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 "SBReproducerPrivate.h"
110b57cec5SDimitry Andric #include "Utils.h"
120b57cec5SDimitry Andric #include "lldb/API/SBAddress.h"
130b57cec5SDimitry Andric #include "lldb/API/SBDebugger.h"
140b57cec5SDimitry Andric #include "lldb/API/SBEvent.h"
150b57cec5SDimitry Andric #include "lldb/API/SBFileSpec.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"
260b57cec5SDimitry Andric #include "lldb/Core/StreamFile.h"
279dba64beSDimitry Andric #include "lldb/Core/StructuredDataImpl.h"
280b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
290b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
300b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
310b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
320b57cec5SDimitry Andric #include "lldb/Target/Process.h"
330b57cec5SDimitry Andric #include "lldb/Target/Queue.h"
340b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h"
350b57cec5SDimitry Andric #include "lldb/Target/SystemRuntime.h"
360b57cec5SDimitry Andric #include "lldb/Target/Target.h"
370b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
380b57cec5SDimitry Andric #include "lldb/Target/ThreadPlan.h"
390b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepInRange.h"
400b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepInstruction.h"
410b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepOut.h"
420b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepRange.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 
530b57cec5SDimitry Andric const char *SBThread::GetBroadcasterClassName() {
540b57cec5SDimitry Andric   LLDB_RECORD_STATIC_METHOD_NO_ARGS(const char *, SBThread,
550b57cec5SDimitry Andric                                     GetBroadcasterClassName);
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   return Thread::GetStaticBroadcasterClass().AsCString();
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric // Constructors
610b57cec5SDimitry Andric SBThread::SBThread() : m_opaque_sp(new ExecutionContextRef()) {
620b57cec5SDimitry Andric   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBThread);
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric SBThread::SBThread(const ThreadSP &lldb_object_sp)
660b57cec5SDimitry Andric     : m_opaque_sp(new ExecutionContextRef(lldb_object_sp)) {
670b57cec5SDimitry Andric   LLDB_RECORD_CONSTRUCTOR(SBThread, (const lldb::ThreadSP &), lldb_object_sp);
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric SBThread::SBThread(const SBThread &rhs) : m_opaque_sp() {
710b57cec5SDimitry Andric   LLDB_RECORD_CONSTRUCTOR(SBThread, (const lldb::SBThread &), rhs);
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   m_opaque_sp = clone(rhs.m_opaque_sp);
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric // Assignment operator
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric const lldb::SBThread &SBThread::operator=(const SBThread &rhs) {
790b57cec5SDimitry Andric   LLDB_RECORD_METHOD(const lldb::SBThread &,
800b57cec5SDimitry Andric                      SBThread, operator=,(const lldb::SBThread &), rhs);
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   if (this != &rhs)
830b57cec5SDimitry Andric     m_opaque_sp = clone(rhs.m_opaque_sp);
840b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(*this);
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric // Destructor
885ffd83dbSDimitry Andric SBThread::~SBThread() = default;
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric lldb::SBQueue SBThread::GetQueue() const {
910b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBQueue, SBThread, GetQueue);
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   SBQueue sb_queue;
940b57cec5SDimitry Andric   QueueSP queue_sp;
950b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
960b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
990b57cec5SDimitry Andric     Process::StopLocker stop_locker;
1000b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1010b57cec5SDimitry Andric       queue_sp = exe_ctx.GetThreadPtr()->GetQueue();
1020b57cec5SDimitry Andric       if (queue_sp) {
1030b57cec5SDimitry Andric         sb_queue.SetQueue(queue_sp);
1040b57cec5SDimitry Andric       }
1050b57cec5SDimitry Andric     }
1060b57cec5SDimitry Andric   }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(sb_queue);
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric bool SBThread::IsValid() const {
1120b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBThread, IsValid);
1130b57cec5SDimitry Andric   return this->operator bool();
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric SBThread::operator bool() const {
1160b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBThread, operator bool);
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
1190b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   Target *target = exe_ctx.GetTargetPtr();
1220b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
1230b57cec5SDimitry Andric   if (target && process) {
1240b57cec5SDimitry Andric     Process::StopLocker stop_locker;
1250b57cec5SDimitry Andric     if (stop_locker.TryLock(&process->GetRunLock()))
1260b57cec5SDimitry Andric       return m_opaque_sp->GetThreadSP().get() != nullptr;
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric   // Without a valid target & process, this thread can't be valid.
1290b57cec5SDimitry Andric   return false;
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric void SBThread::Clear() {
1330b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(void, SBThread, Clear);
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   m_opaque_sp->Clear();
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric StopReason SBThread::GetStopReason() {
1390b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(lldb::StopReason, SBThread, GetStopReason);
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   StopReason reason = eStopReasonInvalid;
1420b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
1430b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
1460b57cec5SDimitry Andric     Process::StopLocker stop_locker;
1470b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1480b57cec5SDimitry Andric       return exe_ctx.GetThreadPtr()->GetStopReason();
1490b57cec5SDimitry Andric     }
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   return reason;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric size_t SBThread::GetStopReasonDataCount() {
1560b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(size_t, SBThread, GetStopReasonDataCount);
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
1590b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
1620b57cec5SDimitry Andric     Process::StopLocker stop_locker;
1630b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1640b57cec5SDimitry Andric       StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
1650b57cec5SDimitry Andric       if (stop_info_sp) {
1660b57cec5SDimitry Andric         StopReason reason = stop_info_sp->GetStopReason();
1670b57cec5SDimitry Andric         switch (reason) {
1680b57cec5SDimitry Andric         case eStopReasonInvalid:
1690b57cec5SDimitry Andric         case eStopReasonNone:
1700b57cec5SDimitry Andric         case eStopReasonTrace:
1710b57cec5SDimitry Andric         case eStopReasonExec:
1720b57cec5SDimitry Andric         case eStopReasonPlanComplete:
1730b57cec5SDimitry Andric         case eStopReasonThreadExiting:
1740b57cec5SDimitry Andric         case eStopReasonInstrumentation:
175fe6060f1SDimitry Andric         case eStopReasonProcessorTrace:
176fe6060f1SDimitry Andric         case eStopReasonVForkDone:
1770b57cec5SDimitry Andric           // There is no data for these stop reasons.
1780b57cec5SDimitry Andric           return 0;
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric         case eStopReasonBreakpoint: {
1810b57cec5SDimitry Andric           break_id_t site_id = stop_info_sp->GetValue();
1820b57cec5SDimitry Andric           lldb::BreakpointSiteSP bp_site_sp(
1830b57cec5SDimitry Andric               exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
1840b57cec5SDimitry Andric                   site_id));
1850b57cec5SDimitry Andric           if (bp_site_sp)
1860b57cec5SDimitry Andric             return bp_site_sp->GetNumberOfOwners() * 2;
1870b57cec5SDimitry Andric           else
1880b57cec5SDimitry Andric             return 0; // Breakpoint must have cleared itself...
1890b57cec5SDimitry Andric         } break;
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric         case eStopReasonWatchpoint:
1920b57cec5SDimitry Andric           return 1;
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric         case eStopReasonSignal:
1950b57cec5SDimitry Andric           return 1;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric         case eStopReasonException:
1980b57cec5SDimitry Andric           return 1;
199fe6060f1SDimitry Andric 
200fe6060f1SDimitry Andric         case eStopReasonFork:
201fe6060f1SDimitry Andric           return 1;
202fe6060f1SDimitry Andric 
203fe6060f1SDimitry Andric         case eStopReasonVFork:
204fe6060f1SDimitry Andric           return 1;
2050b57cec5SDimitry Andric         }
2060b57cec5SDimitry Andric       }
2070b57cec5SDimitry Andric     }
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric   return 0;
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) {
2130b57cec5SDimitry Andric   LLDB_RECORD_METHOD(uint64_t, SBThread, GetStopReasonDataAtIndex, (uint32_t),
2140b57cec5SDimitry Andric                      idx);
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
2170b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
2200b57cec5SDimitry Andric     Process::StopLocker stop_locker;
2210b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
2220b57cec5SDimitry Andric       Thread *thread = exe_ctx.GetThreadPtr();
2230b57cec5SDimitry Andric       StopInfoSP stop_info_sp = thread->GetStopInfo();
2240b57cec5SDimitry Andric       if (stop_info_sp) {
2250b57cec5SDimitry Andric         StopReason reason = stop_info_sp->GetStopReason();
2260b57cec5SDimitry Andric         switch (reason) {
2270b57cec5SDimitry Andric         case eStopReasonInvalid:
2280b57cec5SDimitry Andric         case eStopReasonNone:
2290b57cec5SDimitry Andric         case eStopReasonTrace:
2300b57cec5SDimitry Andric         case eStopReasonExec:
2310b57cec5SDimitry Andric         case eStopReasonPlanComplete:
2320b57cec5SDimitry Andric         case eStopReasonThreadExiting:
2330b57cec5SDimitry Andric         case eStopReasonInstrumentation:
234fe6060f1SDimitry Andric         case eStopReasonProcessorTrace:
235fe6060f1SDimitry Andric         case eStopReasonVForkDone:
2360b57cec5SDimitry Andric           // There is no data for these stop reasons.
2370b57cec5SDimitry Andric           return 0;
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric         case eStopReasonBreakpoint: {
2400b57cec5SDimitry Andric           break_id_t site_id = stop_info_sp->GetValue();
2410b57cec5SDimitry Andric           lldb::BreakpointSiteSP bp_site_sp(
2420b57cec5SDimitry Andric               exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
2430b57cec5SDimitry Andric                   site_id));
2440b57cec5SDimitry Andric           if (bp_site_sp) {
2450b57cec5SDimitry Andric             uint32_t bp_index = idx / 2;
2460b57cec5SDimitry Andric             BreakpointLocationSP bp_loc_sp(
2470b57cec5SDimitry Andric                 bp_site_sp->GetOwnerAtIndex(bp_index));
2480b57cec5SDimitry Andric             if (bp_loc_sp) {
2490b57cec5SDimitry Andric               if (idx & 1) {
2500b57cec5SDimitry Andric                 // Odd idx, return the breakpoint location ID
2510b57cec5SDimitry Andric                 return bp_loc_sp->GetID();
2520b57cec5SDimitry Andric               } else {
2530b57cec5SDimitry Andric                 // Even idx, return the breakpoint ID
2540b57cec5SDimitry Andric                 return bp_loc_sp->GetBreakpoint().GetID();
2550b57cec5SDimitry Andric               }
2560b57cec5SDimitry Andric             }
2570b57cec5SDimitry Andric           }
2580b57cec5SDimitry Andric           return LLDB_INVALID_BREAK_ID;
2590b57cec5SDimitry Andric         } break;
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric         case eStopReasonWatchpoint:
2620b57cec5SDimitry Andric           return stop_info_sp->GetValue();
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric         case eStopReasonSignal:
2650b57cec5SDimitry Andric           return stop_info_sp->GetValue();
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric         case eStopReasonException:
2680b57cec5SDimitry Andric           return stop_info_sp->GetValue();
269fe6060f1SDimitry Andric 
270fe6060f1SDimitry Andric         case eStopReasonFork:
271fe6060f1SDimitry Andric           return stop_info_sp->GetValue();
272fe6060f1SDimitry Andric 
273fe6060f1SDimitry Andric         case eStopReasonVFork:
274fe6060f1SDimitry Andric           return stop_info_sp->GetValue();
2750b57cec5SDimitry Andric         }
2760b57cec5SDimitry Andric       }
2770b57cec5SDimitry Andric     }
2780b57cec5SDimitry Andric   }
2790b57cec5SDimitry Andric   return 0;
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric bool SBThread::GetStopReasonExtendedInfoAsJSON(lldb::SBStream &stream) {
2830b57cec5SDimitry Andric   LLDB_RECORD_METHOD(bool, SBThread, GetStopReasonExtendedInfoAsJSON,
2840b57cec5SDimitry Andric                      (lldb::SBStream &), stream);
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   Stream &strm = stream.ref();
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
2890b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope())
2920b57cec5SDimitry Andric     return false;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
2950b57cec5SDimitry Andric   StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
2960b57cec5SDimitry Andric   if (!info)
2970b57cec5SDimitry Andric     return false;
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   info->Dump(strm);
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   return true;
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric SBThreadCollection
3050b57cec5SDimitry Andric SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) {
3060b57cec5SDimitry Andric   LLDB_RECORD_METHOD(lldb::SBThreadCollection, SBThread,
3070b57cec5SDimitry Andric                      GetStopReasonExtendedBacktraces,
3080b57cec5SDimitry Andric                      (lldb::InstrumentationRuntimeType), type);
3090b57cec5SDimitry Andric 
3105ffd83dbSDimitry Andric   SBThreadCollection threads;
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
3130b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope())
3165ffd83dbSDimitry Andric     return LLDB_RECORD_RESULT(SBThreadCollection());
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   ProcessSP process_sp = exe_ctx.GetProcessSP();
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
3210b57cec5SDimitry Andric   StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
3220b57cec5SDimitry Andric   if (!info)
3230b57cec5SDimitry Andric     return LLDB_RECORD_RESULT(threads);
3240b57cec5SDimitry Andric 
3255ffd83dbSDimitry Andric   threads = process_sp->GetInstrumentationRuntime(type)
3265ffd83dbSDimitry Andric                 ->GetBacktracesFromExtendedStopInfo(info);
3275ffd83dbSDimitry Andric   return LLDB_RECORD_RESULT(threads);
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric size_t SBThread::GetStopDescription(char *dst, size_t dst_len) {
3315ffd83dbSDimitry Andric   LLDB_RECORD_CHAR_PTR_METHOD(size_t, SBThread, GetStopDescription,
3325ffd83dbSDimitry Andric                               (char *, size_t), dst, "", dst_len);
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
3350b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric   if (dst)
3380b57cec5SDimitry Andric     *dst = 0;
3395ffd83dbSDimitry Andric 
3405ffd83dbSDimitry Andric   if (!exe_ctx.HasThreadScope())
3410b57cec5SDimitry Andric     return 0;
3425ffd83dbSDimitry Andric 
3435ffd83dbSDimitry Andric   Process::StopLocker stop_locker;
3445ffd83dbSDimitry Andric   if (!stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
3455ffd83dbSDimitry Andric     return 0;
3465ffd83dbSDimitry Andric 
3475ffd83dbSDimitry Andric   std::string thread_stop_desc = exe_ctx.GetThreadPtr()->GetStopDescription();
3485ffd83dbSDimitry Andric   if (thread_stop_desc.empty())
3495ffd83dbSDimitry Andric     return 0;
3505ffd83dbSDimitry Andric 
3515ffd83dbSDimitry Andric   if (dst)
3525ffd83dbSDimitry Andric     return ::snprintf(dst, dst_len, "%s", thread_stop_desc.c_str()) + 1;
3535ffd83dbSDimitry Andric 
3545ffd83dbSDimitry Andric   // NULL dst passed in, return the length needed to contain the
3555ffd83dbSDimitry Andric   // description.
3565ffd83dbSDimitry Andric   return thread_stop_desc.size() + 1; // Include the NULL byte for size
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric SBValue SBThread::GetStopReturnValue() {
3600b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBValue, SBThread, GetStopReturnValue);
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   ValueObjectSP return_valobj_sp;
3630b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
3640b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
3670b57cec5SDimitry Andric     Process::StopLocker stop_locker;
3680b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
3690b57cec5SDimitry Andric       StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
3700b57cec5SDimitry Andric       if (stop_info_sp) {
3710b57cec5SDimitry Andric         return_valobj_sp = StopInfo::GetReturnValueObject(stop_info_sp);
3720b57cec5SDimitry Andric       }
3730b57cec5SDimitry Andric     }
3740b57cec5SDimitry Andric   }
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(SBValue(return_valobj_sp));
3770b57cec5SDimitry Andric }
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric void SBThread::SetThread(const ThreadSP &lldb_object_sp) {
3800b57cec5SDimitry Andric   m_opaque_sp->SetThreadSP(lldb_object_sp);
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric lldb::tid_t SBThread::GetThreadID() const {
3840b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::tid_t, SBThread, GetThreadID);
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
3870b57cec5SDimitry Andric   if (thread_sp)
3880b57cec5SDimitry Andric     return thread_sp->GetID();
3890b57cec5SDimitry Andric   return LLDB_INVALID_THREAD_ID;
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric uint32_t SBThread::GetIndexID() const {
3930b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBThread, GetIndexID);
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
3960b57cec5SDimitry Andric   if (thread_sp)
3970b57cec5SDimitry Andric     return thread_sp->GetIndexID();
3980b57cec5SDimitry Andric   return LLDB_INVALID_INDEX32;
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric const char *SBThread::GetName() const {
4020b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBThread, GetName);
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   const char *name = nullptr;
4050b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
4060b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
4090b57cec5SDimitry Andric     Process::StopLocker stop_locker;
4100b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
4110b57cec5SDimitry Andric       name = exe_ctx.GetThreadPtr()->GetName();
4120b57cec5SDimitry Andric     }
4130b57cec5SDimitry Andric   }
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric   return name;
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric const char *SBThread::GetQueueName() const {
4190b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBThread, GetQueueName);
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric   const char *name = nullptr;
4220b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
4230b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
4260b57cec5SDimitry Andric     Process::StopLocker stop_locker;
4270b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
4280b57cec5SDimitry Andric       name = exe_ctx.GetThreadPtr()->GetQueueName();
4290b57cec5SDimitry Andric     }
4300b57cec5SDimitry Andric   }
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   return name;
4330b57cec5SDimitry Andric }
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric lldb::queue_id_t SBThread::GetQueueID() const {
4360b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::queue_id_t, SBThread, GetQueueID);
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric   queue_id_t id = LLDB_INVALID_QUEUE_ID;
4390b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
4400b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
4430b57cec5SDimitry Andric     Process::StopLocker stop_locker;
4440b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
4450b57cec5SDimitry Andric       id = exe_ctx.GetThreadPtr()->GetQueueID();
4460b57cec5SDimitry Andric     }
4470b57cec5SDimitry Andric   }
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   return id;
4500b57cec5SDimitry Andric }
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) {
4530b57cec5SDimitry Andric   LLDB_RECORD_METHOD(bool, SBThread, GetInfoItemByPathAsString,
4540b57cec5SDimitry Andric                      (const char *, lldb::SBStream &), path, strm);
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric   bool success = false;
4570b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
4580b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
4610b57cec5SDimitry Andric     Process::StopLocker stop_locker;
4620b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
4630b57cec5SDimitry Andric       Thread *thread = exe_ctx.GetThreadPtr();
4640b57cec5SDimitry Andric       StructuredData::ObjectSP info_root_sp = thread->GetExtendedInfo();
4650b57cec5SDimitry Andric       if (info_root_sp) {
4660b57cec5SDimitry Andric         StructuredData::ObjectSP node =
4670b57cec5SDimitry Andric             info_root_sp->GetObjectForDotSeparatedPath(path);
4680b57cec5SDimitry Andric         if (node) {
4690b57cec5SDimitry Andric           if (node->GetType() == eStructuredDataTypeString) {
4700b57cec5SDimitry Andric             strm.Printf("%s", node->GetAsString()->GetValue().str().c_str());
4710b57cec5SDimitry Andric             success = true;
4720b57cec5SDimitry Andric           }
4730b57cec5SDimitry Andric           if (node->GetType() == eStructuredDataTypeInteger) {
4740b57cec5SDimitry Andric             strm.Printf("0x%" PRIx64, node->GetAsInteger()->GetValue());
4750b57cec5SDimitry Andric             success = true;
4760b57cec5SDimitry Andric           }
4770b57cec5SDimitry Andric           if (node->GetType() == eStructuredDataTypeFloat) {
4780b57cec5SDimitry Andric             strm.Printf("0x%f", node->GetAsFloat()->GetValue());
4790b57cec5SDimitry Andric             success = true;
4800b57cec5SDimitry Andric           }
4810b57cec5SDimitry Andric           if (node->GetType() == eStructuredDataTypeBoolean) {
4820b57cec5SDimitry Andric             if (node->GetAsBoolean()->GetValue())
4830b57cec5SDimitry Andric               strm.Printf("true");
4840b57cec5SDimitry Andric             else
4850b57cec5SDimitry Andric               strm.Printf("false");
4860b57cec5SDimitry Andric             success = true;
4870b57cec5SDimitry Andric           }
4880b57cec5SDimitry Andric           if (node->GetType() == eStructuredDataTypeNull) {
4890b57cec5SDimitry Andric             strm.Printf("null");
4900b57cec5SDimitry Andric             success = true;
4910b57cec5SDimitry Andric           }
4920b57cec5SDimitry Andric         }
4930b57cec5SDimitry Andric       }
4940b57cec5SDimitry Andric     }
4950b57cec5SDimitry Andric   }
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   return success;
4980b57cec5SDimitry Andric }
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx,
5010b57cec5SDimitry Andric                                 ThreadPlan *new_plan) {
5020b57cec5SDimitry Andric   SBError sb_error;
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
5050b57cec5SDimitry Andric   if (!process) {
5060b57cec5SDimitry Andric     sb_error.SetErrorString("No process in SBThread::ResumeNewPlan");
5070b57cec5SDimitry Andric     return sb_error;
5080b57cec5SDimitry Andric   }
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
5110b57cec5SDimitry Andric   if (!thread) {
5120b57cec5SDimitry Andric     sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan");
5130b57cec5SDimitry Andric     return sb_error;
5140b57cec5SDimitry Andric   }
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric   // User level plans should be Master Plans so they can be interrupted, other
5170b57cec5SDimitry Andric   // plans executed, and then a "continue" will resume the plan.
5180b57cec5SDimitry Andric   if (new_plan != nullptr) {
5190b57cec5SDimitry Andric     new_plan->SetIsMasterPlan(true);
5200b57cec5SDimitry Andric     new_plan->SetOkayToDiscard(false);
5210b57cec5SDimitry Andric   }
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric   // Why do we need to set the current thread by ID here???
5240b57cec5SDimitry Andric   process->GetThreadList().SetSelectedThreadByID(thread->GetID());
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric   if (process->GetTarget().GetDebugger().GetAsyncExecution())
5270b57cec5SDimitry Andric     sb_error.ref() = process->Resume();
5280b57cec5SDimitry Andric   else
5290b57cec5SDimitry Andric     sb_error.ref() = process->ResumeSynchronous(nullptr);
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric   return sb_error;
5320b57cec5SDimitry Andric }
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric void SBThread::StepOver(lldb::RunMode stop_other_threads) {
5350b57cec5SDimitry Andric   LLDB_RECORD_METHOD(void, SBThread, StepOver, (lldb::RunMode),
5360b57cec5SDimitry Andric                      stop_other_threads);
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric   SBError error; // Ignored
5390b57cec5SDimitry Andric   StepOver(stop_other_threads, error);
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) {
5430b57cec5SDimitry Andric   LLDB_RECORD_METHOD(void, SBThread, StepOver, (lldb::RunMode, lldb::SBError &),
5440b57cec5SDimitry Andric                      stop_other_threads, error);
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
5470b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
5500b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
5510b57cec5SDimitry Andric     return;
5520b57cec5SDimitry Andric   }
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
5550b57cec5SDimitry Andric   bool abort_other_plans = false;
5560b57cec5SDimitry Andric   StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric   Status new_plan_status;
5590b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp;
5600b57cec5SDimitry Andric   if (frame_sp) {
5610b57cec5SDimitry Andric     if (frame_sp->HasDebugInformation()) {
5620b57cec5SDimitry Andric       const LazyBool avoid_no_debug = eLazyBoolCalculate;
5630b57cec5SDimitry Andric       SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
5640b57cec5SDimitry Andric       new_plan_sp = thread->QueueThreadPlanForStepOverRange(
5650b57cec5SDimitry Andric           abort_other_plans, sc.line_entry, sc, stop_other_threads,
5660b57cec5SDimitry Andric           new_plan_status, avoid_no_debug);
5670b57cec5SDimitry Andric     } else {
5680b57cec5SDimitry Andric       new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
5690b57cec5SDimitry Andric           true, abort_other_plans, stop_other_threads, new_plan_status);
5700b57cec5SDimitry Andric     }
5710b57cec5SDimitry Andric   }
5720b57cec5SDimitry Andric   error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
5730b57cec5SDimitry Andric }
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric void SBThread::StepInto(lldb::RunMode stop_other_threads) {
5760b57cec5SDimitry Andric   LLDB_RECORD_METHOD(void, SBThread, StepInto, (lldb::RunMode),
5770b57cec5SDimitry Andric                      stop_other_threads);
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric   StepInto(nullptr, stop_other_threads);
5800b57cec5SDimitry Andric }
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric void SBThread::StepInto(const char *target_name,
5830b57cec5SDimitry Andric                         lldb::RunMode stop_other_threads) {
5840b57cec5SDimitry Andric   LLDB_RECORD_METHOD(void, SBThread, StepInto, (const char *, lldb::RunMode),
5850b57cec5SDimitry Andric                      target_name, stop_other_threads);
5860b57cec5SDimitry Andric 
5870b57cec5SDimitry Andric   SBError error; // Ignored
5880b57cec5SDimitry Andric   StepInto(target_name, LLDB_INVALID_LINE_NUMBER, error, stop_other_threads);
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric void SBThread::StepInto(const char *target_name, uint32_t end_line,
5920b57cec5SDimitry Andric                         SBError &error, lldb::RunMode stop_other_threads) {
5930b57cec5SDimitry Andric   LLDB_RECORD_METHOD(void, SBThread, StepInto,
5940b57cec5SDimitry Andric                      (const char *, uint32_t, lldb::SBError &, lldb::RunMode),
5950b57cec5SDimitry Andric                      target_name, end_line, error, stop_other_threads);
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
5990b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
6020b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
6030b57cec5SDimitry Andric     return;
6040b57cec5SDimitry Andric   }
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric   bool abort_other_plans = false;
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
6090b57cec5SDimitry Andric   StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
6100b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp;
6110b57cec5SDimitry Andric   Status new_plan_status;
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric   if (frame_sp && frame_sp->HasDebugInformation()) {
6140b57cec5SDimitry Andric     SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
6150b57cec5SDimitry Andric     AddressRange range;
6160b57cec5SDimitry Andric     if (end_line == LLDB_INVALID_LINE_NUMBER)
6170b57cec5SDimitry Andric       range = sc.line_entry.range;
6180b57cec5SDimitry Andric     else {
6190b57cec5SDimitry Andric       if (!sc.GetAddressRangeFromHereToEndLine(end_line, range, error.ref()))
6200b57cec5SDimitry Andric         return;
6210b57cec5SDimitry Andric     }
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric     const LazyBool step_out_avoids_code_without_debug_info =
6240b57cec5SDimitry Andric         eLazyBoolCalculate;
6250b57cec5SDimitry Andric     const LazyBool step_in_avoids_code_without_debug_info =
6260b57cec5SDimitry Andric         eLazyBoolCalculate;
6270b57cec5SDimitry Andric     new_plan_sp = thread->QueueThreadPlanForStepInRange(
6280b57cec5SDimitry Andric         abort_other_plans, range, sc, target_name, stop_other_threads,
6290b57cec5SDimitry Andric         new_plan_status, step_in_avoids_code_without_debug_info,
6300b57cec5SDimitry Andric         step_out_avoids_code_without_debug_info);
6310b57cec5SDimitry Andric   } else {
6320b57cec5SDimitry Andric     new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
6330b57cec5SDimitry Andric         false, abort_other_plans, stop_other_threads, new_plan_status);
6340b57cec5SDimitry Andric   }
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   if (new_plan_status.Success())
6370b57cec5SDimitry Andric     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
6380b57cec5SDimitry Andric   else
6390b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
6400b57cec5SDimitry Andric }
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric void SBThread::StepOut() {
6430b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(void, SBThread, StepOut);
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric   SBError error; // Ignored
6460b57cec5SDimitry Andric   StepOut(error);
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric void SBThread::StepOut(SBError &error) {
6500b57cec5SDimitry Andric   LLDB_RECORD_METHOD(void, SBThread, StepOut, (lldb::SBError &), error);
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
6530b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
6560b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
6570b57cec5SDimitry Andric     return;
6580b57cec5SDimitry Andric   }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric   bool abort_other_plans = false;
6610b57cec5SDimitry Andric   bool stop_other_threads = false;
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   const LazyBool avoid_no_debug = eLazyBoolCalculate;
6660b57cec5SDimitry Andric   Status new_plan_status;
6670b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
6680b57cec5SDimitry Andric       abort_other_plans, nullptr, false, stop_other_threads, eVoteYes,
6690b57cec5SDimitry Andric       eVoteNoOpinion, 0, new_plan_status, avoid_no_debug));
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric   if (new_plan_status.Success())
6720b57cec5SDimitry Andric     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
6730b57cec5SDimitry Andric   else
6740b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
6750b57cec5SDimitry Andric }
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric void SBThread::StepOutOfFrame(SBFrame &sb_frame) {
6780b57cec5SDimitry Andric   LLDB_RECORD_METHOD(void, SBThread, StepOutOfFrame, (lldb::SBFrame &),
6790b57cec5SDimitry Andric                      sb_frame);
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric   SBError error; // Ignored
6820b57cec5SDimitry Andric   StepOutOfFrame(sb_frame, error);
6830b57cec5SDimitry Andric }
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) {
6860b57cec5SDimitry Andric   LLDB_RECORD_METHOD(void, SBThread, StepOutOfFrame,
6870b57cec5SDimitry Andric                      (lldb::SBFrame &, lldb::SBError &), sb_frame, error);
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
6910b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric   if (!sb_frame.IsValid()) {
6940b57cec5SDimitry Andric     error.SetErrorString("passed invalid SBFrame object");
6950b57cec5SDimitry Andric     return;
6960b57cec5SDimitry Andric   }
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric   StackFrameSP frame_sp(sb_frame.GetFrameSP());
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
7010b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
7020b57cec5SDimitry Andric     return;
7030b57cec5SDimitry Andric   }
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   bool abort_other_plans = false;
7060b57cec5SDimitry Andric   bool stop_other_threads = false;
7070b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
7080b57cec5SDimitry Andric   if (sb_frame.GetThread().GetThreadID() != thread->GetID()) {
7090b57cec5SDimitry Andric     error.SetErrorString("passed a frame from another thread");
7100b57cec5SDimitry Andric     return;
7110b57cec5SDimitry Andric   }
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric   Status new_plan_status;
7140b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
7150b57cec5SDimitry Andric       abort_other_plans, nullptr, false, stop_other_threads, eVoteYes,
7160b57cec5SDimitry Andric       eVoteNoOpinion, frame_sp->GetFrameIndex(), new_plan_status));
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric   if (new_plan_status.Success())
7190b57cec5SDimitry Andric     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
7200b57cec5SDimitry Andric   else
7210b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
7220b57cec5SDimitry Andric }
7230b57cec5SDimitry Andric 
7240b57cec5SDimitry Andric void SBThread::StepInstruction(bool step_over) {
7250b57cec5SDimitry Andric   LLDB_RECORD_METHOD(void, SBThread, StepInstruction, (bool), step_over);
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric   SBError error; // Ignored
7280b57cec5SDimitry Andric   StepInstruction(step_over, error);
7290b57cec5SDimitry Andric }
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric void SBThread::StepInstruction(bool step_over, SBError &error) {
7320b57cec5SDimitry Andric   LLDB_RECORD_METHOD(void, SBThread, StepInstruction, (bool, lldb::SBError &),
7330b57cec5SDimitry Andric                      step_over, error);
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
7360b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
7390b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
7400b57cec5SDimitry Andric     return;
7410b57cec5SDimitry Andric   }
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
7440b57cec5SDimitry Andric   Status new_plan_status;
7450b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepSingleInstruction(
7460b57cec5SDimitry Andric       step_over, true, true, new_plan_status));
7470b57cec5SDimitry Andric 
7480b57cec5SDimitry Andric   if (new_plan_status.Success())
7490b57cec5SDimitry Andric     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
7500b57cec5SDimitry Andric   else
7510b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
7520b57cec5SDimitry Andric }
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric void SBThread::RunToAddress(lldb::addr_t addr) {
7550b57cec5SDimitry Andric   LLDB_RECORD_METHOD(void, SBThread, RunToAddress, (lldb::addr_t), addr);
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric   SBError error; // Ignored
7580b57cec5SDimitry Andric   RunToAddress(addr, error);
7590b57cec5SDimitry Andric }
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) {
7620b57cec5SDimitry Andric   LLDB_RECORD_METHOD(void, SBThread, RunToAddress,
7630b57cec5SDimitry Andric                      (lldb::addr_t, lldb::SBError &), addr, error);
7640b57cec5SDimitry Andric 
7650b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
7660b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
7690b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
7700b57cec5SDimitry Andric     return;
7710b57cec5SDimitry Andric   }
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric   bool abort_other_plans = false;
7740b57cec5SDimitry Andric   bool stop_other_threads = true;
7750b57cec5SDimitry Andric 
7760b57cec5SDimitry Andric   Address target_addr(addr);
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   Status new_plan_status;
7810b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
7820b57cec5SDimitry Andric       abort_other_plans, target_addr, stop_other_threads, new_plan_status));
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric   if (new_plan_status.Success())
7850b57cec5SDimitry Andric     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
7860b57cec5SDimitry Andric   else
7870b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
7880b57cec5SDimitry Andric }
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
7910b57cec5SDimitry Andric                                 lldb::SBFileSpec &sb_file_spec, uint32_t line) {
7920b57cec5SDimitry Andric   LLDB_RECORD_METHOD(lldb::SBError, SBThread, StepOverUntil,
7930b57cec5SDimitry Andric                      (lldb::SBFrame &, lldb::SBFileSpec &, uint32_t), sb_frame,
7940b57cec5SDimitry Andric                      sb_file_spec, line);
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric   SBError sb_error;
7970b57cec5SDimitry Andric   char path[PATH_MAX];
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
8000b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric   StackFrameSP frame_sp(sb_frame.GetFrameSP());
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
8050b57cec5SDimitry Andric     Target *target = exe_ctx.GetTargetPtr();
8060b57cec5SDimitry Andric     Thread *thread = exe_ctx.GetThreadPtr();
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric     if (line == 0) {
8090b57cec5SDimitry Andric       sb_error.SetErrorString("invalid line argument");
8100b57cec5SDimitry Andric       return LLDB_RECORD_RESULT(sb_error);
8110b57cec5SDimitry Andric     }
8120b57cec5SDimitry Andric 
8130b57cec5SDimitry Andric     if (!frame_sp) {
8140b57cec5SDimitry Andric       frame_sp = thread->GetSelectedFrame();
8150b57cec5SDimitry Andric       if (!frame_sp)
8160b57cec5SDimitry Andric         frame_sp = thread->GetStackFrameAtIndex(0);
8170b57cec5SDimitry Andric     }
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric     SymbolContext frame_sc;
8200b57cec5SDimitry Andric     if (!frame_sp) {
8210b57cec5SDimitry Andric       sb_error.SetErrorString("no valid frames in thread to step");
8220b57cec5SDimitry Andric       return LLDB_RECORD_RESULT(sb_error);
8230b57cec5SDimitry Andric     }
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric     // If we have a frame, get its line
8260b57cec5SDimitry Andric     frame_sc = frame_sp->GetSymbolContext(
8270b57cec5SDimitry Andric         eSymbolContextCompUnit | eSymbolContextFunction |
8280b57cec5SDimitry Andric         eSymbolContextLineEntry | eSymbolContextSymbol);
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric     if (frame_sc.comp_unit == nullptr) {
8310b57cec5SDimitry Andric       sb_error.SetErrorStringWithFormat(
8320b57cec5SDimitry Andric           "frame %u doesn't have debug information", frame_sp->GetFrameIndex());
8330b57cec5SDimitry Andric       return LLDB_RECORD_RESULT(sb_error);
8340b57cec5SDimitry Andric     }
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric     FileSpec step_file_spec;
8370b57cec5SDimitry Andric     if (sb_file_spec.IsValid()) {
8380b57cec5SDimitry Andric       // The file spec passed in was valid, so use it
8390b57cec5SDimitry Andric       step_file_spec = sb_file_spec.ref();
8400b57cec5SDimitry Andric     } else {
8410b57cec5SDimitry Andric       if (frame_sc.line_entry.IsValid())
8420b57cec5SDimitry Andric         step_file_spec = frame_sc.line_entry.file;
8430b57cec5SDimitry Andric       else {
8440b57cec5SDimitry Andric         sb_error.SetErrorString("invalid file argument or no file for frame");
8450b57cec5SDimitry Andric         return LLDB_RECORD_RESULT(sb_error);
8460b57cec5SDimitry Andric       }
8470b57cec5SDimitry Andric     }
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric     // Grab the current function, then we will make sure the "until" address is
8500b57cec5SDimitry Andric     // within the function.  We discard addresses that are out of the current
8510b57cec5SDimitry Andric     // function, and then if there are no addresses remaining, give an
8520b57cec5SDimitry Andric     // appropriate error message.
8530b57cec5SDimitry Andric 
8540b57cec5SDimitry Andric     bool all_in_function = true;
8550b57cec5SDimitry Andric     AddressRange fun_range = frame_sc.function->GetAddressRange();
8560b57cec5SDimitry Andric 
8570b57cec5SDimitry Andric     std::vector<addr_t> step_over_until_addrs;
8580b57cec5SDimitry Andric     const bool abort_other_plans = false;
8590b57cec5SDimitry Andric     const bool stop_other_threads = false;
860fe6060f1SDimitry Andric     // TODO: Handle SourceLocationSpec column information
861fe6060f1SDimitry Andric     SourceLocationSpec location_spec(
862fe6060f1SDimitry Andric         step_file_spec, line, /*column=*/llvm::None, /*check_inlines=*/true,
863fe6060f1SDimitry Andric         /*exact_match=*/false);
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric     SymbolContextList sc_list;
866fe6060f1SDimitry Andric     frame_sc.comp_unit->ResolveSymbolContext(location_spec,
867480093f4SDimitry Andric                                              eSymbolContextLineEntry, sc_list);
868480093f4SDimitry Andric     const uint32_t num_matches = sc_list.GetSize();
8690b57cec5SDimitry Andric     if (num_matches > 0) {
8700b57cec5SDimitry Andric       SymbolContext sc;
8710b57cec5SDimitry Andric       for (uint32_t i = 0; i < num_matches; ++i) {
8720b57cec5SDimitry Andric         if (sc_list.GetContextAtIndex(i, sc)) {
8730b57cec5SDimitry Andric           addr_t step_addr =
8740b57cec5SDimitry Andric               sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
8750b57cec5SDimitry Andric           if (step_addr != LLDB_INVALID_ADDRESS) {
8760b57cec5SDimitry Andric             if (fun_range.ContainsLoadAddress(step_addr, target))
8770b57cec5SDimitry Andric               step_over_until_addrs.push_back(step_addr);
8780b57cec5SDimitry Andric             else
8790b57cec5SDimitry Andric               all_in_function = false;
8800b57cec5SDimitry Andric           }
8810b57cec5SDimitry Andric         }
8820b57cec5SDimitry Andric       }
8830b57cec5SDimitry Andric     }
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric     if (step_over_until_addrs.empty()) {
8860b57cec5SDimitry Andric       if (all_in_function) {
8870b57cec5SDimitry Andric         step_file_spec.GetPath(path, sizeof(path));
8880b57cec5SDimitry Andric         sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path,
8890b57cec5SDimitry Andric                                           line);
8900b57cec5SDimitry Andric       } else
8910b57cec5SDimitry Andric         sb_error.SetErrorString("step until target not in current function");
8920b57cec5SDimitry Andric     } else {
8930b57cec5SDimitry Andric       Status new_plan_status;
8940b57cec5SDimitry Andric       ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepUntil(
8950b57cec5SDimitry Andric           abort_other_plans, &step_over_until_addrs[0],
8960b57cec5SDimitry Andric           step_over_until_addrs.size(), stop_other_threads,
8970b57cec5SDimitry Andric           frame_sp->GetFrameIndex(), new_plan_status));
8980b57cec5SDimitry Andric 
8990b57cec5SDimitry Andric       if (new_plan_status.Success())
9000b57cec5SDimitry Andric         sb_error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
9010b57cec5SDimitry Andric       else
9020b57cec5SDimitry Andric         sb_error.SetErrorString(new_plan_status.AsCString());
9030b57cec5SDimitry Andric     }
9040b57cec5SDimitry Andric   } else {
9050b57cec5SDimitry Andric     sb_error.SetErrorString("this SBThread object is invalid");
9060b57cec5SDimitry Andric   }
9070b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(sb_error);
9080b57cec5SDimitry Andric }
9090b57cec5SDimitry Andric 
9100b57cec5SDimitry Andric SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name) {
9110b57cec5SDimitry Andric   LLDB_RECORD_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan,
9120b57cec5SDimitry Andric                      (const char *), script_class_name);
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(
9150b57cec5SDimitry Andric       StepUsingScriptedThreadPlan(script_class_name, true));
9160b57cec5SDimitry Andric }
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
9190b57cec5SDimitry Andric                                             bool resume_immediately) {
9200b57cec5SDimitry Andric   LLDB_RECORD_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan,
9210b57cec5SDimitry Andric                      (const char *, bool), script_class_name,
9220b57cec5SDimitry Andric                      resume_immediately);
9230b57cec5SDimitry Andric 
9249dba64beSDimitry Andric   lldb::SBStructuredData no_data;
9255ffd83dbSDimitry Andric   return LLDB_RECORD_RESULT(StepUsingScriptedThreadPlan(
9265ffd83dbSDimitry Andric       script_class_name, no_data, resume_immediately));
9279dba64beSDimitry Andric }
9289dba64beSDimitry Andric 
9299dba64beSDimitry Andric SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
9309dba64beSDimitry Andric                                               SBStructuredData &args_data,
9319dba64beSDimitry Andric                                               bool resume_immediately) {
9329dba64beSDimitry Andric   LLDB_RECORD_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan,
9339dba64beSDimitry Andric                      (const char *, lldb::SBStructuredData &, bool),
9345ffd83dbSDimitry Andric                      script_class_name, args_data, resume_immediately);
9359dba64beSDimitry Andric 
9360b57cec5SDimitry Andric   SBError error;
9370b57cec5SDimitry Andric 
9380b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
9390b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
9420b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
9430b57cec5SDimitry Andric     return LLDB_RECORD_RESULT(error);
9440b57cec5SDimitry Andric   }
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
9470b57cec5SDimitry Andric   Status new_plan_status;
9489dba64beSDimitry Andric   StructuredData::ObjectSP obj_sp = args_data.m_impl_up->GetObjectSP();
9499dba64beSDimitry Andric 
9500b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp = thread->QueueThreadPlanForStepScripted(
9519dba64beSDimitry Andric       false, script_class_name, obj_sp, false, new_plan_status);
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric   if (new_plan_status.Fail()) {
9540b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
9550b57cec5SDimitry Andric     return LLDB_RECORD_RESULT(error);
9560b57cec5SDimitry Andric   }
9570b57cec5SDimitry Andric 
9580b57cec5SDimitry Andric   if (!resume_immediately)
9590b57cec5SDimitry Andric     return LLDB_RECORD_RESULT(error);
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric   if (new_plan_status.Success())
9620b57cec5SDimitry Andric     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
9630b57cec5SDimitry Andric   else
9640b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
9650b57cec5SDimitry Andric 
9660b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(error);
9670b57cec5SDimitry Andric }
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) {
9700b57cec5SDimitry Andric   LLDB_RECORD_METHOD(lldb::SBError, SBThread, JumpToLine,
9710b57cec5SDimitry Andric                      (lldb::SBFileSpec &, uint32_t), file_spec, line);
9720b57cec5SDimitry Andric 
9730b57cec5SDimitry Andric   SBError sb_error;
9740b57cec5SDimitry Andric 
9750b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
9760b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
9770b57cec5SDimitry Andric 
9780b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
9790b57cec5SDimitry Andric     sb_error.SetErrorString("this SBThread object is invalid");
9800b57cec5SDimitry Andric     return LLDB_RECORD_RESULT(sb_error);
9810b57cec5SDimitry Andric   }
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
9840b57cec5SDimitry Andric 
985480093f4SDimitry Andric   Status err = thread->JumpToLine(file_spec.ref(), line, true);
9860b57cec5SDimitry Andric   sb_error.SetError(err);
9870b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(sb_error);
9880b57cec5SDimitry Andric }
9890b57cec5SDimitry Andric 
9900b57cec5SDimitry Andric SBError SBThread::ReturnFromFrame(SBFrame &frame, SBValue &return_value) {
9910b57cec5SDimitry Andric   LLDB_RECORD_METHOD(lldb::SBError, SBThread, ReturnFromFrame,
9920b57cec5SDimitry Andric                      (lldb::SBFrame &, lldb::SBValue &), frame, return_value);
9930b57cec5SDimitry Andric 
9940b57cec5SDimitry Andric   SBError sb_error;
9950b57cec5SDimitry Andric 
9960b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
9970b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
9980b57cec5SDimitry Andric 
9990b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
10000b57cec5SDimitry Andric     Thread *thread = exe_ctx.GetThreadPtr();
10010b57cec5SDimitry Andric     sb_error.SetError(
10020b57cec5SDimitry Andric         thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
10030b57cec5SDimitry Andric   }
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(sb_error);
10060b57cec5SDimitry Andric }
10070b57cec5SDimitry Andric 
10080b57cec5SDimitry Andric SBError SBThread::UnwindInnermostExpression() {
10090b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBError, SBThread,
10100b57cec5SDimitry Andric                              UnwindInnermostExpression);
10110b57cec5SDimitry Andric 
10120b57cec5SDimitry Andric   SBError sb_error;
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
10150b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
10180b57cec5SDimitry Andric     Thread *thread = exe_ctx.GetThreadPtr();
10190b57cec5SDimitry Andric     sb_error.SetError(thread->UnwindInnermostExpression());
10200b57cec5SDimitry Andric     if (sb_error.Success())
10210b57cec5SDimitry Andric       thread->SetSelectedFrameByIndex(0, false);
10220b57cec5SDimitry Andric   }
10230b57cec5SDimitry Andric 
10240b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(sb_error);
10250b57cec5SDimitry Andric }
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric bool SBThread::Suspend() {
10280b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(bool, SBThread, Suspend);
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric   SBError error; // Ignored
10310b57cec5SDimitry Andric   return Suspend(error);
10320b57cec5SDimitry Andric }
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric bool SBThread::Suspend(SBError &error) {
10350b57cec5SDimitry Andric   LLDB_RECORD_METHOD(bool, SBThread, Suspend, (lldb::SBError &), error);
10360b57cec5SDimitry Andric 
10370b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
10380b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric   bool result = false;
10410b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
10420b57cec5SDimitry Andric     Process::StopLocker stop_locker;
10430b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
10440b57cec5SDimitry Andric       exe_ctx.GetThreadPtr()->SetResumeState(eStateSuspended);
10450b57cec5SDimitry Andric       result = true;
10460b57cec5SDimitry Andric     } else {
10470b57cec5SDimitry Andric       error.SetErrorString("process is running");
10480b57cec5SDimitry Andric     }
10490b57cec5SDimitry Andric   } else
10500b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
10510b57cec5SDimitry Andric   return result;
10520b57cec5SDimitry Andric }
10530b57cec5SDimitry Andric 
10540b57cec5SDimitry Andric bool SBThread::Resume() {
10550b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(bool, SBThread, Resume);
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric   SBError error; // Ignored
10580b57cec5SDimitry Andric   return Resume(error);
10590b57cec5SDimitry Andric }
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric bool SBThread::Resume(SBError &error) {
10620b57cec5SDimitry Andric   LLDB_RECORD_METHOD(bool, SBThread, Resume, (lldb::SBError &), error);
10630b57cec5SDimitry Andric 
10640b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
10650b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10660b57cec5SDimitry Andric 
10670b57cec5SDimitry Andric   bool result = false;
10680b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
10690b57cec5SDimitry Andric     Process::StopLocker stop_locker;
10700b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
10710b57cec5SDimitry Andric       const bool override_suspend = true;
10720b57cec5SDimitry Andric       exe_ctx.GetThreadPtr()->SetResumeState(eStateRunning, override_suspend);
10730b57cec5SDimitry Andric       result = true;
10740b57cec5SDimitry Andric     } else {
10750b57cec5SDimitry Andric       error.SetErrorString("process is running");
10760b57cec5SDimitry Andric     }
10770b57cec5SDimitry Andric   } else
10780b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
10790b57cec5SDimitry Andric   return result;
10800b57cec5SDimitry Andric }
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric bool SBThread::IsSuspended() {
10830b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(bool, SBThread, IsSuspended);
10840b57cec5SDimitry Andric 
10850b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
10860b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope())
10890b57cec5SDimitry Andric     return exe_ctx.GetThreadPtr()->GetResumeState() == eStateSuspended;
10900b57cec5SDimitry Andric   return false;
10910b57cec5SDimitry Andric }
10920b57cec5SDimitry Andric 
10930b57cec5SDimitry Andric bool SBThread::IsStopped() {
10940b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(bool, SBThread, IsStopped);
10950b57cec5SDimitry Andric 
10960b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
10970b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope())
11000b57cec5SDimitry Andric     return StateIsStoppedState(exe_ctx.GetThreadPtr()->GetState(), true);
11010b57cec5SDimitry Andric   return false;
11020b57cec5SDimitry Andric }
11030b57cec5SDimitry Andric 
11040b57cec5SDimitry Andric SBProcess SBThread::GetProcess() {
11050b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBProcess, SBThread, GetProcess);
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   SBProcess sb_process;
11080b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
11090b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
11100b57cec5SDimitry Andric 
11110b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
11120b57cec5SDimitry Andric     // Have to go up to the target so we can get a shared pointer to our
11130b57cec5SDimitry Andric     // process...
11140b57cec5SDimitry Andric     sb_process.SetSP(exe_ctx.GetProcessSP());
11150b57cec5SDimitry Andric   }
11160b57cec5SDimitry Andric 
11170b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(sb_process);
11180b57cec5SDimitry Andric }
11190b57cec5SDimitry Andric 
11200b57cec5SDimitry Andric uint32_t SBThread::GetNumFrames() {
11210b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBThread, GetNumFrames);
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric   uint32_t num_frames = 0;
11240b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
11250b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
11260b57cec5SDimitry Andric 
11270b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
11280b57cec5SDimitry Andric     Process::StopLocker stop_locker;
11290b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
11300b57cec5SDimitry Andric       num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount();
11310b57cec5SDimitry Andric     }
11320b57cec5SDimitry Andric   }
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric   return num_frames;
11350b57cec5SDimitry Andric }
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric SBFrame SBThread::GetFrameAtIndex(uint32_t idx) {
11380b57cec5SDimitry Andric   LLDB_RECORD_METHOD(lldb::SBFrame, SBThread, GetFrameAtIndex, (uint32_t), idx);
11390b57cec5SDimitry Andric 
11400b57cec5SDimitry Andric   SBFrame sb_frame;
11410b57cec5SDimitry Andric   StackFrameSP frame_sp;
11420b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
11430b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
11440b57cec5SDimitry Andric 
11450b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
11460b57cec5SDimitry Andric     Process::StopLocker stop_locker;
11470b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
11480b57cec5SDimitry Andric       frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx);
11490b57cec5SDimitry Andric       sb_frame.SetFrameSP(frame_sp);
11500b57cec5SDimitry Andric     }
11510b57cec5SDimitry Andric   }
11520b57cec5SDimitry Andric 
11530b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(sb_frame);
11540b57cec5SDimitry Andric }
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric lldb::SBFrame SBThread::GetSelectedFrame() {
11570b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBFrame, SBThread, GetSelectedFrame);
11580b57cec5SDimitry Andric 
11590b57cec5SDimitry Andric   SBFrame sb_frame;
11600b57cec5SDimitry Andric   StackFrameSP frame_sp;
11610b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
11620b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
11630b57cec5SDimitry Andric 
11640b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
11650b57cec5SDimitry Andric     Process::StopLocker stop_locker;
11660b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
11670b57cec5SDimitry Andric       frame_sp = exe_ctx.GetThreadPtr()->GetSelectedFrame();
11680b57cec5SDimitry Andric       sb_frame.SetFrameSP(frame_sp);
11690b57cec5SDimitry Andric     }
11700b57cec5SDimitry Andric   }
11710b57cec5SDimitry Andric 
11720b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(sb_frame);
11730b57cec5SDimitry Andric }
11740b57cec5SDimitry Andric 
11750b57cec5SDimitry Andric lldb::SBFrame SBThread::SetSelectedFrame(uint32_t idx) {
11760b57cec5SDimitry Andric   LLDB_RECORD_METHOD(lldb::SBFrame, SBThread, SetSelectedFrame, (uint32_t),
11770b57cec5SDimitry Andric                      idx);
11780b57cec5SDimitry Andric 
11790b57cec5SDimitry Andric   SBFrame sb_frame;
11800b57cec5SDimitry Andric   StackFrameSP frame_sp;
11810b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
11820b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
11850b57cec5SDimitry Andric     Process::StopLocker stop_locker;
11860b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
11870b57cec5SDimitry Andric       Thread *thread = exe_ctx.GetThreadPtr();
11880b57cec5SDimitry Andric       frame_sp = thread->GetStackFrameAtIndex(idx);
11890b57cec5SDimitry Andric       if (frame_sp) {
11900b57cec5SDimitry Andric         thread->SetSelectedFrame(frame_sp.get());
11910b57cec5SDimitry Andric         sb_frame.SetFrameSP(frame_sp);
11920b57cec5SDimitry Andric       }
11930b57cec5SDimitry Andric     }
11940b57cec5SDimitry Andric   }
11950b57cec5SDimitry Andric 
11960b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(sb_frame);
11970b57cec5SDimitry Andric }
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric bool SBThread::EventIsThreadEvent(const SBEvent &event) {
12000b57cec5SDimitry Andric   LLDB_RECORD_STATIC_METHOD(bool, SBThread, EventIsThreadEvent,
12010b57cec5SDimitry Andric                             (const lldb::SBEvent &), event);
12020b57cec5SDimitry Andric 
12030b57cec5SDimitry Andric   return Thread::ThreadEventData::GetEventDataFromEvent(event.get()) != nullptr;
12040b57cec5SDimitry Andric }
12050b57cec5SDimitry Andric 
12060b57cec5SDimitry Andric SBFrame SBThread::GetStackFrameFromEvent(const SBEvent &event) {
12070b57cec5SDimitry Andric   LLDB_RECORD_STATIC_METHOD(lldb::SBFrame, SBThread, GetStackFrameFromEvent,
12080b57cec5SDimitry Andric                             (const lldb::SBEvent &), event);
12090b57cec5SDimitry Andric 
12100b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(
12110b57cec5SDimitry Andric       Thread::ThreadEventData::GetStackFrameFromEvent(event.get()));
12120b57cec5SDimitry Andric }
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric SBThread SBThread::GetThreadFromEvent(const SBEvent &event) {
12150b57cec5SDimitry Andric   LLDB_RECORD_STATIC_METHOD(lldb::SBThread, SBThread, GetThreadFromEvent,
12160b57cec5SDimitry Andric                             (const lldb::SBEvent &), event);
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(
12190b57cec5SDimitry Andric       Thread::ThreadEventData::GetThreadFromEvent(event.get()));
12200b57cec5SDimitry Andric }
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric bool SBThread::operator==(const SBThread &rhs) const {
12230b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST(bool, SBThread, operator==,(const lldb::SBThread &),
12240b57cec5SDimitry Andric                            rhs);
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric   return m_opaque_sp->GetThreadSP().get() ==
12270b57cec5SDimitry Andric          rhs.m_opaque_sp->GetThreadSP().get();
12280b57cec5SDimitry Andric }
12290b57cec5SDimitry Andric 
12300b57cec5SDimitry Andric bool SBThread::operator!=(const SBThread &rhs) const {
12310b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST(bool, SBThread, operator!=,(const lldb::SBThread &),
12320b57cec5SDimitry Andric                            rhs);
12330b57cec5SDimitry Andric 
12340b57cec5SDimitry Andric   return m_opaque_sp->GetThreadSP().get() !=
12350b57cec5SDimitry Andric          rhs.m_opaque_sp->GetThreadSP().get();
12360b57cec5SDimitry Andric }
12370b57cec5SDimitry Andric 
12380b57cec5SDimitry Andric bool SBThread::GetStatus(SBStream &status) const {
12390b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST(bool, SBThread, GetStatus, (lldb::SBStream &),
12400b57cec5SDimitry Andric                            status);
12410b57cec5SDimitry Andric 
12420b57cec5SDimitry Andric   Stream &strm = status.ref();
12430b57cec5SDimitry Andric 
12440b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
12450b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
12480b57cec5SDimitry Andric     exe_ctx.GetThreadPtr()->GetStatus(strm, 0, 1, 1, true);
12490b57cec5SDimitry Andric   } else
12500b57cec5SDimitry Andric     strm.PutCString("No status");
12510b57cec5SDimitry Andric 
12520b57cec5SDimitry Andric   return true;
12530b57cec5SDimitry Andric }
12540b57cec5SDimitry Andric 
12550b57cec5SDimitry Andric bool SBThread::GetDescription(SBStream &description) const {
12560b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST(bool, SBThread, GetDescription, (lldb::SBStream &),
12570b57cec5SDimitry Andric                            description);
12580b57cec5SDimitry Andric 
12590b57cec5SDimitry Andric   return GetDescription(description, false);
12600b57cec5SDimitry Andric }
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric bool SBThread::GetDescription(SBStream &description, bool stop_format) const {
12630b57cec5SDimitry Andric   LLDB_RECORD_METHOD_CONST(bool, SBThread, GetDescription,
12640b57cec5SDimitry Andric                            (lldb::SBStream &, bool), description, stop_format);
12650b57cec5SDimitry Andric 
12660b57cec5SDimitry Andric   Stream &strm = description.ref();
12670b57cec5SDimitry Andric 
12680b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
12690b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12700b57cec5SDimitry Andric 
12710b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
12720b57cec5SDimitry Andric     exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat(strm,
12730b57cec5SDimitry Andric                                                     LLDB_INVALID_THREAD_ID,
12740b57cec5SDimitry Andric                                                     stop_format);
12750b57cec5SDimitry Andric     // strm.Printf("SBThread: tid = 0x%4.4" PRIx64,
12760b57cec5SDimitry Andric     // exe_ctx.GetThreadPtr()->GetID());
12770b57cec5SDimitry Andric   } else
12780b57cec5SDimitry Andric     strm.PutCString("No value");
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric   return true;
12810b57cec5SDimitry Andric }
12820b57cec5SDimitry Andric 
12830b57cec5SDimitry Andric SBThread SBThread::GetExtendedBacktraceThread(const char *type) {
12840b57cec5SDimitry Andric   LLDB_RECORD_METHOD(lldb::SBThread, SBThread, GetExtendedBacktraceThread,
12850b57cec5SDimitry Andric                      (const char *), type);
12860b57cec5SDimitry Andric 
12870b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
12880b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12890b57cec5SDimitry Andric   SBThread sb_origin_thread;
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric   Process::StopLocker stop_locker;
12920b57cec5SDimitry Andric   if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
12930b57cec5SDimitry Andric     if (exe_ctx.HasThreadScope()) {
12940b57cec5SDimitry Andric       ThreadSP real_thread(exe_ctx.GetThreadSP());
12950b57cec5SDimitry Andric       if (real_thread) {
12960b57cec5SDimitry Andric         ConstString type_const(type);
12970b57cec5SDimitry Andric         Process *process = exe_ctx.GetProcessPtr();
12980b57cec5SDimitry Andric         if (process) {
12990b57cec5SDimitry Andric           SystemRuntime *runtime = process->GetSystemRuntime();
13000b57cec5SDimitry Andric           if (runtime) {
13010b57cec5SDimitry Andric             ThreadSP new_thread_sp(
13020b57cec5SDimitry Andric                 runtime->GetExtendedBacktraceThread(real_thread, type_const));
13030b57cec5SDimitry Andric             if (new_thread_sp) {
13040b57cec5SDimitry Andric               // Save this in the Process' ExtendedThreadList so a strong
13050b57cec5SDimitry Andric               // pointer retains the object.
13060b57cec5SDimitry Andric               process->GetExtendedThreadList().AddThread(new_thread_sp);
13070b57cec5SDimitry Andric               sb_origin_thread.SetThread(new_thread_sp);
13080b57cec5SDimitry Andric             }
13090b57cec5SDimitry Andric           }
13100b57cec5SDimitry Andric         }
13110b57cec5SDimitry Andric       }
13120b57cec5SDimitry Andric     }
13130b57cec5SDimitry Andric   }
13140b57cec5SDimitry Andric 
13150b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(sb_origin_thread);
13160b57cec5SDimitry Andric }
13170b57cec5SDimitry Andric 
13180b57cec5SDimitry Andric uint32_t SBThread::GetExtendedBacktraceOriginatingIndexID() {
13190b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBThread,
13200b57cec5SDimitry Andric                              GetExtendedBacktraceOriginatingIndexID);
13210b57cec5SDimitry Andric 
13220b57cec5SDimitry Andric   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
13230b57cec5SDimitry Andric   if (thread_sp)
13240b57cec5SDimitry Andric     return thread_sp->GetExtendedBacktraceOriginatingIndexID();
13250b57cec5SDimitry Andric   return LLDB_INVALID_INDEX32;
13260b57cec5SDimitry Andric }
13270b57cec5SDimitry Andric 
13280b57cec5SDimitry Andric SBValue SBThread::GetCurrentException() {
13290b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBValue, SBThread, GetCurrentException);
13300b57cec5SDimitry Andric 
13310b57cec5SDimitry Andric   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
13320b57cec5SDimitry Andric   if (!thread_sp)
13330b57cec5SDimitry Andric     return LLDB_RECORD_RESULT(SBValue());
13340b57cec5SDimitry Andric 
13350b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(SBValue(thread_sp->GetCurrentException()));
13360b57cec5SDimitry Andric }
13370b57cec5SDimitry Andric 
13380b57cec5SDimitry Andric SBThread SBThread::GetCurrentExceptionBacktrace() {
13390b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBThread, SBThread,
13400b57cec5SDimitry Andric                              GetCurrentExceptionBacktrace);
13410b57cec5SDimitry Andric 
13420b57cec5SDimitry Andric   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
13430b57cec5SDimitry Andric   if (!thread_sp)
13440b57cec5SDimitry Andric     return LLDB_RECORD_RESULT(SBThread());
13450b57cec5SDimitry Andric 
13460b57cec5SDimitry Andric   return LLDB_RECORD_RESULT(
13470b57cec5SDimitry Andric       SBThread(thread_sp->GetCurrentExceptionBacktrace()));
13480b57cec5SDimitry Andric }
13490b57cec5SDimitry Andric 
13500b57cec5SDimitry Andric bool SBThread::SafeToCallFunctions() {
13510b57cec5SDimitry Andric   LLDB_RECORD_METHOD_NO_ARGS(bool, SBThread, SafeToCallFunctions);
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
13540b57cec5SDimitry Andric   if (thread_sp)
13550b57cec5SDimitry Andric     return thread_sp->SafeToCallFunctions();
13560b57cec5SDimitry Andric   return true;
13570b57cec5SDimitry Andric }
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric lldb_private::Thread *SBThread::operator->() {
13600b57cec5SDimitry Andric   return get();
13610b57cec5SDimitry Andric }
13620b57cec5SDimitry Andric 
13630b57cec5SDimitry Andric lldb_private::Thread *SBThread::get() {
13640b57cec5SDimitry Andric   return m_opaque_sp->GetThreadSP().get();
13650b57cec5SDimitry Andric }
13660b57cec5SDimitry Andric 
13670b57cec5SDimitry Andric namespace lldb_private {
13680b57cec5SDimitry Andric namespace repro {
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric template <>
13710b57cec5SDimitry Andric void RegisterMethods<SBThread>(Registry &R) {
13720b57cec5SDimitry Andric   LLDB_REGISTER_STATIC_METHOD(const char *, SBThread, GetBroadcasterClassName,
13730b57cec5SDimitry Andric                               ());
13740b57cec5SDimitry Andric   LLDB_REGISTER_CONSTRUCTOR(SBThread, ());
13750b57cec5SDimitry Andric   LLDB_REGISTER_CONSTRUCTOR(SBThread, (const lldb::ThreadSP &));
13760b57cec5SDimitry Andric   LLDB_REGISTER_CONSTRUCTOR(SBThread, (const lldb::SBThread &));
13770b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(const lldb::SBThread &,
13780b57cec5SDimitry Andric                        SBThread, operator=,(const lldb::SBThread &));
13790b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(lldb::SBQueue, SBThread, GetQueue, ());
13800b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(bool, SBThread, IsValid, ());
13810b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(bool, SBThread, operator bool, ());
13820b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, Clear, ());
13830b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::StopReason, SBThread, GetStopReason, ());
13840b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(size_t, SBThread, GetStopReasonDataCount, ());
13850b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(uint64_t, SBThread, GetStopReasonDataAtIndex,
13860b57cec5SDimitry Andric                        (uint32_t));
13870b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(bool, SBThread, GetStopReasonExtendedInfoAsJSON,
13880b57cec5SDimitry Andric                        (lldb::SBStream &));
13890b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBThreadCollection, SBThread,
13900b57cec5SDimitry Andric                        GetStopReasonExtendedBacktraces,
13910b57cec5SDimitry Andric                        (lldb::InstrumentationRuntimeType));
13920b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBValue, SBThread, GetStopReturnValue, ());
13930b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(lldb::tid_t, SBThread, GetThreadID, ());
13940b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(uint32_t, SBThread, GetIndexID, ());
13950b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(const char *, SBThread, GetName, ());
13960b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(const char *, SBThread, GetQueueName, ());
13970b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(lldb::queue_id_t, SBThread, GetQueueID, ());
13980b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(bool, SBThread, GetInfoItemByPathAsString,
13990b57cec5SDimitry Andric                        (const char *, lldb::SBStream &));
14000b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, StepOver, (lldb::RunMode));
14010b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, StepOver,
14020b57cec5SDimitry Andric                        (lldb::RunMode, lldb::SBError &));
14030b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, StepInto, (lldb::RunMode));
14040b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, StepInto,
14050b57cec5SDimitry Andric                        (const char *, lldb::RunMode));
14060b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(
14070b57cec5SDimitry Andric       void, SBThread, StepInto,
14080b57cec5SDimitry Andric       (const char *, uint32_t, lldb::SBError &, lldb::RunMode));
14090b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, StepOut, ());
14100b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, StepOut, (lldb::SBError &));
14110b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, StepOutOfFrame, (lldb::SBFrame &));
14120b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, StepOutOfFrame,
14130b57cec5SDimitry Andric                        (lldb::SBFrame &, lldb::SBError &));
14140b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, StepInstruction, (bool));
14150b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, StepInstruction,
14160b57cec5SDimitry Andric                        (bool, lldb::SBError &));
14170b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, RunToAddress, (lldb::addr_t));
14180b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(void, SBThread, RunToAddress,
14190b57cec5SDimitry Andric                        (lldb::addr_t, lldb::SBError &));
14200b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBError, SBThread, StepOverUntil,
14210b57cec5SDimitry Andric                        (lldb::SBFrame &, lldb::SBFileSpec &, uint32_t));
14220b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan,
14230b57cec5SDimitry Andric                        (const char *));
14240b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan,
14250b57cec5SDimitry Andric                        (const char *, bool));
14269dba64beSDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan,
14279dba64beSDimitry Andric                        (const char *, SBStructuredData &, bool));
14280b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBError, SBThread, JumpToLine,
14290b57cec5SDimitry Andric                        (lldb::SBFileSpec &, uint32_t));
14300b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBError, SBThread, ReturnFromFrame,
14310b57cec5SDimitry Andric                        (lldb::SBFrame &, lldb::SBValue &));
14320b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBError, SBThread, UnwindInnermostExpression,
14330b57cec5SDimitry Andric                        ());
14340b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(bool, SBThread, Suspend, ());
14350b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(bool, SBThread, Suspend, (lldb::SBError &));
14360b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(bool, SBThread, Resume, ());
14370b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(bool, SBThread, Resume, (lldb::SBError &));
14380b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(bool, SBThread, IsSuspended, ());
14390b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(bool, SBThread, IsStopped, ());
14400b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBProcess, SBThread, GetProcess, ());
14410b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(uint32_t, SBThread, GetNumFrames, ());
14420b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBFrame, SBThread, GetFrameAtIndex, (uint32_t));
14430b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBFrame, SBThread, GetSelectedFrame, ());
14440b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBFrame, SBThread, SetSelectedFrame, (uint32_t));
14450b57cec5SDimitry Andric   LLDB_REGISTER_STATIC_METHOD(bool, SBThread, EventIsThreadEvent,
14460b57cec5SDimitry Andric                               (const lldb::SBEvent &));
14470b57cec5SDimitry Andric   LLDB_REGISTER_STATIC_METHOD(lldb::SBFrame, SBThread, GetStackFrameFromEvent,
14480b57cec5SDimitry Andric                               (const lldb::SBEvent &));
14490b57cec5SDimitry Andric   LLDB_REGISTER_STATIC_METHOD(lldb::SBThread, SBThread, GetThreadFromEvent,
14500b57cec5SDimitry Andric                               (const lldb::SBEvent &));
14510b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(bool,
14520b57cec5SDimitry Andric                              SBThread, operator==,(const lldb::SBThread &));
14530b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(bool,
14540b57cec5SDimitry Andric                              SBThread, operator!=,(const lldb::SBThread &));
14550b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(bool, SBThread, GetStatus, (lldb::SBStream &));
14560b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(bool, SBThread, GetDescription,
14570b57cec5SDimitry Andric                              (lldb::SBStream &));
14580b57cec5SDimitry Andric   LLDB_REGISTER_METHOD_CONST(bool, SBThread, GetDescription,
14590b57cec5SDimitry Andric                              (lldb::SBStream &, bool));
14600b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBThread, SBThread, GetExtendedBacktraceThread,
14610b57cec5SDimitry Andric                        (const char *));
14620b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(uint32_t, SBThread,
14630b57cec5SDimitry Andric                        GetExtendedBacktraceOriginatingIndexID, ());
14640b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBValue, SBThread, GetCurrentException, ());
14650b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(lldb::SBThread, SBThread, GetCurrentExceptionBacktrace,
14660b57cec5SDimitry Andric                        ());
14670b57cec5SDimitry Andric   LLDB_REGISTER_METHOD(bool, SBThread, SafeToCallFunctions, ());
14685ffd83dbSDimitry Andric   LLDB_REGISTER_CHAR_PTR_METHOD(size_t, SBThread, GetStopDescription);
14690b57cec5SDimitry Andric }
14700b57cec5SDimitry Andric 
14710b57cec5SDimitry Andric }
14720b57cec5SDimitry Andric }
1473