130fdc8d8SChris Lattner //===-- SBThread.cpp --------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
104c5de699SEli Friedman #include "lldb/API/SBThread.h"
1130fdc8d8SChris Lattner 
1230fdc8d8SChris Lattner #include "lldb/API/SBFileSpec.h"
13dde9cff3SCaroline Tice #include "lldb/API/SBStream.h"
14b9c1b51eSKate Stone #include "lldb/API/SBSymbolContext.h"
154e78f606SGreg Clayton #include "lldb/Breakpoint/BreakpointLocation.h"
166611103cSGreg Clayton #include "lldb/Core/Debugger.h"
17a75418dbSAndrew Kaylor #include "lldb/Core/State.h"
1830fdc8d8SChris Lattner #include "lldb/Core/StreamFile.h"
19705b1809SJason Molenda #include "lldb/Core/StructuredData.h"
20a78bd7ffSZachary Turner #include "lldb/Core/ValueObject.h"
216611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
2293749ab3SZachary Turner #include "lldb/Symbol/CompileUnit.h"
23b9c1b51eSKate Stone #include "lldb/Symbol/SymbolContext.h"
2430fdc8d8SChris Lattner #include "lldb/Target/Process.h"
25b9ffa98cSJason Molenda #include "lldb/Target/Queue.h"
26f4b47e15SGreg Clayton #include "lldb/Target/StopInfo.h"
27b9c1b51eSKate Stone #include "lldb/Target/SystemRuntime.h"
2830fdc8d8SChris Lattner #include "lldb/Target/Target.h"
29b9c1b51eSKate Stone #include "lldb/Target/Thread.h"
3030fdc8d8SChris Lattner #include "lldb/Target/ThreadPlan.h"
31b9c1b51eSKate Stone #include "lldb/Target/ThreadPlanStepInRange.h"
3230fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepInstruction.h"
3330fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepOut.h"
3430fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepRange.h"
35b9c1b51eSKate Stone #include "lldb/Target/UnixSignals.h"
36bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
3730fdc8d8SChris Lattner 
384c5de699SEli Friedman #include "lldb/API/SBAddress.h"
394c5de699SEli Friedman #include "lldb/API/SBDebugger.h"
404f465cffSJim Ingham #include "lldb/API/SBEvent.h"
4173ca05a2SJim Ingham #include "lldb/API/SBFrame.h"
424c5de699SEli Friedman #include "lldb/API/SBProcess.h"
436a831436SKuba Brecka #include "lldb/API/SBThreadCollection.h"
442bdbfd50SJim Ingham #include "lldb/API/SBThreadPlan.h"
4573ca05a2SJim Ingham #include "lldb/API/SBValue.h"
4630fdc8d8SChris Lattner 
4730fdc8d8SChris Lattner using namespace lldb;
4830fdc8d8SChris Lattner using namespace lldb_private;
4930fdc8d8SChris Lattner 
50b9c1b51eSKate Stone const char *SBThread::GetBroadcasterClassName() {
514f465cffSJim Ingham   return Thread::GetStaticBroadcasterClass().AsCString();
524f465cffSJim Ingham }
534f465cffSJim Ingham 
54cfd1acedSGreg Clayton //----------------------------------------------------------------------
55cfd1acedSGreg Clayton // Constructors
56cfd1acedSGreg Clayton //----------------------------------------------------------------------
57b9c1b51eSKate Stone SBThread::SBThread() : m_opaque_sp(new ExecutionContextRef()) {}
5830fdc8d8SChris Lattner 
59b9c1b51eSKate Stone SBThread::SBThread(const ThreadSP &lldb_object_sp)
60b9c1b51eSKate Stone     : m_opaque_sp(new ExecutionContextRef(lldb_object_sp)) {}
6130fdc8d8SChris Lattner 
62b9c1b51eSKate Stone SBThread::SBThread(const SBThread &rhs)
63b9c1b51eSKate Stone     : m_opaque_sp(new ExecutionContextRef(*rhs.m_opaque_sp)) {}
6430fdc8d8SChris Lattner 
6530fdc8d8SChris Lattner //----------------------------------------------------------------------
66cfd1acedSGreg Clayton // Assignment operator
67cfd1acedSGreg Clayton //----------------------------------------------------------------------
68cfd1acedSGreg Clayton 
69b9c1b51eSKate Stone const lldb::SBThread &SBThread::operator=(const SBThread &rhs) {
70cfd1acedSGreg Clayton   if (this != &rhs)
717fdf9ef1SGreg Clayton     *m_opaque_sp = *rhs.m_opaque_sp;
72cfd1acedSGreg Clayton   return *this;
73cfd1acedSGreg Clayton }
74cfd1acedSGreg Clayton 
75cfd1acedSGreg Clayton //----------------------------------------------------------------------
7630fdc8d8SChris Lattner // Destructor
7730fdc8d8SChris Lattner //----------------------------------------------------------------------
78b9c1b51eSKate Stone SBThread::~SBThread() {}
7930fdc8d8SChris Lattner 
80b9c1b51eSKate Stone lldb::SBQueue SBThread::GetQueue() const {
81b9ffa98cSJason Molenda   SBQueue sb_queue;
82b9ffa98cSJason Molenda   QueueSP queue_sp;
83bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
84bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
85b9ffa98cSJason Molenda 
86b9ffa98cSJason Molenda   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
87b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
88b9ffa98cSJason Molenda     Process::StopLocker stop_locker;
89b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
90b9ffa98cSJason Molenda       queue_sp = exe_ctx.GetThreadPtr()->GetQueue();
91b9c1b51eSKate Stone       if (queue_sp) {
92b9ffa98cSJason Molenda         sb_queue.SetQueue(queue_sp);
93b9ffa98cSJason Molenda       }
94b9c1b51eSKate Stone     } else {
95b9ffa98cSJason Molenda       if (log)
96358cf1eaSGreg Clayton         log->Printf("SBThread(%p)::GetQueue() => error: process is running",
97b9ffa98cSJason Molenda                     static_cast<void *>(exe_ctx.GetThreadPtr()));
98b9ffa98cSJason Molenda     }
99b9ffa98cSJason Molenda   }
100b9ffa98cSJason Molenda 
101b9ffa98cSJason Molenda   if (log)
102358cf1eaSGreg Clayton     log->Printf("SBThread(%p)::GetQueue () => SBQueue(%p)",
103b9c1b51eSKate Stone                 static_cast<void *>(exe_ctx.GetThreadPtr()),
104b9c1b51eSKate Stone                 static_cast<void *>(queue_sp.get()));
105b9ffa98cSJason Molenda 
106b9ffa98cSJason Molenda   return sb_queue;
107b9ffa98cSJason Molenda }
108b9ffa98cSJason Molenda 
109b9c1b51eSKate Stone bool SBThread::IsValid() const {
110bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
111bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1127fa7dc36SJim Ingham 
1137fa7dc36SJim Ingham   Target *target = exe_ctx.GetTargetPtr();
1147fa7dc36SJim Ingham   Process *process = exe_ctx.GetProcessPtr();
115b9c1b51eSKate Stone   if (target && process) {
1167fa7dc36SJim Ingham     Process::StopLocker stop_locker;
1177fa7dc36SJim Ingham     if (stop_locker.TryLock(&process->GetRunLock()))
1187fdf9ef1SGreg Clayton       return m_opaque_sp->GetThreadSP().get() != NULL;
11930fdc8d8SChris Lattner   }
1207fa7dc36SJim Ingham   // Without a valid target & process, this thread can't be valid.
1217fa7dc36SJim Ingham   return false;
1227fa7dc36SJim Ingham }
12330fdc8d8SChris Lattner 
124b9c1b51eSKate Stone void SBThread::Clear() { m_opaque_sp->Clear(); }
12548e42549SGreg Clayton 
126b9c1b51eSKate Stone StopReason SBThread::GetStopReason() {
1275160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
128ceb6b139SCaroline Tice 
129ceb6b139SCaroline Tice   StopReason reason = eStopReasonInvalid;
130bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
131bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1324fc6cb9cSJim Ingham 
133b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
1347fdf9ef1SGreg Clayton     Process::StopLocker stop_locker;
135b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
13697d5cf05SGreg Clayton       return exe_ctx.GetThreadPtr()->GetStopReason();
137b9c1b51eSKate Stone     } else {
138c9858e4dSGreg Clayton       if (log)
139b9c1b51eSKate Stone         log->Printf(
140b9c1b51eSKate Stone             "SBThread(%p)::GetStopReason() => error: process is running",
141324a1036SSaleem Abdulrasool             static_cast<void *>(exe_ctx.GetThreadPtr()));
142c9858e4dSGreg Clayton     }
1437fdf9ef1SGreg Clayton   }
144ceb6b139SCaroline Tice 
145ceb6b139SCaroline Tice   if (log)
146324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::GetStopReason () => %s",
147324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()),
148750cd175SCaroline Tice                 Thread::StopReasonAsCString(reason));
149ceb6b139SCaroline Tice 
150ceb6b139SCaroline Tice   return reason;
15130fdc8d8SChris Lattner }
15230fdc8d8SChris Lattner 
153b9c1b51eSKate Stone size_t SBThread::GetStopReasonDataCount() {
154bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
155bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1564fc6cb9cSJim Ingham 
157b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
1587fdf9ef1SGreg Clayton     Process::StopLocker stop_locker;
159b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1601ac04c30SGreg Clayton       StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
161b9c1b51eSKate Stone       if (stop_info_sp) {
1624e78f606SGreg Clayton         StopReason reason = stop_info_sp->GetStopReason();
163b9c1b51eSKate Stone         switch (reason) {
1644e78f606SGreg Clayton         case eStopReasonInvalid:
1654e78f606SGreg Clayton         case eStopReasonNone:
1664e78f606SGreg Clayton         case eStopReasonTrace:
16790ba8115SGreg Clayton         case eStopReasonExec:
1684e78f606SGreg Clayton         case eStopReasonPlanComplete:
169f85defaeSAndrew Kaylor         case eStopReasonThreadExiting:
170afdf842bSKuba Brecka         case eStopReasonInstrumentation:
1714e78f606SGreg Clayton           // There is no data for these stop reasons.
1724e78f606SGreg Clayton           return 0;
1734e78f606SGreg Clayton 
174b9c1b51eSKate Stone         case eStopReasonBreakpoint: {
1754e78f606SGreg Clayton           break_id_t site_id = stop_info_sp->GetValue();
176b9c1b51eSKate Stone           lldb::BreakpointSiteSP bp_site_sp(
177b9c1b51eSKate Stone               exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
178b9c1b51eSKate Stone                   site_id));
1794e78f606SGreg Clayton           if (bp_site_sp)
1804e78f606SGreg Clayton             return bp_site_sp->GetNumberOfOwners() * 2;
1814e78f606SGreg Clayton           else
1824e78f606SGreg Clayton             return 0; // Breakpoint must have cleared itself...
183b9c1b51eSKate Stone         } break;
1844e78f606SGreg Clayton 
1854e78f606SGreg Clayton         case eStopReasonWatchpoint:
186290fa41bSJohnny Chen           return 1;
1874e78f606SGreg Clayton 
1884e78f606SGreg Clayton         case eStopReasonSignal:
1894e78f606SGreg Clayton           return 1;
1904e78f606SGreg Clayton 
1914e78f606SGreg Clayton         case eStopReasonException:
1924e78f606SGreg Clayton           return 1;
1934e78f606SGreg Clayton         }
1944e78f606SGreg Clayton       }
195b9c1b51eSKate Stone     } else {
1965160ce5cSGreg Clayton       Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
197c9858e4dSGreg Clayton       if (log)
198b9c1b51eSKate Stone         log->Printf("SBThread(%p)::GetStopReasonDataCount() => error: process "
199b9c1b51eSKate Stone                     "is running",
200324a1036SSaleem Abdulrasool                     static_cast<void *>(exe_ctx.GetThreadPtr()));
201c9858e4dSGreg Clayton     }
2027fdf9ef1SGreg Clayton   }
2034e78f606SGreg Clayton   return 0;
2044e78f606SGreg Clayton }
2054e78f606SGreg Clayton 
206b9c1b51eSKate Stone uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) {
207bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
208bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
2094fc6cb9cSJim Ingham 
210b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
2117fdf9ef1SGreg Clayton     Process::StopLocker stop_locker;
212b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
2131ac04c30SGreg Clayton       Thread *thread = exe_ctx.GetThreadPtr();
2141ac04c30SGreg Clayton       StopInfoSP stop_info_sp = thread->GetStopInfo();
215b9c1b51eSKate Stone       if (stop_info_sp) {
2164e78f606SGreg Clayton         StopReason reason = stop_info_sp->GetStopReason();
217b9c1b51eSKate Stone         switch (reason) {
2184e78f606SGreg Clayton         case eStopReasonInvalid:
2194e78f606SGreg Clayton         case eStopReasonNone:
2204e78f606SGreg Clayton         case eStopReasonTrace:
22190ba8115SGreg Clayton         case eStopReasonExec:
2224e78f606SGreg Clayton         case eStopReasonPlanComplete:
223f85defaeSAndrew Kaylor         case eStopReasonThreadExiting:
224afdf842bSKuba Brecka         case eStopReasonInstrumentation:
2254e78f606SGreg Clayton           // There is no data for these stop reasons.
2264e78f606SGreg Clayton           return 0;
2274e78f606SGreg Clayton 
228b9c1b51eSKate Stone         case eStopReasonBreakpoint: {
2294e78f606SGreg Clayton           break_id_t site_id = stop_info_sp->GetValue();
230b9c1b51eSKate Stone           lldb::BreakpointSiteSP bp_site_sp(
231b9c1b51eSKate Stone               exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
232b9c1b51eSKate Stone                   site_id));
233b9c1b51eSKate Stone           if (bp_site_sp) {
2344e78f606SGreg Clayton             uint32_t bp_index = idx / 2;
235b9c1b51eSKate Stone             BreakpointLocationSP bp_loc_sp(
236b9c1b51eSKate Stone                 bp_site_sp->GetOwnerAtIndex(bp_index));
237b9c1b51eSKate Stone             if (bp_loc_sp) {
238b9c1b51eSKate Stone               if (idx & 1) {
2394e78f606SGreg Clayton                 // Odd idx, return the breakpoint location ID
2404e78f606SGreg Clayton                 return bp_loc_sp->GetID();
241b9c1b51eSKate Stone               } else {
2424e78f606SGreg Clayton                 // Even idx, return the breakpoint ID
2434e78f606SGreg Clayton                 return bp_loc_sp->GetBreakpoint().GetID();
2444e78f606SGreg Clayton               }
2454e78f606SGreg Clayton             }
2464e78f606SGreg Clayton           }
2474e78f606SGreg Clayton           return LLDB_INVALID_BREAK_ID;
248b9c1b51eSKate Stone         } break;
2494e78f606SGreg Clayton 
2504e78f606SGreg Clayton         case eStopReasonWatchpoint:
251290fa41bSJohnny Chen           return stop_info_sp->GetValue();
2524e78f606SGreg Clayton 
2534e78f606SGreg Clayton         case eStopReasonSignal:
2544e78f606SGreg Clayton           return stop_info_sp->GetValue();
2554e78f606SGreg Clayton 
2564e78f606SGreg Clayton         case eStopReasonException:
2574e78f606SGreg Clayton           return stop_info_sp->GetValue();
2584e78f606SGreg Clayton         }
2594e78f606SGreg Clayton       }
260b9c1b51eSKate Stone     } else {
2615160ce5cSGreg Clayton       Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
262c9858e4dSGreg Clayton       if (log)
263b9c1b51eSKate Stone         log->Printf("SBThread(%p)::GetStopReasonDataAtIndex() => error: "
264b9c1b51eSKate Stone                     "process is running",
265324a1036SSaleem Abdulrasool                     static_cast<void *>(exe_ctx.GetThreadPtr()));
266c9858e4dSGreg Clayton     }
2677fdf9ef1SGreg Clayton   }
2684e78f606SGreg Clayton   return 0;
2694e78f606SGreg Clayton }
2704e78f606SGreg Clayton 
271b9c1b51eSKate Stone bool SBThread::GetStopReasonExtendedInfoAsJSON(lldb::SBStream &stream) {
272afdf842bSKuba Brecka   Stream &strm = stream.ref();
273afdf842bSKuba Brecka 
274b2e7d28eSJim Ingham   std::unique_lock<std::recursive_mutex> lock;
275b2e7d28eSJim Ingham   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
276b2e7d28eSJim Ingham 
277afdf842bSKuba Brecka   if (!exe_ctx.HasThreadScope())
278afdf842bSKuba Brecka     return false;
279afdf842bSKuba Brecka 
280afdf842bSKuba Brecka   StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
281afdf842bSKuba Brecka   StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
282afdf842bSKuba Brecka   if (!info)
283afdf842bSKuba Brecka     return false;
284afdf842bSKuba Brecka 
285afdf842bSKuba Brecka   info->Dump(strm);
286afdf842bSKuba Brecka 
287afdf842bSKuba Brecka   return true;
288afdf842bSKuba Brecka }
289afdf842bSKuba Brecka 
2906a831436SKuba Brecka SBThreadCollection
291b9c1b51eSKate Stone SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) {
2926a831436SKuba Brecka   ThreadCollectionSP threads;
2936a831436SKuba Brecka   threads.reset(new ThreadCollection());
2946a831436SKuba Brecka 
2956a831436SKuba Brecka   // We currently only support ThreadSanitizer.
2966a831436SKuba Brecka   if (type != eInstrumentationRuntimeTypeThreadSanitizer)
2976a831436SKuba Brecka     return threads;
2986a831436SKuba Brecka 
299b2e7d28eSJim Ingham   std::unique_lock<std::recursive_mutex> lock;
300b2e7d28eSJim Ingham   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
301b2e7d28eSJim Ingham 
3026a831436SKuba Brecka   if (!exe_ctx.HasThreadScope())
3031aad8fb7SKuba Brecka     return threads;
3046a831436SKuba Brecka 
3056a831436SKuba Brecka   ProcessSP process_sp = exe_ctx.GetProcessSP();
3066a831436SKuba Brecka 
3076a831436SKuba Brecka   StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
3086a831436SKuba Brecka   StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
3096a831436SKuba Brecka   if (!info)
3106a831436SKuba Brecka     return threads;
3116a831436SKuba Brecka 
312b9c1b51eSKate Stone   return process_sp->GetInstrumentationRuntime(type)
313b9c1b51eSKate Stone       ->GetBacktracesFromExtendedStopInfo(info);
3146a831436SKuba Brecka }
3156a831436SKuba Brecka 
316b9c1b51eSKate Stone size_t SBThread::GetStopDescription(char *dst, size_t dst_len) {
3175160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
318ceb6b139SCaroline Tice 
319bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
320bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
3214fc6cb9cSJim Ingham 
322b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
3237fdf9ef1SGreg Clayton     Process::StopLocker stop_locker;
324b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
3257fdf9ef1SGreg Clayton 
3261ac04c30SGreg Clayton       StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
327b9c1b51eSKate Stone       if (stop_info_sp) {
328b15bfc75SJim Ingham         const char *stop_desc = stop_info_sp->GetDescription();
329b9c1b51eSKate Stone         if (stop_desc) {
330ceb6b139SCaroline Tice           if (log)
331b9c1b51eSKate Stone             log->Printf(
332b9c1b51eSKate Stone                 "SBThread(%p)::GetStopDescription (dst, dst_len) => \"%s\"",
333b9c1b51eSKate Stone                 static_cast<void *>(exe_ctx.GetThreadPtr()), stop_desc);
33430fdc8d8SChris Lattner           if (dst)
33530fdc8d8SChris Lattner             return ::snprintf(dst, dst_len, "%s", stop_desc);
336b9c1b51eSKate Stone           else {
337b9c1b51eSKate Stone             // NULL dst passed in, return the length needed to contain the
338b9c1b51eSKate Stone             // description
33930fdc8d8SChris Lattner             return ::strlen(stop_desc) + 1; // Include the NULL byte for size
34030fdc8d8SChris Lattner           }
341b9c1b51eSKate Stone         } else {
34230fdc8d8SChris Lattner           size_t stop_desc_len = 0;
343b9c1b51eSKate Stone           switch (stop_info_sp->GetStopReason()) {
34430fdc8d8SChris Lattner           case eStopReasonTrace:
345b9c1b51eSKate Stone           case eStopReasonPlanComplete: {
34630fdc8d8SChris Lattner             static char trace_desc[] = "step";
34730fdc8d8SChris Lattner             stop_desc = trace_desc;
348b9c1b51eSKate Stone             stop_desc_len =
349b9c1b51eSKate Stone                 sizeof(trace_desc); // Include the NULL byte for size
350b9c1b51eSKate Stone           } break;
35130fdc8d8SChris Lattner 
352b9c1b51eSKate Stone           case eStopReasonBreakpoint: {
35330fdc8d8SChris Lattner             static char bp_desc[] = "breakpoint hit";
35430fdc8d8SChris Lattner             stop_desc = bp_desc;
35530fdc8d8SChris Lattner             stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
356b9c1b51eSKate Stone           } break;
35730fdc8d8SChris Lattner 
358b9c1b51eSKate Stone           case eStopReasonWatchpoint: {
35930fdc8d8SChris Lattner             static char wp_desc[] = "watchpoint hit";
36030fdc8d8SChris Lattner             stop_desc = wp_desc;
36130fdc8d8SChris Lattner             stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
362b9c1b51eSKate Stone           } break;
36330fdc8d8SChris Lattner 
364b9c1b51eSKate Stone           case eStopReasonSignal: {
365b9c1b51eSKate Stone             stop_desc =
366b9c1b51eSKate Stone                 exe_ctx.GetProcessPtr()->GetUnixSignals()->GetSignalAsCString(
367b9c1b51eSKate Stone                     stop_info_sp->GetValue());
368b9c1b51eSKate Stone             if (stop_desc == NULL || stop_desc[0] == '\0') {
36930fdc8d8SChris Lattner               static char signal_desc[] = "signal";
37030fdc8d8SChris Lattner               stop_desc = signal_desc;
371b9c1b51eSKate Stone               stop_desc_len =
372b9c1b51eSKate Stone                   sizeof(signal_desc); // Include the NULL byte for size
37330fdc8d8SChris Lattner             }
374b9c1b51eSKate Stone           } break;
37530fdc8d8SChris Lattner 
376b9c1b51eSKate Stone           case eStopReasonException: {
37730fdc8d8SChris Lattner             char exc_desc[] = "exception";
37830fdc8d8SChris Lattner             stop_desc = exc_desc;
37930fdc8d8SChris Lattner             stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
380b9c1b51eSKate Stone           } break;
381c982c768SGreg Clayton 
382b9c1b51eSKate Stone           case eStopReasonExec: {
38390ba8115SGreg Clayton             char exc_desc[] = "exec";
38490ba8115SGreg Clayton             stop_desc = exc_desc;
38590ba8115SGreg Clayton             stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
386b9c1b51eSKate Stone           } break;
38790ba8115SGreg Clayton 
388b9c1b51eSKate Stone           case eStopReasonThreadExiting: {
389f85defaeSAndrew Kaylor             char limbo_desc[] = "thread exiting";
390f85defaeSAndrew Kaylor             stop_desc = limbo_desc;
391f85defaeSAndrew Kaylor             stop_desc_len = sizeof(limbo_desc);
392b9c1b51eSKate Stone           } break;
393c982c768SGreg Clayton           default:
394c982c768SGreg Clayton             break;
39530fdc8d8SChris Lattner           }
39630fdc8d8SChris Lattner 
397b9c1b51eSKate Stone           if (stop_desc && stop_desc[0]) {
398ceb6b139SCaroline Tice             if (log)
399b9c1b51eSKate Stone               log->Printf(
400b9c1b51eSKate Stone                   "SBThread(%p)::GetStopDescription (dst, dst_len) => '%s'",
401b9c1b51eSKate Stone                   static_cast<void *>(exe_ctx.GetThreadPtr()), stop_desc);
402ceb6b139SCaroline Tice 
40330fdc8d8SChris Lattner             if (dst)
404b9c1b51eSKate Stone               return ::snprintf(dst, dst_len, "%s", stop_desc) +
405b9c1b51eSKate Stone                      1; // Include the NULL byte
40630fdc8d8SChris Lattner 
40730fdc8d8SChris Lattner             if (stop_desc_len == 0)
40830fdc8d8SChris Lattner               stop_desc_len = ::strlen(stop_desc) + 1; // Include the NULL byte
40930fdc8d8SChris Lattner 
41030fdc8d8SChris Lattner             return stop_desc_len;
41130fdc8d8SChris Lattner           }
41230fdc8d8SChris Lattner         }
41330fdc8d8SChris Lattner       }
414b9c1b51eSKate Stone     } else {
4155160ce5cSGreg Clayton       Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
416c9858e4dSGreg Clayton       if (log)
417b9c1b51eSKate Stone         log->Printf(
418b9c1b51eSKate Stone             "SBThread(%p)::GetStopDescription() => error: process is running",
419324a1036SSaleem Abdulrasool             static_cast<void *>(exe_ctx.GetThreadPtr()));
420c9858e4dSGreg Clayton     }
4217fdf9ef1SGreg Clayton   }
42230fdc8d8SChris Lattner   if (dst)
42330fdc8d8SChris Lattner     *dst = 0;
42430fdc8d8SChris Lattner   return 0;
42530fdc8d8SChris Lattner }
42630fdc8d8SChris Lattner 
427b9c1b51eSKate Stone SBValue SBThread::GetStopReturnValue() {
4285160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
42973ca05a2SJim Ingham   ValueObjectSP return_valobj_sp;
430bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
431bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
4324fc6cb9cSJim Ingham 
433b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
4347fdf9ef1SGreg Clayton     Process::StopLocker stop_locker;
435b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
4361ac04c30SGreg Clayton       StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
437b9c1b51eSKate Stone       if (stop_info_sp) {
43873ca05a2SJim Ingham         return_valobj_sp = StopInfo::GetReturnValueObject(stop_info_sp);
43973ca05a2SJim Ingham       }
440b9c1b51eSKate Stone     } else {
441c9858e4dSGreg Clayton       if (log)
442b9c1b51eSKate Stone         log->Printf(
443b9c1b51eSKate Stone             "SBThread(%p)::GetStopReturnValue() => error: process is running",
444324a1036SSaleem Abdulrasool             static_cast<void *>(exe_ctx.GetThreadPtr()));
445c9858e4dSGreg Clayton     }
4467fdf9ef1SGreg Clayton   }
44773ca05a2SJim Ingham 
44873ca05a2SJim Ingham   if (log)
449324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::GetStopReturnValue () => %s",
450324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()),
451b9c1b51eSKate Stone                 return_valobj_sp.get() ? return_valobj_sp->GetValueAsCString()
45273ca05a2SJim Ingham                                        : "<no return value>");
45373ca05a2SJim Ingham 
45473ca05a2SJim Ingham   return SBValue(return_valobj_sp);
45573ca05a2SJim Ingham }
45673ca05a2SJim Ingham 
457b9c1b51eSKate Stone void SBThread::SetThread(const ThreadSP &lldb_object_sp) {
4587fdf9ef1SGreg Clayton   m_opaque_sp->SetThreadSP(lldb_object_sp);
45930fdc8d8SChris Lattner }
46030fdc8d8SChris Lattner 
461b9c1b51eSKate Stone lldb::tid_t SBThread::GetThreadID() const {
4627fdf9ef1SGreg Clayton   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
46317a6ad05SGreg Clayton   if (thread_sp)
4641ac04c30SGreg Clayton     return thread_sp->GetID();
4651ac04c30SGreg Clayton   return LLDB_INVALID_THREAD_ID;
46630fdc8d8SChris Lattner }
46730fdc8d8SChris Lattner 
468b9c1b51eSKate Stone uint32_t SBThread::GetIndexID() const {
4697fdf9ef1SGreg Clayton   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
47017a6ad05SGreg Clayton   if (thread_sp)
47117a6ad05SGreg Clayton     return thread_sp->GetIndexID();
47230fdc8d8SChris Lattner   return LLDB_INVALID_INDEX32;
47330fdc8d8SChris Lattner }
4741ac04c30SGreg Clayton 
475b9c1b51eSKate Stone const char *SBThread::GetName() const {
4765160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
4774838131bSGreg Clayton   const char *name = NULL;
478bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
479bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
4804fc6cb9cSJim Ingham 
481b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
4827fdf9ef1SGreg Clayton     Process::StopLocker stop_locker;
483b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
4841ac04c30SGreg Clayton       name = exe_ctx.GetThreadPtr()->GetName();
485b9c1b51eSKate Stone     } else {
486c9858e4dSGreg Clayton       if (log)
487324a1036SSaleem Abdulrasool         log->Printf("SBThread(%p)::GetName() => error: process is running",
488324a1036SSaleem Abdulrasool                     static_cast<void *>(exe_ctx.GetThreadPtr()));
489c9858e4dSGreg Clayton     }
4907fdf9ef1SGreg Clayton   }
491ceb6b139SCaroline Tice 
492ceb6b139SCaroline Tice   if (log)
493324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::GetName () => %s",
494324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()),
495324a1036SSaleem Abdulrasool                 name ? name : "NULL");
496ceb6b139SCaroline Tice 
4974838131bSGreg Clayton   return name;
49830fdc8d8SChris Lattner }
49930fdc8d8SChris Lattner 
500b9c1b51eSKate Stone const char *SBThread::GetQueueName() const {
5014838131bSGreg Clayton   const char *name = NULL;
502bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
503bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
5044fc6cb9cSJim Ingham 
5055160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
506b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
5077fdf9ef1SGreg Clayton     Process::StopLocker stop_locker;
508b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
5091ac04c30SGreg Clayton       name = exe_ctx.GetThreadPtr()->GetQueueName();
510b9c1b51eSKate Stone     } else {
511c9858e4dSGreg Clayton       if (log)
512324a1036SSaleem Abdulrasool         log->Printf("SBThread(%p)::GetQueueName() => error: process is running",
513324a1036SSaleem Abdulrasool                     static_cast<void *>(exe_ctx.GetThreadPtr()));
514c9858e4dSGreg Clayton     }
5157fdf9ef1SGreg Clayton   }
516ceb6b139SCaroline Tice 
517ceb6b139SCaroline Tice   if (log)
518324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::GetQueueName () => %s",
519324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()),
520324a1036SSaleem Abdulrasool                 name ? name : "NULL");
521ceb6b139SCaroline Tice 
5224838131bSGreg Clayton   return name;
52330fdc8d8SChris Lattner }
52430fdc8d8SChris Lattner 
525b9c1b51eSKate Stone lldb::queue_id_t SBThread::GetQueueID() const {
5264fdb5863SJason Molenda   queue_id_t id = LLDB_INVALID_QUEUE_ID;
527bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
528bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
5294fdb5863SJason Molenda 
5304fdb5863SJason Molenda   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
531b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
5324fdb5863SJason Molenda     Process::StopLocker stop_locker;
533b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
5344fdb5863SJason Molenda       id = exe_ctx.GetThreadPtr()->GetQueueID();
535b9c1b51eSKate Stone     } else {
5364fdb5863SJason Molenda       if (log)
537324a1036SSaleem Abdulrasool         log->Printf("SBThread(%p)::GetQueueID() => error: process is running",
538324a1036SSaleem Abdulrasool                     static_cast<void *>(exe_ctx.GetThreadPtr()));
5394fdb5863SJason Molenda     }
5404fdb5863SJason Molenda   }
5414fdb5863SJason Molenda 
5424fdb5863SJason Molenda   if (log)
543324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::GetQueueID () => 0x%" PRIx64,
544324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()), id);
5454fdb5863SJason Molenda 
5464fdb5863SJason Molenda   return id;
5474fdb5863SJason Molenda }
5484fdb5863SJason Molenda 
549b9c1b51eSKate Stone bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) {
550705b1809SJason Molenda   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
551705b1809SJason Molenda   bool success = false;
552bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
553bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
554705b1809SJason Molenda 
555b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
556705b1809SJason Molenda     Process::StopLocker stop_locker;
557b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
558705b1809SJason Molenda       Thread *thread = exe_ctx.GetThreadPtr();
559705b1809SJason Molenda       StructuredData::ObjectSP info_root_sp = thread->GetExtendedInfo();
560b9c1b51eSKate Stone       if (info_root_sp) {
561b9c1b51eSKate Stone         StructuredData::ObjectSP node =
562b9c1b51eSKate Stone             info_root_sp->GetObjectForDotSeparatedPath(path);
563b9c1b51eSKate Stone         if (node) {
564b9c1b51eSKate Stone           if (node->GetType() == StructuredData::Type::eTypeString) {
565705b1809SJason Molenda             strm.Printf("%s", node->GetAsString()->GetValue().c_str());
566705b1809SJason Molenda             success = true;
567705b1809SJason Molenda           }
568b9c1b51eSKate Stone           if (node->GetType() == StructuredData::Type::eTypeInteger) {
569705b1809SJason Molenda             strm.Printf("0x%" PRIx64, node->GetAsInteger()->GetValue());
570705b1809SJason Molenda             success = true;
571705b1809SJason Molenda           }
572b9c1b51eSKate Stone           if (node->GetType() == StructuredData::Type::eTypeFloat) {
573705b1809SJason Molenda             strm.Printf("0x%f", node->GetAsFloat()->GetValue());
574705b1809SJason Molenda             success = true;
575705b1809SJason Molenda           }
576b9c1b51eSKate Stone           if (node->GetType() == StructuredData::Type::eTypeBoolean) {
577705b1809SJason Molenda             if (node->GetAsBoolean()->GetValue() == true)
578705b1809SJason Molenda               strm.Printf("true");
579705b1809SJason Molenda             else
580705b1809SJason Molenda               strm.Printf("false");
581705b1809SJason Molenda             success = true;
582705b1809SJason Molenda           }
583b9c1b51eSKate Stone           if (node->GetType() == StructuredData::Type::eTypeNull) {
584705b1809SJason Molenda             strm.Printf("null");
585705b1809SJason Molenda             success = true;
586705b1809SJason Molenda           }
587705b1809SJason Molenda         }
588705b1809SJason Molenda       }
589b9c1b51eSKate Stone     } else {
590705b1809SJason Molenda       if (log)
591b9c1b51eSKate Stone         log->Printf("SBThread(%p)::GetInfoItemByPathAsString() => error: "
592b9c1b51eSKate Stone                     "process is running",
593705b1809SJason Molenda                     static_cast<void *>(exe_ctx.GetThreadPtr()));
594705b1809SJason Molenda     }
595705b1809SJason Molenda   }
596705b1809SJason Molenda 
597705b1809SJason Molenda   if (log)
598753e13c0SJason Molenda     log->Printf("SBThread(%p)::GetInfoItemByPathAsString (\"%s\") => \"%s\"",
599753e13c0SJason Molenda                 static_cast<void *>(exe_ctx.GetThreadPtr()), path, strm.GetData());
600705b1809SJason Molenda 
601705b1809SJason Molenda   return success;
602705b1809SJason Molenda }
603705b1809SJason Molenda 
604b9c1b51eSKate Stone SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx,
605b9c1b51eSKate Stone                                 ThreadPlan *new_plan) {
60664e7ead1SJim Ingham   SBError sb_error;
60764e7ead1SJim Ingham 
60864e7ead1SJim Ingham   Process *process = exe_ctx.GetProcessPtr();
609b9c1b51eSKate Stone   if (!process) {
61064e7ead1SJim Ingham     sb_error.SetErrorString("No process in SBThread::ResumeNewPlan");
61164e7ead1SJim Ingham     return sb_error;
61264e7ead1SJim Ingham   }
61364e7ead1SJim Ingham 
61464e7ead1SJim Ingham   Thread *thread = exe_ctx.GetThreadPtr();
615b9c1b51eSKate Stone   if (!thread) {
61664e7ead1SJim Ingham     sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan");
61764e7ead1SJim Ingham     return sb_error;
61864e7ead1SJim Ingham   }
61964e7ead1SJim Ingham 
620b9c1b51eSKate Stone   // User level plans should be Master Plans so they can be interrupted, other
621b9c1b51eSKate Stone   // plans executed, and
62264e7ead1SJim Ingham   // then a "continue" will resume the plan.
623b9c1b51eSKate Stone   if (new_plan != NULL) {
62464e7ead1SJim Ingham     new_plan->SetIsMasterPlan(true);
62564e7ead1SJim Ingham     new_plan->SetOkayToDiscard(false);
62664e7ead1SJim Ingham   }
62764e7ead1SJim Ingham 
62864e7ead1SJim Ingham   // Why do we need to set the current thread by ID here???
62964e7ead1SJim Ingham   process->GetThreadList().SetSelectedThreadByID(thread->GetID());
63064e7ead1SJim Ingham 
631dc6224e0SGreg Clayton   if (process->GetTarget().GetDebugger().GetAsyncExecution())
632dc6224e0SGreg Clayton     sb_error.ref() = process->Resume();
633dc6224e0SGreg Clayton   else
634dc6224e0SGreg Clayton     sb_error.ref() = process->ResumeSynchronous(NULL);
63564e7ead1SJim Ingham 
63664e7ead1SJim Ingham   return sb_error;
63764e7ead1SJim Ingham }
63830fdc8d8SChris Lattner 
639b9c1b51eSKate Stone void SBThread::StepOver(lldb::RunMode stop_other_threads) {
6405160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
641ceb6b139SCaroline Tice 
642bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
643bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
64417a6ad05SGreg Clayton 
645ceb6b139SCaroline Tice   if (log)
646324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::StepOver (stop_other_threads='%s')",
647324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()),
648ceb6b139SCaroline Tice                 Thread::RunModeAsCString(stop_other_threads));
649ceb6b139SCaroline Tice 
650b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
6511ac04c30SGreg Clayton     Thread *thread = exe_ctx.GetThreadPtr();
6527ba6e991SJim Ingham     bool abort_other_plans = false;
653b57e4a1bSJason Molenda     StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
65430fdc8d8SChris Lattner 
6554d56e9c1SJim Ingham     ThreadPlanSP new_plan_sp;
656b9c1b51eSKate Stone     if (frame_sp) {
657b9c1b51eSKate Stone       if (frame_sp->HasDebugInformation()) {
6584b4b2478SJim Ingham         const LazyBool avoid_no_debug = eLazyBoolCalculate;
65930fdc8d8SChris Lattner         SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
660b9c1b51eSKate Stone         new_plan_sp = thread->QueueThreadPlanForStepOverRange(
661b9c1b51eSKate Stone             abort_other_plans, sc.line_entry, sc, stop_other_threads,
6624b4b2478SJim Ingham             avoid_no_debug);
663b9c1b51eSKate Stone       } else {
664b9c1b51eSKate Stone         new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
665b9c1b51eSKate Stone             true, abort_other_plans, stop_other_threads);
66630fdc8d8SChris Lattner       }
66730fdc8d8SChris Lattner     }
66830fdc8d8SChris Lattner 
66964e7ead1SJim Ingham     // This returns an error, we should use it!
6704d56e9c1SJim Ingham     ResumeNewPlan(exe_ctx, new_plan_sp.get());
67130fdc8d8SChris Lattner   }
67230fdc8d8SChris Lattner }
67330fdc8d8SChris Lattner 
674b9c1b51eSKate Stone void SBThread::StepInto(lldb::RunMode stop_other_threads) {
675c627682eSJim Ingham   StepInto(NULL, stop_other_threads);
676c627682eSJim Ingham }
677c627682eSJim Ingham 
678b9c1b51eSKate Stone void SBThread::StepInto(const char *target_name,
679b9c1b51eSKate Stone                         lldb::RunMode stop_other_threads) {
680cbf6f9b2SJim Ingham   SBError error;
681cbf6f9b2SJim Ingham   StepInto(target_name, LLDB_INVALID_LINE_NUMBER, error, stop_other_threads);
682cbf6f9b2SJim Ingham }
683cbf6f9b2SJim Ingham 
684b9c1b51eSKate Stone void SBThread::StepInto(const char *target_name, uint32_t end_line,
685b9c1b51eSKate Stone                         SBError &error, lldb::RunMode stop_other_threads) {
6865160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
687ceb6b139SCaroline Tice 
688bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
689bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
69017a6ad05SGreg Clayton 
69117a6ad05SGreg Clayton   if (log)
692b9c1b51eSKate Stone     log->Printf(
693b9c1b51eSKate Stone         "SBThread(%p)::StepInto (target_name='%s', stop_other_threads='%s')",
694324a1036SSaleem Abdulrasool         static_cast<void *>(exe_ctx.GetThreadPtr()),
695c627682eSJim Ingham         target_name ? target_name : "<NULL>",
69617a6ad05SGreg Clayton         Thread::RunModeAsCString(stop_other_threads));
697c627682eSJim Ingham 
698b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
6997ba6e991SJim Ingham     bool abort_other_plans = false;
70030fdc8d8SChris Lattner 
7011ac04c30SGreg Clayton     Thread *thread = exe_ctx.GetThreadPtr();
702b57e4a1bSJason Molenda     StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
7034d56e9c1SJim Ingham     ThreadPlanSP new_plan_sp;
70430fdc8d8SChris Lattner 
705b9c1b51eSKate Stone     if (frame_sp && frame_sp->HasDebugInformation()) {
706cbf6f9b2SJim Ingham       SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
707cbf6f9b2SJim Ingham       AddressRange range;
708cbf6f9b2SJim Ingham       if (end_line == LLDB_INVALID_LINE_NUMBER)
709cbf6f9b2SJim Ingham         range = sc.line_entry.range;
710b9c1b51eSKate Stone       else {
711cbf6f9b2SJim Ingham         if (!sc.GetAddressRangeFromHereToEndLine(end_line, range, error.ref()))
712cbf6f9b2SJim Ingham           return;
713cbf6f9b2SJim Ingham       }
714cbf6f9b2SJim Ingham 
715b9c1b51eSKate Stone       const LazyBool step_out_avoids_code_without_debug_info =
716b9c1b51eSKate Stone           eLazyBoolCalculate;
717b9c1b51eSKate Stone       const LazyBool step_in_avoids_code_without_debug_info =
718b9c1b51eSKate Stone           eLazyBoolCalculate;
719b9c1b51eSKate Stone       new_plan_sp = thread->QueueThreadPlanForStepInRange(
720b9c1b51eSKate Stone           abort_other_plans, range, sc, target_name, stop_other_threads,
7214b4b2478SJim Ingham           step_in_avoids_code_without_debug_info,
7224b4b2478SJim Ingham           step_out_avoids_code_without_debug_info);
723b9c1b51eSKate Stone     } else {
724b9c1b51eSKate Stone       new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
725b9c1b51eSKate Stone           false, abort_other_plans, stop_other_threads);
72630fdc8d8SChris Lattner     }
72730fdc8d8SChris Lattner 
728cbf6f9b2SJim Ingham     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
72930fdc8d8SChris Lattner   }
73030fdc8d8SChris Lattner }
73130fdc8d8SChris Lattner 
732b9c1b51eSKate Stone void SBThread::StepOut() {
7335160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
734ceb6b139SCaroline Tice 
735bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
736bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
7374fc6cb9cSJim Ingham 
73817a6ad05SGreg Clayton   if (log)
739324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::StepOut ()",
740324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()));
74117a6ad05SGreg Clayton 
742b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
7437ba6e991SJim Ingham     bool abort_other_plans = false;
74494b09246SJim Ingham     bool stop_other_threads = false;
74530fdc8d8SChris Lattner 
7461ac04c30SGreg Clayton     Thread *thread = exe_ctx.GetThreadPtr();
7471ac04c30SGreg Clayton 
7484b4b2478SJim Ingham     const LazyBool avoid_no_debug = eLazyBoolCalculate;
749b9c1b51eSKate Stone     ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
750b9c1b51eSKate Stone         abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
751b9c1b51eSKate Stone         eVoteNoOpinion, 0, avoid_no_debug));
752481cef25SGreg Clayton 
75364e7ead1SJim Ingham     // This returns an error, we should use it!
7544d56e9c1SJim Ingham     ResumeNewPlan(exe_ctx, new_plan_sp.get());
755481cef25SGreg Clayton   }
756481cef25SGreg Clayton }
757481cef25SGreg Clayton 
758b9c1b51eSKate Stone void SBThread::StepOutOfFrame(lldb::SBFrame &sb_frame) {
7595160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
760481cef25SGreg Clayton 
761bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
762bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
7634fc6cb9cSJim Ingham 
764b9c1b51eSKate Stone   if (!sb_frame.IsValid()) {
765989a7558SJim Ingham     if (log)
766b9c1b51eSKate Stone       log->Printf(
767b9c1b51eSKate Stone           "SBThread(%p)::StepOutOfFrame passed an invalid frame, returning.",
768989a7558SJim Ingham           static_cast<void *>(exe_ctx.GetThreadPtr()));
769989a7558SJim Ingham     return;
770989a7558SJim Ingham   }
771989a7558SJim Ingham 
772b57e4a1bSJason Molenda   StackFrameSP frame_sp(sb_frame.GetFrameSP());
773b9c1b51eSKate Stone   if (log) {
774481cef25SGreg Clayton     SBStream frame_desc_strm;
775481cef25SGreg Clayton     sb_frame.GetDescription(frame_desc_strm);
776324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::StepOutOfFrame (frame = SBFrame(%p): %s)",
777324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()),
778b9c1b51eSKate Stone                 static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
779481cef25SGreg Clayton   }
780481cef25SGreg Clayton 
781b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
7827ba6e991SJim Ingham     bool abort_other_plans = false;
78394b09246SJim Ingham     bool stop_other_threads = false;
7841ac04c30SGreg Clayton     Thread *thread = exe_ctx.GetThreadPtr();
785b9c1b51eSKate Stone     if (sb_frame.GetThread().GetThreadID() != thread->GetID()) {
786b9c1b51eSKate Stone       log->Printf("SBThread(%p)::StepOutOfFrame passed a frame from another "
787b9c1b51eSKate Stone                   "thread (0x%" PRIx64 " vrs. 0x%" PRIx64 ", returning.",
788989a7558SJim Ingham                   static_cast<void *>(exe_ctx.GetThreadPtr()),
789b9c1b51eSKate Stone                   sb_frame.GetThread().GetThreadID(), thread->GetID());
790989a7558SJim Ingham     }
791481cef25SGreg Clayton 
792b9c1b51eSKate Stone     ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
793b9c1b51eSKate Stone         abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
794b9c1b51eSKate Stone         eVoteNoOpinion, frame_sp->GetFrameIndex()));
79530fdc8d8SChris Lattner 
79664e7ead1SJim Ingham     // This returns an error, we should use it!
7974d56e9c1SJim Ingham     ResumeNewPlan(exe_ctx, new_plan_sp.get());
79830fdc8d8SChris Lattner   }
79930fdc8d8SChris Lattner }
80030fdc8d8SChris Lattner 
801b9c1b51eSKate Stone void SBThread::StepInstruction(bool step_over) {
8025160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
803ceb6b139SCaroline Tice 
804bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
805bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
806ceb6b139SCaroline Tice 
80717a6ad05SGreg Clayton   if (log)
808324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::StepInstruction (step_over=%i)",
809324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()), step_over);
81017a6ad05SGreg Clayton 
811b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
8121ac04c30SGreg Clayton     Thread *thread = exe_ctx.GetThreadPtr();
813b9c1b51eSKate Stone     ThreadPlanSP new_plan_sp(
814b9c1b51eSKate Stone         thread->QueueThreadPlanForStepSingleInstruction(step_over, true, true));
81564e7ead1SJim Ingham 
81664e7ead1SJim Ingham     // This returns an error, we should use it!
8174d56e9c1SJim Ingham     ResumeNewPlan(exe_ctx, new_plan_sp.get());
81830fdc8d8SChris Lattner   }
81930fdc8d8SChris Lattner }
82030fdc8d8SChris Lattner 
821b9c1b51eSKate Stone void SBThread::RunToAddress(lldb::addr_t addr) {
8225160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
823ceb6b139SCaroline Tice 
824bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
825bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
826ceb6b139SCaroline Tice 
82717a6ad05SGreg Clayton   if (log)
828324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::RunToAddress (addr=0x%" PRIx64 ")",
829324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()), addr);
83017a6ad05SGreg Clayton 
831b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
8327ba6e991SJim Ingham     bool abort_other_plans = false;
83330fdc8d8SChris Lattner     bool stop_other_threads = true;
83430fdc8d8SChris Lattner 
835e72dfb32SGreg Clayton     Address target_addr(addr);
83630fdc8d8SChris Lattner 
8371ac04c30SGreg Clayton     Thread *thread = exe_ctx.GetThreadPtr();
8381ac04c30SGreg Clayton 
839b9c1b51eSKate Stone     ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
840b9c1b51eSKate Stone         abort_other_plans, target_addr, stop_other_threads));
84164e7ead1SJim Ingham 
84264e7ead1SJim Ingham     // This returns an error, we should use it!
8434d56e9c1SJim Ingham     ResumeNewPlan(exe_ctx, new_plan_sp.get());
84430fdc8d8SChris Lattner   }
84530fdc8d8SChris Lattner }
84630fdc8d8SChris Lattner 
847b9c1b51eSKate Stone SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
848b9c1b51eSKate Stone                                 lldb::SBFileSpec &sb_file_spec, uint32_t line) {
849481cef25SGreg Clayton   SBError sb_error;
8505160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
851481cef25SGreg Clayton   char path[PATH_MAX];
852481cef25SGreg Clayton 
853bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
854bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
8554fc6cb9cSJim Ingham 
856b57e4a1bSJason Molenda   StackFrameSP frame_sp(sb_frame.GetFrameSP());
85717a6ad05SGreg Clayton 
858b9c1b51eSKate Stone   if (log) {
859481cef25SGreg Clayton     SBStream frame_desc_strm;
860481cef25SGreg Clayton     sb_frame.GetDescription(frame_desc_strm);
861481cef25SGreg Clayton     sb_file_spec->GetPath(path, sizeof(path));
862b9c1b51eSKate Stone     log->Printf("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, "
863b9c1b51eSKate Stone                 "file+line = %s:%u)",
864324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()),
865b9c1b51eSKate Stone                 static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData(),
866b9c1b51eSKate Stone                 path, line);
867481cef25SGreg Clayton   }
868481cef25SGreg Clayton 
869b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
8701ac04c30SGreg Clayton     Target *target = exe_ctx.GetTargetPtr();
8711ac04c30SGreg Clayton     Thread *thread = exe_ctx.GetThreadPtr();
872481cef25SGreg Clayton 
873b9c1b51eSKate Stone     if (line == 0) {
874481cef25SGreg Clayton       sb_error.SetErrorString("invalid line argument");
875481cef25SGreg Clayton       return sb_error;
876481cef25SGreg Clayton     }
877481cef25SGreg Clayton 
878b9c1b51eSKate Stone     if (!frame_sp) {
8791ac04c30SGreg Clayton       frame_sp = thread->GetSelectedFrame();
880481cef25SGreg Clayton       if (!frame_sp)
8811ac04c30SGreg Clayton         frame_sp = thread->GetStackFrameAtIndex(0);
882481cef25SGreg Clayton     }
883481cef25SGreg Clayton 
884481cef25SGreg Clayton     SymbolContext frame_sc;
885b9c1b51eSKate Stone     if (!frame_sp) {
886481cef25SGreg Clayton       sb_error.SetErrorString("no valid frames in thread to step");
887481cef25SGreg Clayton       return sb_error;
888481cef25SGreg Clayton     }
889481cef25SGreg Clayton 
890481cef25SGreg Clayton     // If we have a frame, get its line
891b9c1b51eSKate Stone     frame_sc = frame_sp->GetSymbolContext(
892b9c1b51eSKate Stone         eSymbolContextCompUnit | eSymbolContextFunction |
893b9c1b51eSKate Stone         eSymbolContextLineEntry | eSymbolContextSymbol);
894481cef25SGreg Clayton 
895b9c1b51eSKate Stone     if (frame_sc.comp_unit == NULL) {
896b9c1b51eSKate Stone       sb_error.SetErrorStringWithFormat(
897b9c1b51eSKate Stone           "frame %u doesn't have debug information", frame_sp->GetFrameIndex());
898481cef25SGreg Clayton       return sb_error;
899481cef25SGreg Clayton     }
900481cef25SGreg Clayton 
901481cef25SGreg Clayton     FileSpec step_file_spec;
902b9c1b51eSKate Stone     if (sb_file_spec.IsValid()) {
903481cef25SGreg Clayton       // The file spec passed in was valid, so use it
904481cef25SGreg Clayton       step_file_spec = sb_file_spec.ref();
905b9c1b51eSKate Stone     } else {
906481cef25SGreg Clayton       if (frame_sc.line_entry.IsValid())
907481cef25SGreg Clayton         step_file_spec = frame_sc.line_entry.file;
908b9c1b51eSKate Stone       else {
909481cef25SGreg Clayton         sb_error.SetErrorString("invalid file argument or no file for frame");
910481cef25SGreg Clayton         return sb_error;
911481cef25SGreg Clayton       }
912481cef25SGreg Clayton     }
913481cef25SGreg Clayton 
9149b70ddb3SJim Ingham     // Grab the current function, then we will make sure the "until" address is
9159b70ddb3SJim Ingham     // within the function.  We discard addresses that are out of the current
916b9c1b51eSKate Stone     // function, and then if there are no addresses remaining, give an
917b9c1b51eSKate Stone     // appropriate
9189b70ddb3SJim Ingham     // error message.
9199b70ddb3SJim Ingham 
9209b70ddb3SJim Ingham     bool all_in_function = true;
9219b70ddb3SJim Ingham     AddressRange fun_range = frame_sc.function->GetAddressRange();
9229b70ddb3SJim Ingham 
923481cef25SGreg Clayton     std::vector<addr_t> step_over_until_addrs;
9247ba6e991SJim Ingham     const bool abort_other_plans = false;
925c02e3344SJim Ingham     const bool stop_other_threads = false;
926481cef25SGreg Clayton     const bool check_inlines = true;
927481cef25SGreg Clayton     const bool exact = false;
928481cef25SGreg Clayton 
929481cef25SGreg Clayton     SymbolContextList sc_list;
930b9c1b51eSKate Stone     const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext(
931b9c1b51eSKate Stone         step_file_spec, line, check_inlines, exact, eSymbolContextLineEntry,
9329b70ddb3SJim Ingham         sc_list);
933b9c1b51eSKate Stone     if (num_matches > 0) {
934481cef25SGreg Clayton       SymbolContext sc;
935b9c1b51eSKate Stone       for (uint32_t i = 0; i < num_matches; ++i) {
936b9c1b51eSKate Stone         if (sc_list.GetContextAtIndex(i, sc)) {
937b9c1b51eSKate Stone           addr_t step_addr =
938b9c1b51eSKate Stone               sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
939b9c1b51eSKate Stone           if (step_addr != LLDB_INVALID_ADDRESS) {
9409b70ddb3SJim Ingham             if (fun_range.ContainsLoadAddress(step_addr, target))
941481cef25SGreg Clayton               step_over_until_addrs.push_back(step_addr);
9429b70ddb3SJim Ingham             else
9439b70ddb3SJim Ingham               all_in_function = false;
944481cef25SGreg Clayton           }
945481cef25SGreg Clayton         }
946481cef25SGreg Clayton       }
947481cef25SGreg Clayton     }
948481cef25SGreg Clayton 
949b9c1b51eSKate Stone     if (step_over_until_addrs.empty()) {
950b9c1b51eSKate Stone       if (all_in_function) {
951481cef25SGreg Clayton         step_file_spec.GetPath(path, sizeof(path));
952b9c1b51eSKate Stone         sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path,
953b9c1b51eSKate Stone                                           line);
954b9c1b51eSKate Stone       } else
95586edbf41SGreg Clayton         sb_error.SetErrorString("step until target not in current function");
956b9c1b51eSKate Stone     } else {
957b9c1b51eSKate Stone       ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepUntil(
958b9c1b51eSKate Stone           abort_other_plans, &step_over_until_addrs[0],
959b9c1b51eSKate Stone           step_over_until_addrs.size(), stop_other_threads,
9604d56e9c1SJim Ingham           frame_sp->GetFrameIndex()));
961481cef25SGreg Clayton 
9624d56e9c1SJim Ingham       sb_error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
963481cef25SGreg Clayton     }
964b9c1b51eSKate Stone   } else {
965481cef25SGreg Clayton     sb_error.SetErrorString("this SBThread object is invalid");
966481cef25SGreg Clayton   }
967481cef25SGreg Clayton   return sb_error;
968481cef25SGreg Clayton }
969481cef25SGreg Clayton 
970b9c1b51eSKate Stone SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name) {
971000ca185SOleksiy Vyalov   return StepUsingScriptedThreadPlan(script_class_name, true);
972c915a7d2SJim Ingham }
973c915a7d2SJim Ingham 
974b9c1b51eSKate Stone SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
975b9c1b51eSKate Stone                                               bool resume_immediately) {
9762bdbfd50SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
9772bdbfd50SJim Ingham   SBError sb_error;
9782bdbfd50SJim Ingham 
979bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
980bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
9812bdbfd50SJim Ingham 
982b9c1b51eSKate Stone   if (log) {
9832bdbfd50SJim Ingham     log->Printf("SBThread(%p)::StepUsingScriptedThreadPlan: class name: %s",
984b9c1b51eSKate Stone                 static_cast<void *>(exe_ctx.GetThreadPtr()), script_class_name);
9852bdbfd50SJim Ingham   }
9862bdbfd50SJim Ingham 
987b9c1b51eSKate Stone   if (!exe_ctx.HasThreadScope()) {
9882bdbfd50SJim Ingham     sb_error.SetErrorString("this SBThread object is invalid");
9892bdbfd50SJim Ingham     return sb_error;
9902bdbfd50SJim Ingham   }
9912bdbfd50SJim Ingham 
9922bdbfd50SJim Ingham   Thread *thread = exe_ctx.GetThreadPtr();
993b9c1b51eSKate Stone   ThreadPlanSP thread_plan_sp =
994b9c1b51eSKate Stone       thread->QueueThreadPlanForStepScripted(false, script_class_name, false);
9952bdbfd50SJim Ingham 
996b9c1b51eSKate Stone   if (!thread_plan_sp) {
997b9c1b51eSKate Stone     sb_error.SetErrorStringWithFormat(
998b9c1b51eSKate Stone         "Error queueing thread plan for class: %s", script_class_name);
999c915a7d2SJim Ingham     return sb_error;
1000c915a7d2SJim Ingham   }
1001c915a7d2SJim Ingham 
1002b9c1b51eSKate Stone   if (!resume_immediately) {
1003c915a7d2SJim Ingham     return sb_error;
1004c915a7d2SJim Ingham   }
1005c915a7d2SJim Ingham 
10062bdbfd50SJim Ingham   if (thread_plan_sp)
10072bdbfd50SJim Ingham     sb_error = ResumeNewPlan(exe_ctx, thread_plan_sp.get());
1008b9c1b51eSKate Stone   else {
1009b9c1b51eSKate Stone     sb_error.SetErrorStringWithFormat(
1010b9c1b51eSKate Stone         "Error resuming thread plan for class: %s.", script_class_name);
10112bdbfd50SJim Ingham     if (log)
1012b9c1b51eSKate Stone       log->Printf("SBThread(%p)::StepUsingScriptedThreadPlan: Error queuing "
1013b9c1b51eSKate Stone                   "thread plan for class: %s",
10142bdbfd50SJim Ingham                   static_cast<void *>(exe_ctx.GetThreadPtr()),
10152bdbfd50SJim Ingham                   script_class_name);
10162bdbfd50SJim Ingham   }
10172bdbfd50SJim Ingham 
10182bdbfd50SJim Ingham   return sb_error;
10192bdbfd50SJim Ingham }
10202bdbfd50SJim Ingham 
1021b9c1b51eSKate Stone SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) {
1022f86248d9SRichard Mitton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1023f86248d9SRichard Mitton   SBError sb_error;
1024f86248d9SRichard Mitton 
1025bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
1026bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1027f86248d9SRichard Mitton 
1028f86248d9SRichard Mitton   if (log)
1029324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::JumpToLine (file+line = %s:%u)",
1030324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()),
1031324a1036SSaleem Abdulrasool                 file_spec->GetPath().c_str(), line);
1032f86248d9SRichard Mitton 
1033b9c1b51eSKate Stone   if (!exe_ctx.HasThreadScope()) {
1034f86248d9SRichard Mitton     sb_error.SetErrorString("this SBThread object is invalid");
1035f86248d9SRichard Mitton     return sb_error;
1036f86248d9SRichard Mitton   }
1037f86248d9SRichard Mitton 
1038f86248d9SRichard Mitton   Thread *thread = exe_ctx.GetThreadPtr();
1039f86248d9SRichard Mitton 
1040*97206d57SZachary Turner   Status err = thread->JumpToLine(file_spec.get(), line, true);
1041f86248d9SRichard Mitton   sb_error.SetError(err);
1042f86248d9SRichard Mitton   return sb_error;
1043f86248d9SRichard Mitton }
1044f86248d9SRichard Mitton 
1045b9c1b51eSKate Stone SBError SBThread::ReturnFromFrame(SBFrame &frame, SBValue &return_value) {
10464413758cSJim Ingham   SBError sb_error;
10474413758cSJim Ingham 
10485160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
10494413758cSJim Ingham 
1050bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
1051bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10524413758cSJim Ingham 
10534413758cSJim Ingham   if (log)
1054324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::ReturnFromFrame (frame=%d)",
1055324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()),
1056324a1036SSaleem Abdulrasool                 frame.GetFrameID());
10574413758cSJim Ingham 
1058b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
10594413758cSJim Ingham     Thread *thread = exe_ctx.GetThreadPtr();
1060b9c1b51eSKate Stone     sb_error.SetError(
1061b9c1b51eSKate Stone         thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
10624413758cSJim Ingham   }
10634413758cSJim Ingham 
10644413758cSJim Ingham   return sb_error;
10654413758cSJim Ingham }
10664413758cSJim Ingham 
1067b9c1b51eSKate Stone SBError SBThread::UnwindInnermostExpression() {
10684ac8e93aSJim Ingham   SBError sb_error;
10694ac8e93aSJim Ingham 
10704ac8e93aSJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
10714ac8e93aSJim Ingham 
10724ac8e93aSJim Ingham   std::unique_lock<std::recursive_mutex> lock;
10734ac8e93aSJim Ingham   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10744ac8e93aSJim Ingham 
10754ac8e93aSJim Ingham   if (log)
10764ac8e93aSJim Ingham     log->Printf("SBThread(%p)::UnwindExpressionEvaluation",
10774ac8e93aSJim Ingham                 static_cast<void *>(exe_ctx.GetThreadPtr()));
10784ac8e93aSJim Ingham 
1079b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
10804ac8e93aSJim Ingham     Thread *thread = exe_ctx.GetThreadPtr();
10814ac8e93aSJim Ingham     sb_error.SetError(thread->UnwindInnermostExpression());
10824ac8e93aSJim Ingham     if (sb_error.Success())
10834ac8e93aSJim Ingham       thread->SetSelectedFrameByIndex(0, false);
10844ac8e93aSJim Ingham   }
10854ac8e93aSJim Ingham 
10864ac8e93aSJim Ingham   return sb_error;
10874ac8e93aSJim Ingham }
1088481cef25SGreg Clayton 
1089b9c1b51eSKate Stone bool SBThread::Suspend() {
10905160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1091b2e7d28eSJim Ingham   std::unique_lock<std::recursive_mutex> lock;
1092b2e7d28eSJim Ingham   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1093b2e7d28eSJim Ingham 
1094c9858e4dSGreg Clayton   bool result = false;
1095b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
1096c9858e4dSGreg Clayton     Process::StopLocker stop_locker;
1097b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
10981ac04c30SGreg Clayton       exe_ctx.GetThreadPtr()->SetResumeState(eStateSuspended);
1099c9858e4dSGreg Clayton       result = true;
1100b9c1b51eSKate Stone     } else {
1101c9858e4dSGreg Clayton       if (log)
1102324a1036SSaleem Abdulrasool         log->Printf("SBThread(%p)::Suspend() => error: process is running",
1103324a1036SSaleem Abdulrasool                     static_cast<void *>(exe_ctx.GetThreadPtr()));
1104c9858e4dSGreg Clayton     }
1105c9858e4dSGreg Clayton   }
1106c9858e4dSGreg Clayton   if (log)
1107324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::Suspend() => %i",
1108324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()), result);
1109c9858e4dSGreg Clayton   return result;
1110722a0cdcSGreg Clayton }
1111722a0cdcSGreg Clayton 
1112b9c1b51eSKate Stone bool SBThread::Resume() {
11135160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1114b2e7d28eSJim Ingham   std::unique_lock<std::recursive_mutex> lock;
1115b2e7d28eSJim Ingham   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1116b2e7d28eSJim Ingham 
1117c9858e4dSGreg Clayton   bool result = false;
1118b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
1119c9858e4dSGreg Clayton     Process::StopLocker stop_locker;
1120b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
11216c9ed91cSJim Ingham       const bool override_suspend = true;
11226c9ed91cSJim Ingham       exe_ctx.GetThreadPtr()->SetResumeState(eStateRunning, override_suspend);
1123c9858e4dSGreg Clayton       result = true;
1124b9c1b51eSKate Stone     } else {
1125c9858e4dSGreg Clayton       if (log)
1126324a1036SSaleem Abdulrasool         log->Printf("SBThread(%p)::Resume() => error: process is running",
1127324a1036SSaleem Abdulrasool                     static_cast<void *>(exe_ctx.GetThreadPtr()));
1128c9858e4dSGreg Clayton     }
1129c9858e4dSGreg Clayton   }
1130c9858e4dSGreg Clayton   if (log)
1131324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::Resume() => %i",
1132324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()), result);
1133c9858e4dSGreg Clayton   return result;
1134722a0cdcSGreg Clayton }
1135722a0cdcSGreg Clayton 
1136b9c1b51eSKate Stone bool SBThread::IsSuspended() {
1137b2e7d28eSJim Ingham   std::unique_lock<std::recursive_mutex> lock;
1138b2e7d28eSJim Ingham   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1139b2e7d28eSJim Ingham 
11401ac04c30SGreg Clayton   if (exe_ctx.HasThreadScope())
11411ac04c30SGreg Clayton     return exe_ctx.GetThreadPtr()->GetResumeState() == eStateSuspended;
1142722a0cdcSGreg Clayton   return false;
1143722a0cdcSGreg Clayton }
1144722a0cdcSGreg Clayton 
1145b9c1b51eSKate Stone bool SBThread::IsStopped() {
1146b2e7d28eSJim Ingham   std::unique_lock<std::recursive_mutex> lock;
1147b2e7d28eSJim Ingham   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1148b2e7d28eSJim Ingham 
1149a75418dbSAndrew Kaylor   if (exe_ctx.HasThreadScope())
1150a75418dbSAndrew Kaylor     return StateIsStoppedState(exe_ctx.GetThreadPtr()->GetState(), true);
1151a75418dbSAndrew Kaylor   return false;
1152a75418dbSAndrew Kaylor }
1153a75418dbSAndrew Kaylor 
1154b9c1b51eSKate Stone SBProcess SBThread::GetProcess() {
1155b9556accSGreg Clayton   SBProcess sb_process;
1156b2e7d28eSJim Ingham   std::unique_lock<std::recursive_mutex> lock;
1157b2e7d28eSJim Ingham   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1158b2e7d28eSJim Ingham 
1159b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
1160b9c1b51eSKate Stone     // Have to go up to the target so we can get a shared pointer to our
1161b9c1b51eSKate Stone     // process...
11621ac04c30SGreg Clayton     sb_process.SetSP(exe_ctx.GetProcessSP());
116330fdc8d8SChris Lattner   }
1164ceb6b139SCaroline Tice 
11655160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1166b9c1b51eSKate Stone   if (log) {
1167481cef25SGreg Clayton     SBStream frame_desc_strm;
1168b9556accSGreg Clayton     sb_process.GetDescription(frame_desc_strm);
1169324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::GetProcess () => SBProcess(%p): %s",
1170324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()),
1171324a1036SSaleem Abdulrasool                 static_cast<void *>(sb_process.GetSP().get()),
1172324a1036SSaleem Abdulrasool                 frame_desc_strm.GetData());
1173ceb6b139SCaroline Tice   }
1174ceb6b139SCaroline Tice 
1175b9556accSGreg Clayton   return sb_process;
117630fdc8d8SChris Lattner }
117730fdc8d8SChris Lattner 
1178b9c1b51eSKate Stone uint32_t SBThread::GetNumFrames() {
11795160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1180ceb6b139SCaroline Tice 
1181ceb6b139SCaroline Tice   uint32_t num_frames = 0;
1182bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
1183bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
11844fc6cb9cSJim Ingham 
1185b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
11867fdf9ef1SGreg Clayton     Process::StopLocker stop_locker;
1187b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
11881ac04c30SGreg Clayton       num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount();
1189b9c1b51eSKate Stone     } else {
1190c9858e4dSGreg Clayton       if (log)
1191324a1036SSaleem Abdulrasool         log->Printf("SBThread(%p)::GetNumFrames() => error: process is running",
1192324a1036SSaleem Abdulrasool                     static_cast<void *>(exe_ctx.GetThreadPtr()));
1193c9858e4dSGreg Clayton     }
11947fdf9ef1SGreg Clayton   }
1195ceb6b139SCaroline Tice 
1196ceb6b139SCaroline Tice   if (log)
1197324a1036SSaleem Abdulrasool     log->Printf("SBThread(%p)::GetNumFrames () => %u",
1198324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()), num_frames);
1199ceb6b139SCaroline Tice 
1200ceb6b139SCaroline Tice   return num_frames;
120130fdc8d8SChris Lattner }
120230fdc8d8SChris Lattner 
1203b9c1b51eSKate Stone SBFrame SBThread::GetFrameAtIndex(uint32_t idx) {
12045160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1205ceb6b139SCaroline Tice 
120630fdc8d8SChris Lattner   SBFrame sb_frame;
1207b57e4a1bSJason Molenda   StackFrameSP frame_sp;
1208bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
1209bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12104fc6cb9cSJim Ingham 
1211b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
12127fdf9ef1SGreg Clayton     Process::StopLocker stop_locker;
1213b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
12141ac04c30SGreg Clayton       frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx);
1215b9556accSGreg Clayton       sb_frame.SetFrameSP(frame_sp);
1216b9c1b51eSKate Stone     } else {
1217c9858e4dSGreg Clayton       if (log)
1218b9c1b51eSKate Stone         log->Printf(
1219b9c1b51eSKate Stone             "SBThread(%p)::GetFrameAtIndex() => error: process is running",
1220324a1036SSaleem Abdulrasool             static_cast<void *>(exe_ctx.GetThreadPtr()));
1221c9858e4dSGreg Clayton     }
12227fdf9ef1SGreg Clayton   }
1223ceb6b139SCaroline Tice 
1224b9c1b51eSKate Stone   if (log) {
1225481cef25SGreg Clayton     SBStream frame_desc_strm;
1226481cef25SGreg Clayton     sb_frame.GetDescription(frame_desc_strm);
12274838131bSGreg Clayton     log->Printf("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s",
1228324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()), idx,
1229b9c1b51eSKate Stone                 static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
1230ceb6b139SCaroline Tice   }
1231ceb6b139SCaroline Tice 
123230fdc8d8SChris Lattner   return sb_frame;
123330fdc8d8SChris Lattner }
123430fdc8d8SChris Lattner 
1235b9c1b51eSKate Stone lldb::SBFrame SBThread::GetSelectedFrame() {
12365160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1237f028a1fbSGreg Clayton 
1238f028a1fbSGreg Clayton   SBFrame sb_frame;
1239b57e4a1bSJason Molenda   StackFrameSP frame_sp;
1240bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
1241bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12424fc6cb9cSJim Ingham 
1243b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
12447fdf9ef1SGreg Clayton     Process::StopLocker stop_locker;
1245b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
12461ac04c30SGreg Clayton       frame_sp = exe_ctx.GetThreadPtr()->GetSelectedFrame();
1247b9556accSGreg Clayton       sb_frame.SetFrameSP(frame_sp);
1248b9c1b51eSKate Stone     } else {
1249c9858e4dSGreg Clayton       if (log)
1250b9c1b51eSKate Stone         log->Printf(
1251b9c1b51eSKate Stone             "SBThread(%p)::GetSelectedFrame() => error: process is running",
1252324a1036SSaleem Abdulrasool             static_cast<void *>(exe_ctx.GetThreadPtr()));
1253c9858e4dSGreg Clayton     }
12547fdf9ef1SGreg Clayton   }
1255f028a1fbSGreg Clayton 
1256b9c1b51eSKate Stone   if (log) {
1257481cef25SGreg Clayton     SBStream frame_desc_strm;
1258481cef25SGreg Clayton     sb_frame.GetDescription(frame_desc_strm);
1259f028a1fbSGreg Clayton     log->Printf("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s",
1260324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()),
1261b9c1b51eSKate Stone                 static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
1262f028a1fbSGreg Clayton   }
1263f028a1fbSGreg Clayton 
1264f028a1fbSGreg Clayton   return sb_frame;
1265f028a1fbSGreg Clayton }
1266f028a1fbSGreg Clayton 
1267b9c1b51eSKate Stone lldb::SBFrame SBThread::SetSelectedFrame(uint32_t idx) {
12685160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1269f028a1fbSGreg Clayton 
1270f028a1fbSGreg Clayton   SBFrame sb_frame;
1271b57e4a1bSJason Molenda   StackFrameSP frame_sp;
1272bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
1273bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12744fc6cb9cSJim Ingham 
1275b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
12767fdf9ef1SGreg Clayton     Process::StopLocker stop_locker;
1277b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
12781ac04c30SGreg Clayton       Thread *thread = exe_ctx.GetThreadPtr();
12791ac04c30SGreg Clayton       frame_sp = thread->GetStackFrameAtIndex(idx);
1280b9c1b51eSKate Stone       if (frame_sp) {
12811ac04c30SGreg Clayton         thread->SetSelectedFrame(frame_sp.get());
1282b9556accSGreg Clayton         sb_frame.SetFrameSP(frame_sp);
1283f028a1fbSGreg Clayton       }
1284b9c1b51eSKate Stone     } else {
1285c9858e4dSGreg Clayton       if (log)
1286b9c1b51eSKate Stone         log->Printf(
1287b9c1b51eSKate Stone             "SBThread(%p)::SetSelectedFrame() => error: process is running",
1288324a1036SSaleem Abdulrasool             static_cast<void *>(exe_ctx.GetThreadPtr()));
1289c9858e4dSGreg Clayton     }
12907fdf9ef1SGreg Clayton   }
1291f028a1fbSGreg Clayton 
1292b9c1b51eSKate Stone   if (log) {
1293481cef25SGreg Clayton     SBStream frame_desc_strm;
1294481cef25SGreg Clayton     sb_frame.GetDescription(frame_desc_strm);
1295f028a1fbSGreg Clayton     log->Printf("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s",
1296324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()), idx,
1297b9c1b51eSKate Stone                 static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
1298f028a1fbSGreg Clayton   }
1299f028a1fbSGreg Clayton   return sb_frame;
1300f028a1fbSGreg Clayton }
1301f028a1fbSGreg Clayton 
1302b9c1b51eSKate Stone bool SBThread::EventIsThreadEvent(const SBEvent &event) {
13034f465cffSJim Ingham   return Thread::ThreadEventData::GetEventDataFromEvent(event.get()) != NULL;
13044f465cffSJim Ingham }
13054f465cffSJim Ingham 
1306b9c1b51eSKate Stone SBFrame SBThread::GetStackFrameFromEvent(const SBEvent &event) {
13074f465cffSJim Ingham   return Thread::ThreadEventData::GetStackFrameFromEvent(event.get());
13084f465cffSJim Ingham }
13094f465cffSJim Ingham 
1310b9c1b51eSKate Stone SBThread SBThread::GetThreadFromEvent(const SBEvent &event) {
13114f465cffSJim Ingham   return Thread::ThreadEventData::GetThreadFromEvent(event.get());
13124f465cffSJim Ingham }
1313f028a1fbSGreg Clayton 
1314b9c1b51eSKate Stone bool SBThread::operator==(const SBThread &rhs) const {
1315b9c1b51eSKate Stone   return m_opaque_sp->GetThreadSP().get() ==
1316b9c1b51eSKate Stone          rhs.m_opaque_sp->GetThreadSP().get();
131730fdc8d8SChris Lattner }
131830fdc8d8SChris Lattner 
1319b9c1b51eSKate Stone bool SBThread::operator!=(const SBThread &rhs) const {
1320b9c1b51eSKate Stone   return m_opaque_sp->GetThreadSP().get() !=
1321b9c1b51eSKate Stone          rhs.m_opaque_sp->GetThreadSP().get();
132230fdc8d8SChris Lattner }
1323dde9cff3SCaroline Tice 
1324b9c1b51eSKate Stone bool SBThread::GetStatus(SBStream &status) const {
13254f465cffSJim Ingham   Stream &strm = status.ref();
13264f465cffSJim Ingham 
1327b2e7d28eSJim Ingham   std::unique_lock<std::recursive_mutex> lock;
1328b2e7d28eSJim Ingham   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1329b2e7d28eSJim Ingham 
1330b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
13316a9767c7SJim Ingham     exe_ctx.GetThreadPtr()->GetStatus(strm, 0, 1, 1, true);
1332b9c1b51eSKate Stone   } else
13334f465cffSJim Ingham     strm.PutCString("No status");
13344f465cffSJim Ingham 
13354f465cffSJim Ingham   return true;
13364f465cffSJim Ingham }
13374f465cffSJim Ingham 
1338b9c1b51eSKate Stone bool SBThread::GetDescription(SBStream &description) const {
13396a9767c7SJim Ingham     return GetDescription(description, false);
13406a9767c7SJim Ingham }
13416a9767c7SJim Ingham 
13426a9767c7SJim Ingham bool SBThread::GetDescription(SBStream &description, bool stop_format) const {
1343da7bc7d0SGreg Clayton   Stream &strm = description.ref();
1344da7bc7d0SGreg Clayton 
1345b2e7d28eSJim Ingham   std::unique_lock<std::recursive_mutex> lock;
1346b2e7d28eSJim Ingham   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1347b2e7d28eSJim Ingham 
1348b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
1349b9c1b51eSKate Stone     exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat(strm,
13506a9767c7SJim Ingham                                                     LLDB_INVALID_THREAD_ID,
13516a9767c7SJim Ingham                                                     stop_format);
1352b9c1b51eSKate Stone     // strm.Printf("SBThread: tid = 0x%4.4" PRIx64,
1353b9c1b51eSKate Stone     // exe_ctx.GetThreadPtr()->GetID());
1354b9c1b51eSKate Stone   } else
1355da7bc7d0SGreg Clayton     strm.PutCString("No value");
1356ceb6b139SCaroline Tice 
1357ceb6b139SCaroline Tice   return true;
1358ceb6b139SCaroline Tice }
13595dd4916fSJason Molenda 
1360b9c1b51eSKate Stone SBThread SBThread::GetExtendedBacktraceThread(const char *type) {
13615dd4916fSJason Molenda   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1362bb19a13cSSaleem Abdulrasool   std::unique_lock<std::recursive_mutex> lock;
1363bb19a13cSSaleem Abdulrasool   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
13645dd4916fSJason Molenda   SBThread sb_origin_thread;
13655dd4916fSJason Molenda 
1366b9c1b51eSKate Stone   if (exe_ctx.HasThreadScope()) {
13675dd4916fSJason Molenda     Process::StopLocker stop_locker;
1368b9c1b51eSKate Stone     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
13697a2f7904SJason Molenda       ThreadSP real_thread(exe_ctx.GetThreadSP());
1370b9c1b51eSKate Stone       if (real_thread) {
13715dd4916fSJason Molenda         ConstString type_const(type);
13727a2f7904SJason Molenda         Process *process = exe_ctx.GetProcessPtr();
1373b9c1b51eSKate Stone         if (process) {
13747a2f7904SJason Molenda           SystemRuntime *runtime = process->GetSystemRuntime();
1375b9c1b51eSKate Stone           if (runtime) {
1376b9c1b51eSKate Stone             ThreadSP new_thread_sp(
1377b9c1b51eSKate Stone                 runtime->GetExtendedBacktraceThread(real_thread, type_const));
1378b9c1b51eSKate Stone             if (new_thread_sp) {
1379b9c1b51eSKate Stone               // Save this in the Process' ExtendedThreadList so a strong
1380b9c1b51eSKate Stone               // pointer retains the
13817a2f7904SJason Molenda               // object.
13827a2f7904SJason Molenda               process->GetExtendedThreadList().AddThread(new_thread_sp);
13837a2f7904SJason Molenda               sb_origin_thread.SetThread(new_thread_sp);
1384b9c1b51eSKate Stone               if (log) {
1385a6e9130dSJason Molenda                 const char *queue_name = new_thread_sp->GetQueueName();
1386a6e9130dSJason Molenda                 if (queue_name == NULL)
1387a6e9130dSJason Molenda                   queue_name = "";
1388b9c1b51eSKate Stone                 log->Printf("SBThread(%p)::GetExtendedBacktraceThread() => new "
1389b9c1b51eSKate Stone                             "extended Thread "
1390b9c1b51eSKate Stone                             "created (%p) with queue_id 0x%" PRIx64
1391b9c1b51eSKate Stone                             " queue name '%s'",
1392324a1036SSaleem Abdulrasool                             static_cast<void *>(exe_ctx.GetThreadPtr()),
1393324a1036SSaleem Abdulrasool                             static_cast<void *>(new_thread_sp.get()),
1394b9c1b51eSKate Stone                             new_thread_sp->GetQueueID(), queue_name);
1395a6e9130dSJason Molenda               }
1396a6e9130dSJason Molenda             }
13977a2f7904SJason Molenda           }
13985dd4916fSJason Molenda         }
13995dd4916fSJason Molenda       }
1400b9c1b51eSKate Stone     } else {
14015dd4916fSJason Molenda       if (log)
1402b9c1b51eSKate Stone         log->Printf("SBThread(%p)::GetExtendedBacktraceThread() => error: "
1403b9c1b51eSKate Stone                     "process is running",
1404324a1036SSaleem Abdulrasool                     static_cast<void *>(exe_ctx.GetThreadPtr()));
14055dd4916fSJason Molenda     }
14065dd4916fSJason Molenda   }
14075dd4916fSJason Molenda 
1408ac605f4aSJason Molenda   if (log && sb_origin_thread.IsValid() == false)
1409b9c1b51eSKate Stone     log->Printf("SBThread(%p)::GetExtendedBacktraceThread() is not returning a "
1410b9c1b51eSKate Stone                 "Valid thread",
1411324a1036SSaleem Abdulrasool                 static_cast<void *>(exe_ctx.GetThreadPtr()));
14125dd4916fSJason Molenda   return sb_origin_thread;
14135dd4916fSJason Molenda }
14148ee9cb58SJason Molenda 
1415b9c1b51eSKate Stone uint32_t SBThread::GetExtendedBacktraceOriginatingIndexID() {
14168ee9cb58SJason Molenda   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
14178ee9cb58SJason Molenda   if (thread_sp)
14188ee9cb58SJason Molenda     return thread_sp->GetExtendedBacktraceOriginatingIndexID();
14198ee9cb58SJason Molenda   return LLDB_INVALID_INDEX32;
14208ee9cb58SJason Molenda }
1421b4892cd2SJason Molenda 
1422b9c1b51eSKate Stone bool SBThread::SafeToCallFunctions() {
1423b4892cd2SJason Molenda   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
1424b4892cd2SJason Molenda   if (thread_sp)
1425b4892cd2SJason Molenda     return thread_sp->SafeToCallFunctions();
1426b4892cd2SJason Molenda   return true;
1427b4892cd2SJason Molenda }
14282bdbfd50SJim Ingham 
1429b9c1b51eSKate Stone lldb_private::Thread *SBThread::operator->() {
14302bdbfd50SJim Ingham   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
14312bdbfd50SJim Ingham   if (thread_sp)
14322bdbfd50SJim Ingham     return thread_sp.get();
14332bdbfd50SJim Ingham   else
14342bdbfd50SJim Ingham     return NULL;
14352bdbfd50SJim Ingham }
14362bdbfd50SJim Ingham 
1437b9c1b51eSKate Stone lldb_private::Thread *SBThread::get() {
14382bdbfd50SJim Ingham   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
14392bdbfd50SJim Ingham   if (thread_sp)
14402bdbfd50SJim Ingham     return thread_sp.get();
14412bdbfd50SJim Ingham   else
14422bdbfd50SJim Ingham     return NULL;
14432bdbfd50SJim Ingham }
1444