1ac7ddfbfSEd Maste //===-- SBThread.cpp --------------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste
10ac7ddfbfSEd Maste #include "lldb/API/SBThread.h"
11ac7ddfbfSEd Maste
12ac7ddfbfSEd Maste #include "lldb/API/SBFileSpec.h"
13ac7ddfbfSEd Maste #include "lldb/API/SBStream.h"
14435933ddSDimitry Andric #include "lldb/API/SBSymbolContext.h"
15ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
16ac7ddfbfSEd Maste #include "lldb/Core/Debugger.h"
17ac7ddfbfSEd Maste #include "lldb/Core/StreamFile.h"
181c3bbb01SEd Maste #include "lldb/Core/ValueObject.h"
19ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
201c3bbb01SEd Maste #include "lldb/Symbol/CompileUnit.h"
21435933ddSDimitry Andric #include "lldb/Symbol/SymbolContext.h"
22ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
230127ef0fSEd Maste #include "lldb/Target/Queue.h"
24ac7ddfbfSEd Maste #include "lldb/Target/StopInfo.h"
25435933ddSDimitry Andric #include "lldb/Target/SystemRuntime.h"
26ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
27435933ddSDimitry Andric #include "lldb/Target/Thread.h"
28ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlan.h"
29435933ddSDimitry Andric #include "lldb/Target/ThreadPlanStepInRange.h"
30ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepInstruction.h"
31ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepOut.h"
32ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepRange.h"
33435933ddSDimitry Andric #include "lldb/Target/UnixSignals.h"
34*b5893f02SDimitry Andric #include "lldb/Utility/State.h"
35f678e45dSDimitry Andric #include "lldb/Utility/Stream.h"
36a580b014SDimitry Andric #include "lldb/Utility/StructuredData.h"
37ac7ddfbfSEd Maste
38ac7ddfbfSEd Maste #include "lldb/API/SBAddress.h"
39ac7ddfbfSEd Maste #include "lldb/API/SBDebugger.h"
40ac7ddfbfSEd Maste #include "lldb/API/SBEvent.h"
41ac7ddfbfSEd Maste #include "lldb/API/SBFrame.h"
42ac7ddfbfSEd Maste #include "lldb/API/SBProcess.h"
434bb0738eSEd Maste #include "lldb/API/SBThreadCollection.h"
447aa51b79SEd Maste #include "lldb/API/SBThreadPlan.h"
45ac7ddfbfSEd Maste #include "lldb/API/SBValue.h"
46302affcbSDimitry Andric #include "lldb/lldb-enumerations.h"
47ac7ddfbfSEd Maste
48ac7ddfbfSEd Maste using namespace lldb;
49ac7ddfbfSEd Maste using namespace lldb_private;
50ac7ddfbfSEd Maste
GetBroadcasterClassName()51435933ddSDimitry Andric const char *SBThread::GetBroadcasterClassName() {
52ac7ddfbfSEd Maste return Thread::GetStaticBroadcasterClass().AsCString();
53ac7ddfbfSEd Maste }
54ac7ddfbfSEd Maste
55ac7ddfbfSEd Maste //----------------------------------------------------------------------
56ac7ddfbfSEd Maste // Constructors
57ac7ddfbfSEd Maste //----------------------------------------------------------------------
SBThread()58435933ddSDimitry Andric SBThread::SBThread() : m_opaque_sp(new ExecutionContextRef()) {}
59ac7ddfbfSEd Maste
SBThread(const ThreadSP & lldb_object_sp)60435933ddSDimitry Andric SBThread::SBThread(const ThreadSP &lldb_object_sp)
61435933ddSDimitry Andric : m_opaque_sp(new ExecutionContextRef(lldb_object_sp)) {}
62ac7ddfbfSEd Maste
SBThread(const SBThread & rhs)63435933ddSDimitry Andric SBThread::SBThread(const SBThread &rhs)
64435933ddSDimitry Andric : m_opaque_sp(new ExecutionContextRef(*rhs.m_opaque_sp)) {}
65ac7ddfbfSEd Maste
66ac7ddfbfSEd Maste //----------------------------------------------------------------------
67ac7ddfbfSEd Maste // Assignment operator
68ac7ddfbfSEd Maste //----------------------------------------------------------------------
69ac7ddfbfSEd Maste
operator =(const SBThread & rhs)70435933ddSDimitry Andric const lldb::SBThread &SBThread::operator=(const SBThread &rhs) {
71ac7ddfbfSEd Maste if (this != &rhs)
72ac7ddfbfSEd Maste *m_opaque_sp = *rhs.m_opaque_sp;
73ac7ddfbfSEd Maste return *this;
74ac7ddfbfSEd Maste }
75ac7ddfbfSEd Maste
76ac7ddfbfSEd Maste //----------------------------------------------------------------------
77ac7ddfbfSEd Maste // Destructor
78ac7ddfbfSEd Maste //----------------------------------------------------------------------
~SBThread()79435933ddSDimitry Andric SBThread::~SBThread() {}
80ac7ddfbfSEd Maste
GetQueue() const81435933ddSDimitry Andric lldb::SBQueue SBThread::GetQueue() const {
820127ef0fSEd Maste SBQueue sb_queue;
830127ef0fSEd Maste QueueSP queue_sp;
844bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
854bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
860127ef0fSEd Maste
870127ef0fSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
88435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
890127ef0fSEd Maste Process::StopLocker stop_locker;
90435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
910127ef0fSEd Maste queue_sp = exe_ctx.GetThreadPtr()->GetQueue();
92435933ddSDimitry Andric if (queue_sp) {
930127ef0fSEd Maste sb_queue.SetQueue(queue_sp);
940127ef0fSEd Maste }
95435933ddSDimitry Andric } else {
960127ef0fSEd Maste if (log)
971c3bbb01SEd Maste log->Printf("SBThread(%p)::GetQueue() => error: process is running",
980127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
990127ef0fSEd Maste }
1000127ef0fSEd Maste }
1010127ef0fSEd Maste
1020127ef0fSEd Maste if (log)
1031c3bbb01SEd Maste log->Printf("SBThread(%p)::GetQueue () => SBQueue(%p)",
104435933ddSDimitry Andric static_cast<void *>(exe_ctx.GetThreadPtr()),
105435933ddSDimitry Andric static_cast<void *>(queue_sp.get()));
1060127ef0fSEd Maste
1070127ef0fSEd Maste return sb_queue;
1080127ef0fSEd Maste }
1090127ef0fSEd Maste
IsValid() const110435933ddSDimitry Andric bool SBThread::IsValid() const {
1114bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
1124bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1134bb0738eSEd Maste
1144bb0738eSEd Maste Target *target = exe_ctx.GetTargetPtr();
1154bb0738eSEd Maste Process *process = exe_ctx.GetProcessPtr();
116435933ddSDimitry Andric if (target && process) {
1174bb0738eSEd Maste Process::StopLocker stop_locker;
1184bb0738eSEd Maste if (stop_locker.TryLock(&process->GetRunLock()))
119ac7ddfbfSEd Maste return m_opaque_sp->GetThreadSP().get() != NULL;
120ac7ddfbfSEd Maste }
1214bb0738eSEd Maste // Without a valid target & process, this thread can't be valid.
1224bb0738eSEd Maste return false;
1234bb0738eSEd Maste }
124ac7ddfbfSEd Maste
Clear()125435933ddSDimitry Andric void SBThread::Clear() { m_opaque_sp->Clear(); }
126ac7ddfbfSEd Maste
GetStopReason()127435933ddSDimitry Andric StopReason SBThread::GetStopReason() {
128ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
129ac7ddfbfSEd Maste
130ac7ddfbfSEd Maste StopReason reason = eStopReasonInvalid;
1314bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
1324bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
133ac7ddfbfSEd Maste
134435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
135ac7ddfbfSEd Maste Process::StopLocker stop_locker;
136435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
137ac7ddfbfSEd Maste return exe_ctx.GetThreadPtr()->GetStopReason();
138435933ddSDimitry Andric } else {
139ac7ddfbfSEd Maste if (log)
140435933ddSDimitry Andric log->Printf(
141435933ddSDimitry Andric "SBThread(%p)::GetStopReason() => error: process is running",
1420127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
143ac7ddfbfSEd Maste }
144ac7ddfbfSEd Maste }
145ac7ddfbfSEd Maste
146ac7ddfbfSEd Maste if (log)
1470127ef0fSEd Maste log->Printf("SBThread(%p)::GetStopReason () => %s",
1480127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
149ac7ddfbfSEd Maste Thread::StopReasonAsCString(reason));
150ac7ddfbfSEd Maste
151ac7ddfbfSEd Maste return reason;
152ac7ddfbfSEd Maste }
153ac7ddfbfSEd Maste
GetStopReasonDataCount()154435933ddSDimitry Andric size_t SBThread::GetStopReasonDataCount() {
1554bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
1564bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
157ac7ddfbfSEd Maste
158435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
159ac7ddfbfSEd Maste Process::StopLocker stop_locker;
160435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
161ac7ddfbfSEd Maste StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
162435933ddSDimitry Andric if (stop_info_sp) {
163ac7ddfbfSEd Maste StopReason reason = stop_info_sp->GetStopReason();
164435933ddSDimitry Andric switch (reason) {
165ac7ddfbfSEd Maste case eStopReasonInvalid:
166ac7ddfbfSEd Maste case eStopReasonNone:
167ac7ddfbfSEd Maste case eStopReasonTrace:
168ac7ddfbfSEd Maste case eStopReasonExec:
169ac7ddfbfSEd Maste case eStopReasonPlanComplete:
170ac7ddfbfSEd Maste case eStopReasonThreadExiting:
1717aa51b79SEd Maste case eStopReasonInstrumentation:
172ac7ddfbfSEd Maste // There is no data for these stop reasons.
173ac7ddfbfSEd Maste return 0;
174ac7ddfbfSEd Maste
175435933ddSDimitry Andric case eStopReasonBreakpoint: {
176ac7ddfbfSEd Maste break_id_t site_id = stop_info_sp->GetValue();
177435933ddSDimitry Andric lldb::BreakpointSiteSP bp_site_sp(
178435933ddSDimitry Andric exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
179435933ddSDimitry Andric site_id));
180ac7ddfbfSEd Maste if (bp_site_sp)
181ac7ddfbfSEd Maste return bp_site_sp->GetNumberOfOwners() * 2;
182ac7ddfbfSEd Maste else
183ac7ddfbfSEd Maste return 0; // Breakpoint must have cleared itself...
184435933ddSDimitry Andric } break;
185ac7ddfbfSEd Maste
186ac7ddfbfSEd Maste case eStopReasonWatchpoint:
187ac7ddfbfSEd Maste return 1;
188ac7ddfbfSEd Maste
189ac7ddfbfSEd Maste case eStopReasonSignal:
190ac7ddfbfSEd Maste return 1;
191ac7ddfbfSEd Maste
192ac7ddfbfSEd Maste case eStopReasonException:
193ac7ddfbfSEd Maste return 1;
194ac7ddfbfSEd Maste }
195ac7ddfbfSEd Maste }
196435933ddSDimitry Andric } else {
197ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
198ac7ddfbfSEd Maste if (log)
199435933ddSDimitry Andric log->Printf("SBThread(%p)::GetStopReasonDataCount() => error: process "
200435933ddSDimitry Andric "is running",
2010127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
202ac7ddfbfSEd Maste }
203ac7ddfbfSEd Maste }
204ac7ddfbfSEd Maste return 0;
205ac7ddfbfSEd Maste }
206ac7ddfbfSEd Maste
GetStopReasonDataAtIndex(uint32_t idx)207435933ddSDimitry Andric uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) {
2084bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
2094bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
210ac7ddfbfSEd Maste
211435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
212ac7ddfbfSEd Maste Process::StopLocker stop_locker;
213435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
214ac7ddfbfSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
215ac7ddfbfSEd Maste StopInfoSP stop_info_sp = thread->GetStopInfo();
216435933ddSDimitry Andric if (stop_info_sp) {
217ac7ddfbfSEd Maste StopReason reason = stop_info_sp->GetStopReason();
218435933ddSDimitry Andric switch (reason) {
219ac7ddfbfSEd Maste case eStopReasonInvalid:
220ac7ddfbfSEd Maste case eStopReasonNone:
221ac7ddfbfSEd Maste case eStopReasonTrace:
222ac7ddfbfSEd Maste case eStopReasonExec:
223ac7ddfbfSEd Maste case eStopReasonPlanComplete:
224ac7ddfbfSEd Maste case eStopReasonThreadExiting:
2257aa51b79SEd Maste case eStopReasonInstrumentation:
226ac7ddfbfSEd Maste // There is no data for these stop reasons.
227ac7ddfbfSEd Maste return 0;
228ac7ddfbfSEd Maste
229435933ddSDimitry Andric case eStopReasonBreakpoint: {
230ac7ddfbfSEd Maste break_id_t site_id = stop_info_sp->GetValue();
231435933ddSDimitry Andric lldb::BreakpointSiteSP bp_site_sp(
232435933ddSDimitry Andric exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
233435933ddSDimitry Andric site_id));
234435933ddSDimitry Andric if (bp_site_sp) {
235ac7ddfbfSEd Maste uint32_t bp_index = idx / 2;
236435933ddSDimitry Andric BreakpointLocationSP bp_loc_sp(
237435933ddSDimitry Andric bp_site_sp->GetOwnerAtIndex(bp_index));
238435933ddSDimitry Andric if (bp_loc_sp) {
239435933ddSDimitry Andric if (idx & 1) {
240ac7ddfbfSEd Maste // Odd idx, return the breakpoint location ID
241ac7ddfbfSEd Maste return bp_loc_sp->GetID();
242435933ddSDimitry Andric } else {
243ac7ddfbfSEd Maste // Even idx, return the breakpoint ID
244ac7ddfbfSEd Maste return bp_loc_sp->GetBreakpoint().GetID();
245ac7ddfbfSEd Maste }
246ac7ddfbfSEd Maste }
247ac7ddfbfSEd Maste }
248ac7ddfbfSEd Maste return LLDB_INVALID_BREAK_ID;
249435933ddSDimitry Andric } break;
250ac7ddfbfSEd Maste
251ac7ddfbfSEd Maste case eStopReasonWatchpoint:
252ac7ddfbfSEd Maste return stop_info_sp->GetValue();
253ac7ddfbfSEd Maste
254ac7ddfbfSEd Maste case eStopReasonSignal:
255ac7ddfbfSEd Maste return stop_info_sp->GetValue();
256ac7ddfbfSEd Maste
257ac7ddfbfSEd Maste case eStopReasonException:
258ac7ddfbfSEd Maste return stop_info_sp->GetValue();
259ac7ddfbfSEd Maste }
260ac7ddfbfSEd Maste }
261435933ddSDimitry Andric } else {
262ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
263ac7ddfbfSEd Maste if (log)
264435933ddSDimitry Andric log->Printf("SBThread(%p)::GetStopReasonDataAtIndex() => error: "
265435933ddSDimitry Andric "process is running",
2660127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
267ac7ddfbfSEd Maste }
268ac7ddfbfSEd Maste }
269ac7ddfbfSEd Maste return 0;
270ac7ddfbfSEd Maste }
271ac7ddfbfSEd Maste
GetStopReasonExtendedInfoAsJSON(lldb::SBStream & stream)272435933ddSDimitry Andric bool SBThread::GetStopReasonExtendedInfoAsJSON(lldb::SBStream &stream) {
2737aa51b79SEd Maste Stream &strm = stream.ref();
2747aa51b79SEd Maste
2754bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
2764bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
2774bb0738eSEd Maste
2787aa51b79SEd Maste if (!exe_ctx.HasThreadScope())
2797aa51b79SEd Maste return false;
2807aa51b79SEd Maste
2817aa51b79SEd Maste StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
2827aa51b79SEd Maste StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
2837aa51b79SEd Maste if (!info)
2847aa51b79SEd Maste return false;
2857aa51b79SEd Maste
2867aa51b79SEd Maste info->Dump(strm);
2877aa51b79SEd Maste
2887aa51b79SEd Maste return true;
2897aa51b79SEd Maste }
2907aa51b79SEd Maste
2914bb0738eSEd Maste SBThreadCollection
GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type)292435933ddSDimitry Andric SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) {
2934bb0738eSEd Maste ThreadCollectionSP threads;
2944bb0738eSEd Maste threads.reset(new ThreadCollection());
2954bb0738eSEd Maste
2964bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
2974bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
2984bb0738eSEd Maste
2994bb0738eSEd Maste if (!exe_ctx.HasThreadScope())
3004bb0738eSEd Maste return threads;
3014bb0738eSEd Maste
3024bb0738eSEd Maste ProcessSP process_sp = exe_ctx.GetProcessSP();
3034bb0738eSEd Maste
3044bb0738eSEd Maste StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
3054bb0738eSEd Maste StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
3064bb0738eSEd Maste if (!info)
3074bb0738eSEd Maste return threads;
3084bb0738eSEd Maste
309435933ddSDimitry Andric return process_sp->GetInstrumentationRuntime(type)
310435933ddSDimitry Andric ->GetBacktracesFromExtendedStopInfo(info);
3114bb0738eSEd Maste }
3124bb0738eSEd Maste
GetStopDescription(char * dst,size_t dst_len)313435933ddSDimitry Andric size_t SBThread::GetStopDescription(char *dst, size_t dst_len) {
314ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
315ac7ddfbfSEd Maste
3164bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
3174bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
318ac7ddfbfSEd Maste
319435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
320ac7ddfbfSEd Maste Process::StopLocker stop_locker;
321435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
322ac7ddfbfSEd Maste
323ac7ddfbfSEd Maste StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
324435933ddSDimitry Andric if (stop_info_sp) {
325ac7ddfbfSEd Maste const char *stop_desc = stop_info_sp->GetDescription();
326435933ddSDimitry Andric if (stop_desc) {
327ac7ddfbfSEd Maste if (log)
328435933ddSDimitry Andric log->Printf(
329435933ddSDimitry Andric "SBThread(%p)::GetStopDescription (dst, dst_len) => \"%s\"",
330435933ddSDimitry Andric static_cast<void *>(exe_ctx.GetThreadPtr()), stop_desc);
331ac7ddfbfSEd Maste if (dst)
332ac7ddfbfSEd Maste return ::snprintf(dst, dst_len, "%s", stop_desc);
333435933ddSDimitry Andric else {
334435933ddSDimitry Andric // NULL dst passed in, return the length needed to contain the
335435933ddSDimitry Andric // description
336ac7ddfbfSEd Maste return ::strlen(stop_desc) + 1; // Include the NULL byte for size
337ac7ddfbfSEd Maste }
338435933ddSDimitry Andric } else {
339ac7ddfbfSEd Maste size_t stop_desc_len = 0;
340435933ddSDimitry Andric switch (stop_info_sp->GetStopReason()) {
341ac7ddfbfSEd Maste case eStopReasonTrace:
342435933ddSDimitry Andric case eStopReasonPlanComplete: {
343ac7ddfbfSEd Maste static char trace_desc[] = "step";
344ac7ddfbfSEd Maste stop_desc = trace_desc;
345435933ddSDimitry Andric stop_desc_len =
346435933ddSDimitry Andric sizeof(trace_desc); // Include the NULL byte for size
347435933ddSDimitry Andric } break;
348ac7ddfbfSEd Maste
349435933ddSDimitry Andric case eStopReasonBreakpoint: {
350ac7ddfbfSEd Maste static char bp_desc[] = "breakpoint hit";
351ac7ddfbfSEd Maste stop_desc = bp_desc;
352ac7ddfbfSEd Maste stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
353435933ddSDimitry Andric } break;
354ac7ddfbfSEd Maste
355435933ddSDimitry Andric case eStopReasonWatchpoint: {
356ac7ddfbfSEd Maste static char wp_desc[] = "watchpoint hit";
357ac7ddfbfSEd Maste stop_desc = wp_desc;
358ac7ddfbfSEd Maste stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
359435933ddSDimitry Andric } break;
360ac7ddfbfSEd Maste
361435933ddSDimitry Andric case eStopReasonSignal: {
362435933ddSDimitry Andric stop_desc =
363435933ddSDimitry Andric exe_ctx.GetProcessPtr()->GetUnixSignals()->GetSignalAsCString(
364435933ddSDimitry Andric stop_info_sp->GetValue());
365435933ddSDimitry Andric if (stop_desc == NULL || stop_desc[0] == '\0') {
366ac7ddfbfSEd Maste static char signal_desc[] = "signal";
367ac7ddfbfSEd Maste stop_desc = signal_desc;
368435933ddSDimitry Andric stop_desc_len =
369435933ddSDimitry Andric sizeof(signal_desc); // Include the NULL byte for size
370ac7ddfbfSEd Maste }
371435933ddSDimitry Andric } break;
372ac7ddfbfSEd Maste
373435933ddSDimitry Andric case eStopReasonException: {
374ac7ddfbfSEd Maste char exc_desc[] = "exception";
375ac7ddfbfSEd Maste stop_desc = exc_desc;
376ac7ddfbfSEd Maste stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
377435933ddSDimitry Andric } break;
378ac7ddfbfSEd Maste
379435933ddSDimitry Andric case eStopReasonExec: {
380ac7ddfbfSEd Maste char exc_desc[] = "exec";
381ac7ddfbfSEd Maste stop_desc = exc_desc;
382ac7ddfbfSEd Maste stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
383435933ddSDimitry Andric } break;
384ac7ddfbfSEd Maste
385435933ddSDimitry Andric case eStopReasonThreadExiting: {
386ac7ddfbfSEd Maste char limbo_desc[] = "thread exiting";
387ac7ddfbfSEd Maste stop_desc = limbo_desc;
388ac7ddfbfSEd Maste stop_desc_len = sizeof(limbo_desc);
389435933ddSDimitry Andric } break;
390ac7ddfbfSEd Maste default:
391ac7ddfbfSEd Maste break;
392ac7ddfbfSEd Maste }
393ac7ddfbfSEd Maste
394435933ddSDimitry Andric if (stop_desc && stop_desc[0]) {
395ac7ddfbfSEd Maste if (log)
396435933ddSDimitry Andric log->Printf(
397435933ddSDimitry Andric "SBThread(%p)::GetStopDescription (dst, dst_len) => '%s'",
398435933ddSDimitry Andric static_cast<void *>(exe_ctx.GetThreadPtr()), stop_desc);
399ac7ddfbfSEd Maste
400ac7ddfbfSEd Maste if (dst)
401435933ddSDimitry Andric return ::snprintf(dst, dst_len, "%s", stop_desc) +
402435933ddSDimitry Andric 1; // Include the NULL byte
403ac7ddfbfSEd Maste
404ac7ddfbfSEd Maste if (stop_desc_len == 0)
405ac7ddfbfSEd Maste stop_desc_len = ::strlen(stop_desc) + 1; // Include the NULL byte
406ac7ddfbfSEd Maste
407ac7ddfbfSEd Maste return stop_desc_len;
408ac7ddfbfSEd Maste }
409ac7ddfbfSEd Maste }
410ac7ddfbfSEd Maste }
411435933ddSDimitry Andric } else {
412ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
413ac7ddfbfSEd Maste if (log)
414435933ddSDimitry Andric log->Printf(
415435933ddSDimitry Andric "SBThread(%p)::GetStopDescription() => error: process is running",
4160127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
417ac7ddfbfSEd Maste }
418ac7ddfbfSEd Maste }
419ac7ddfbfSEd Maste if (dst)
420ac7ddfbfSEd Maste *dst = 0;
421ac7ddfbfSEd Maste return 0;
422ac7ddfbfSEd Maste }
423ac7ddfbfSEd Maste
GetStopReturnValue()424435933ddSDimitry Andric SBValue SBThread::GetStopReturnValue() {
425ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
426ac7ddfbfSEd Maste ValueObjectSP return_valobj_sp;
4274bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
4284bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
429ac7ddfbfSEd Maste
430435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
431ac7ddfbfSEd Maste Process::StopLocker stop_locker;
432435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
433ac7ddfbfSEd Maste StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
434435933ddSDimitry Andric if (stop_info_sp) {
435ac7ddfbfSEd Maste return_valobj_sp = StopInfo::GetReturnValueObject(stop_info_sp);
436ac7ddfbfSEd Maste }
437435933ddSDimitry Andric } else {
438ac7ddfbfSEd Maste if (log)
439435933ddSDimitry Andric log->Printf(
440435933ddSDimitry Andric "SBThread(%p)::GetStopReturnValue() => error: process is running",
4410127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
442ac7ddfbfSEd Maste }
443ac7ddfbfSEd Maste }
444ac7ddfbfSEd Maste
445ac7ddfbfSEd Maste if (log)
4460127ef0fSEd Maste log->Printf("SBThread(%p)::GetStopReturnValue () => %s",
4470127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
448435933ddSDimitry Andric return_valobj_sp.get() ? return_valobj_sp->GetValueAsCString()
449ac7ddfbfSEd Maste : "<no return value>");
450ac7ddfbfSEd Maste
451ac7ddfbfSEd Maste return SBValue(return_valobj_sp);
452ac7ddfbfSEd Maste }
453ac7ddfbfSEd Maste
SetThread(const ThreadSP & lldb_object_sp)454435933ddSDimitry Andric void SBThread::SetThread(const ThreadSP &lldb_object_sp) {
455ac7ddfbfSEd Maste m_opaque_sp->SetThreadSP(lldb_object_sp);
456ac7ddfbfSEd Maste }
457ac7ddfbfSEd Maste
GetThreadID() const458435933ddSDimitry Andric lldb::tid_t SBThread::GetThreadID() const {
459ac7ddfbfSEd Maste ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
460ac7ddfbfSEd Maste if (thread_sp)
461ac7ddfbfSEd Maste return thread_sp->GetID();
462ac7ddfbfSEd Maste return LLDB_INVALID_THREAD_ID;
463ac7ddfbfSEd Maste }
464ac7ddfbfSEd Maste
GetIndexID() const465435933ddSDimitry Andric uint32_t SBThread::GetIndexID() const {
466ac7ddfbfSEd Maste ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
467ac7ddfbfSEd Maste if (thread_sp)
468ac7ddfbfSEd Maste return thread_sp->GetIndexID();
469ac7ddfbfSEd Maste return LLDB_INVALID_INDEX32;
470ac7ddfbfSEd Maste }
471ac7ddfbfSEd Maste
GetName() const472435933ddSDimitry Andric const char *SBThread::GetName() const {
473ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
474ac7ddfbfSEd Maste const char *name = NULL;
4754bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
4764bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
477ac7ddfbfSEd Maste
478435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
479ac7ddfbfSEd Maste Process::StopLocker stop_locker;
480435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
481ac7ddfbfSEd Maste name = exe_ctx.GetThreadPtr()->GetName();
482435933ddSDimitry Andric } else {
483ac7ddfbfSEd Maste if (log)
4840127ef0fSEd Maste log->Printf("SBThread(%p)::GetName() => error: process is running",
4850127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
486ac7ddfbfSEd Maste }
487ac7ddfbfSEd Maste }
488ac7ddfbfSEd Maste
489ac7ddfbfSEd Maste if (log)
4900127ef0fSEd Maste log->Printf("SBThread(%p)::GetName () => %s",
4910127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
4920127ef0fSEd Maste name ? name : "NULL");
493ac7ddfbfSEd Maste
494ac7ddfbfSEd Maste return name;
495ac7ddfbfSEd Maste }
496ac7ddfbfSEd Maste
GetQueueName() const497435933ddSDimitry Andric const char *SBThread::GetQueueName() const {
498ac7ddfbfSEd Maste const char *name = NULL;
4994bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
5004bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
501ac7ddfbfSEd Maste
502ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
503435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
504ac7ddfbfSEd Maste Process::StopLocker stop_locker;
505435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
506ac7ddfbfSEd Maste name = exe_ctx.GetThreadPtr()->GetQueueName();
507435933ddSDimitry Andric } else {
508ac7ddfbfSEd Maste if (log)
5090127ef0fSEd Maste log->Printf("SBThread(%p)::GetQueueName() => error: process is running",
5100127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
511ac7ddfbfSEd Maste }
512ac7ddfbfSEd Maste }
513ac7ddfbfSEd Maste
514ac7ddfbfSEd Maste if (log)
5150127ef0fSEd Maste log->Printf("SBThread(%p)::GetQueueName () => %s",
5160127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
5170127ef0fSEd Maste name ? name : "NULL");
518ac7ddfbfSEd Maste
519ac7ddfbfSEd Maste return name;
520ac7ddfbfSEd Maste }
521ac7ddfbfSEd Maste
GetQueueID() const522435933ddSDimitry Andric lldb::queue_id_t SBThread::GetQueueID() const {
52335617911SEd Maste queue_id_t id = LLDB_INVALID_QUEUE_ID;
5244bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
5254bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
52635617911SEd Maste
52735617911SEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
528435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
52935617911SEd Maste Process::StopLocker stop_locker;
530435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
53135617911SEd Maste id = exe_ctx.GetThreadPtr()->GetQueueID();
532435933ddSDimitry Andric } else {
53335617911SEd Maste if (log)
5340127ef0fSEd Maste log->Printf("SBThread(%p)::GetQueueID() => error: process is running",
5350127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
53635617911SEd Maste }
53735617911SEd Maste }
53835617911SEd Maste
53935617911SEd Maste if (log)
5400127ef0fSEd Maste log->Printf("SBThread(%p)::GetQueueID () => 0x%" PRIx64,
5410127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()), id);
54235617911SEd Maste
54335617911SEd Maste return id;
54435617911SEd Maste }
54535617911SEd Maste
GetInfoItemByPathAsString(const char * path,SBStream & strm)546435933ddSDimitry Andric bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) {
5470127ef0fSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
5480127ef0fSEd Maste bool success = false;
5494bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
5504bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
5510127ef0fSEd Maste
552435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
5530127ef0fSEd Maste Process::StopLocker stop_locker;
554435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
5550127ef0fSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
5560127ef0fSEd Maste StructuredData::ObjectSP info_root_sp = thread->GetExtendedInfo();
557435933ddSDimitry Andric if (info_root_sp) {
558435933ddSDimitry Andric StructuredData::ObjectSP node =
559435933ddSDimitry Andric info_root_sp->GetObjectForDotSeparatedPath(path);
560435933ddSDimitry Andric if (node) {
561302affcbSDimitry Andric if (node->GetType() == eStructuredDataTypeString) {
5625517e702SDimitry Andric strm.Printf("%s", node->GetAsString()->GetValue().str().c_str());
5630127ef0fSEd Maste success = true;
5640127ef0fSEd Maste }
565302affcbSDimitry Andric if (node->GetType() == eStructuredDataTypeInteger) {
5660127ef0fSEd Maste strm.Printf("0x%" PRIx64, node->GetAsInteger()->GetValue());
5670127ef0fSEd Maste success = true;
5680127ef0fSEd Maste }
569302affcbSDimitry Andric if (node->GetType() == eStructuredDataTypeFloat) {
5700127ef0fSEd Maste strm.Printf("0x%f", node->GetAsFloat()->GetValue());
5710127ef0fSEd Maste success = true;
5720127ef0fSEd Maste }
573302affcbSDimitry Andric if (node->GetType() == eStructuredDataTypeBoolean) {
574*b5893f02SDimitry Andric if (node->GetAsBoolean()->GetValue())
5750127ef0fSEd Maste strm.Printf("true");
5760127ef0fSEd Maste else
5770127ef0fSEd Maste strm.Printf("false");
5780127ef0fSEd Maste success = true;
5790127ef0fSEd Maste }
580302affcbSDimitry Andric if (node->GetType() == eStructuredDataTypeNull) {
5810127ef0fSEd Maste strm.Printf("null");
5820127ef0fSEd Maste success = true;
5830127ef0fSEd Maste }
5840127ef0fSEd Maste }
5850127ef0fSEd Maste }
586435933ddSDimitry Andric } else {
5870127ef0fSEd Maste if (log)
588435933ddSDimitry Andric log->Printf("SBThread(%p)::GetInfoItemByPathAsString() => error: "
589435933ddSDimitry Andric "process is running",
5900127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
5910127ef0fSEd Maste }
5920127ef0fSEd Maste }
5930127ef0fSEd Maste
5940127ef0fSEd Maste if (log)
595f678e45dSDimitry Andric log->Printf("SBThread(%p)::GetInfoItemByPathAsString (\"%s\") => \"%s\"",
596f678e45dSDimitry Andric static_cast<void *>(exe_ctx.GetThreadPtr()), path, strm.GetData());
5970127ef0fSEd Maste
5980127ef0fSEd Maste return success;
5990127ef0fSEd Maste }
6000127ef0fSEd Maste
ResumeNewPlan(ExecutionContext & exe_ctx,ThreadPlan * new_plan)601435933ddSDimitry Andric SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx,
602435933ddSDimitry Andric ThreadPlan *new_plan) {
603ac7ddfbfSEd Maste SBError sb_error;
604ac7ddfbfSEd Maste
605ac7ddfbfSEd Maste Process *process = exe_ctx.GetProcessPtr();
606435933ddSDimitry Andric if (!process) {
607ac7ddfbfSEd Maste sb_error.SetErrorString("No process in SBThread::ResumeNewPlan");
608ac7ddfbfSEd Maste return sb_error;
609ac7ddfbfSEd Maste }
610ac7ddfbfSEd Maste
611ac7ddfbfSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
612435933ddSDimitry Andric if (!thread) {
613ac7ddfbfSEd Maste sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan");
614ac7ddfbfSEd Maste return sb_error;
615ac7ddfbfSEd Maste }
616ac7ddfbfSEd Maste
617435933ddSDimitry Andric // User level plans should be Master Plans so they can be interrupted, other
6184ba319b5SDimitry Andric // plans executed, and then a "continue" will resume the plan.
619435933ddSDimitry Andric if (new_plan != NULL) {
620ac7ddfbfSEd Maste new_plan->SetIsMasterPlan(true);
621ac7ddfbfSEd Maste new_plan->SetOkayToDiscard(false);
622ac7ddfbfSEd Maste }
623ac7ddfbfSEd Maste
624ac7ddfbfSEd Maste // Why do we need to set the current thread by ID here???
625ac7ddfbfSEd Maste process->GetThreadList().SetSelectedThreadByID(thread->GetID());
626ac7ddfbfSEd Maste
6277aa51b79SEd Maste if (process->GetTarget().GetDebugger().GetAsyncExecution())
6287aa51b79SEd Maste sb_error.ref() = process->Resume();
6297aa51b79SEd Maste else
6307aa51b79SEd Maste sb_error.ref() = process->ResumeSynchronous(NULL);
631ac7ddfbfSEd Maste
632ac7ddfbfSEd Maste return sb_error;
633ac7ddfbfSEd Maste }
634ac7ddfbfSEd Maste
StepOver(lldb::RunMode stop_other_threads)635435933ddSDimitry Andric void SBThread::StepOver(lldb::RunMode stop_other_threads) {
6364ba319b5SDimitry Andric SBError error; // Ignored
6374ba319b5SDimitry Andric StepOver(stop_other_threads, error);
6384ba319b5SDimitry Andric }
6394ba319b5SDimitry Andric
StepOver(lldb::RunMode stop_other_threads,SBError & error)6404ba319b5SDimitry Andric void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) {
641ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
642ac7ddfbfSEd Maste
6434bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
6444bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
645ac7ddfbfSEd Maste
646ac7ddfbfSEd Maste if (log)
6470127ef0fSEd Maste log->Printf("SBThread(%p)::StepOver (stop_other_threads='%s')",
6480127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
649ac7ddfbfSEd Maste Thread::RunModeAsCString(stop_other_threads));
650ac7ddfbfSEd Maste
6514ba319b5SDimitry Andric if (!exe_ctx.HasThreadScope()) {
6524ba319b5SDimitry Andric error.SetErrorString("this SBThread object is invalid");
6534ba319b5SDimitry Andric return;
6544ba319b5SDimitry Andric }
6554ba319b5SDimitry Andric
656ac7ddfbfSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
657ac7ddfbfSEd Maste bool abort_other_plans = false;
658ac7ddfbfSEd Maste StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
659ac7ddfbfSEd Maste
660*b5893f02SDimitry Andric Status new_plan_status;
661ac7ddfbfSEd Maste ThreadPlanSP new_plan_sp;
662435933ddSDimitry Andric if (frame_sp) {
663435933ddSDimitry Andric if (frame_sp->HasDebugInformation()) {
6640127ef0fSEd Maste const LazyBool avoid_no_debug = eLazyBoolCalculate;
665ac7ddfbfSEd Maste SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
666435933ddSDimitry Andric new_plan_sp = thread->QueueThreadPlanForStepOverRange(
667435933ddSDimitry Andric abort_other_plans, sc.line_entry, sc, stop_other_threads,
668*b5893f02SDimitry Andric new_plan_status, avoid_no_debug);
669435933ddSDimitry Andric } else {
670435933ddSDimitry Andric new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
671*b5893f02SDimitry Andric true, abort_other_plans, stop_other_threads, new_plan_status);
672ac7ddfbfSEd Maste }
673ac7ddfbfSEd Maste }
6744ba319b5SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
675ac7ddfbfSEd Maste }
676ac7ddfbfSEd Maste
StepInto(lldb::RunMode stop_other_threads)677435933ddSDimitry Andric void SBThread::StepInto(lldb::RunMode stop_other_threads) {
678ac7ddfbfSEd Maste StepInto(NULL, stop_other_threads);
679ac7ddfbfSEd Maste }
680ac7ddfbfSEd Maste
StepInto(const char * target_name,lldb::RunMode stop_other_threads)681435933ddSDimitry Andric void SBThread::StepInto(const char *target_name,
682435933ddSDimitry Andric lldb::RunMode stop_other_threads) {
6834ba319b5SDimitry Andric SBError error; // Ignored
6844bb0738eSEd Maste StepInto(target_name, LLDB_INVALID_LINE_NUMBER, error, stop_other_threads);
6854bb0738eSEd Maste }
6864bb0738eSEd Maste
StepInto(const char * target_name,uint32_t end_line,SBError & error,lldb::RunMode stop_other_threads)687435933ddSDimitry Andric void SBThread::StepInto(const char *target_name, uint32_t end_line,
688435933ddSDimitry Andric SBError &error, lldb::RunMode stop_other_threads) {
689ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
690ac7ddfbfSEd Maste
6914bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
6924bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
693ac7ddfbfSEd Maste
694ac7ddfbfSEd Maste if (log)
695435933ddSDimitry Andric log->Printf(
696435933ddSDimitry Andric "SBThread(%p)::StepInto (target_name='%s', stop_other_threads='%s')",
6970127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
698ac7ddfbfSEd Maste target_name ? target_name : "<NULL>",
699ac7ddfbfSEd Maste Thread::RunModeAsCString(stop_other_threads));
700ac7ddfbfSEd Maste
7014ba319b5SDimitry Andric if (!exe_ctx.HasThreadScope()) {
7024ba319b5SDimitry Andric error.SetErrorString("this SBThread object is invalid");
7034ba319b5SDimitry Andric return;
7044ba319b5SDimitry Andric }
7054ba319b5SDimitry Andric
706ac7ddfbfSEd Maste bool abort_other_plans = false;
707ac7ddfbfSEd Maste
708ac7ddfbfSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
709ac7ddfbfSEd Maste StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
710ac7ddfbfSEd Maste ThreadPlanSP new_plan_sp;
711*b5893f02SDimitry Andric Status new_plan_status;
712ac7ddfbfSEd Maste
713435933ddSDimitry Andric if (frame_sp && frame_sp->HasDebugInformation()) {
7144bb0738eSEd Maste SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
7154bb0738eSEd Maste AddressRange range;
7164bb0738eSEd Maste if (end_line == LLDB_INVALID_LINE_NUMBER)
7174bb0738eSEd Maste range = sc.line_entry.range;
718435933ddSDimitry Andric else {
7194bb0738eSEd Maste if (!sc.GetAddressRangeFromHereToEndLine(end_line, range, error.ref()))
7204bb0738eSEd Maste return;
7214bb0738eSEd Maste }
7224bb0738eSEd Maste
723435933ddSDimitry Andric const LazyBool step_out_avoids_code_without_debug_info =
724435933ddSDimitry Andric eLazyBoolCalculate;
725435933ddSDimitry Andric const LazyBool step_in_avoids_code_without_debug_info =
726435933ddSDimitry Andric eLazyBoolCalculate;
727435933ddSDimitry Andric new_plan_sp = thread->QueueThreadPlanForStepInRange(
728435933ddSDimitry Andric abort_other_plans, range, sc, target_name, stop_other_threads,
729*b5893f02SDimitry Andric new_plan_status, step_in_avoids_code_without_debug_info,
7300127ef0fSEd Maste step_out_avoids_code_without_debug_info);
731435933ddSDimitry Andric } else {
732435933ddSDimitry Andric new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
733*b5893f02SDimitry Andric false, abort_other_plans, stop_other_threads, new_plan_status);
734ac7ddfbfSEd Maste }
735*b5893f02SDimitry Andric
736*b5893f02SDimitry Andric if (new_plan_status.Success())
7374bb0738eSEd Maste error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
738*b5893f02SDimitry Andric else
739*b5893f02SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
740ac7ddfbfSEd Maste }
741ac7ddfbfSEd Maste
StepOut()742435933ddSDimitry Andric void SBThread::StepOut() {
7434ba319b5SDimitry Andric SBError error; // Ignored
7444ba319b5SDimitry Andric StepOut(error);
7454ba319b5SDimitry Andric }
7464ba319b5SDimitry Andric
StepOut(SBError & error)7474ba319b5SDimitry Andric void SBThread::StepOut(SBError &error) {
748ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
749ac7ddfbfSEd Maste
7504bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
7514bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
752ac7ddfbfSEd Maste
753ac7ddfbfSEd Maste if (log)
7540127ef0fSEd Maste log->Printf("SBThread(%p)::StepOut ()",
7550127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
756ac7ddfbfSEd Maste
7574ba319b5SDimitry Andric if (!exe_ctx.HasThreadScope()) {
7584ba319b5SDimitry Andric error.SetErrorString("this SBThread object is invalid");
7594ba319b5SDimitry Andric return;
7604ba319b5SDimitry Andric }
7614ba319b5SDimitry Andric
762ac7ddfbfSEd Maste bool abort_other_plans = false;
763ac7ddfbfSEd Maste bool stop_other_threads = false;
764ac7ddfbfSEd Maste
765ac7ddfbfSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
766ac7ddfbfSEd Maste
7670127ef0fSEd Maste const LazyBool avoid_no_debug = eLazyBoolCalculate;
768*b5893f02SDimitry Andric Status new_plan_status;
769435933ddSDimitry Andric ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
770435933ddSDimitry Andric abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
771*b5893f02SDimitry Andric eVoteNoOpinion, 0, new_plan_status, avoid_no_debug));
772ac7ddfbfSEd Maste
773*b5893f02SDimitry Andric if (new_plan_status.Success())
7744ba319b5SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
775*b5893f02SDimitry Andric else
776*b5893f02SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
777ac7ddfbfSEd Maste }
778ac7ddfbfSEd Maste
StepOutOfFrame(SBFrame & sb_frame)7794ba319b5SDimitry Andric void SBThread::StepOutOfFrame(SBFrame &sb_frame) {
7804ba319b5SDimitry Andric SBError error; // Ignored
7814ba319b5SDimitry Andric StepOutOfFrame(sb_frame, error);
7824ba319b5SDimitry Andric }
7834ba319b5SDimitry Andric
StepOutOfFrame(SBFrame & sb_frame,SBError & error)7844ba319b5SDimitry Andric void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) {
785ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
786ac7ddfbfSEd Maste
7874bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
7884bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
789ac7ddfbfSEd Maste
790435933ddSDimitry Andric if (!sb_frame.IsValid()) {
7919f2f44ceSEd Maste if (log)
792435933ddSDimitry Andric log->Printf(
793435933ddSDimitry Andric "SBThread(%p)::StepOutOfFrame passed an invalid frame, returning.",
7949f2f44ceSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
7954ba319b5SDimitry Andric error.SetErrorString("passed invalid SBFrame object");
7969f2f44ceSEd Maste return;
7979f2f44ceSEd Maste }
7989f2f44ceSEd Maste
799ac7ddfbfSEd Maste StackFrameSP frame_sp(sb_frame.GetFrameSP());
800435933ddSDimitry Andric if (log) {
801ac7ddfbfSEd Maste SBStream frame_desc_strm;
802ac7ddfbfSEd Maste sb_frame.GetDescription(frame_desc_strm);
8030127ef0fSEd Maste log->Printf("SBThread(%p)::StepOutOfFrame (frame = SBFrame(%p): %s)",
8040127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
805435933ddSDimitry Andric static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
806ac7ddfbfSEd Maste }
807ac7ddfbfSEd Maste
8084ba319b5SDimitry Andric if (!exe_ctx.HasThreadScope()) {
8094ba319b5SDimitry Andric error.SetErrorString("this SBThread object is invalid");
8104ba319b5SDimitry Andric return;
8114ba319b5SDimitry Andric }
8124ba319b5SDimitry Andric
813ac7ddfbfSEd Maste bool abort_other_plans = false;
814ac7ddfbfSEd Maste bool stop_other_threads = false;
815ac7ddfbfSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
816435933ddSDimitry Andric if (sb_frame.GetThread().GetThreadID() != thread->GetID()) {
817435933ddSDimitry Andric log->Printf("SBThread(%p)::StepOutOfFrame passed a frame from another "
818435933ddSDimitry Andric "thread (0x%" PRIx64 " vrs. 0x%" PRIx64 ", returning.",
8199f2f44ceSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
820435933ddSDimitry Andric sb_frame.GetThread().GetThreadID(), thread->GetID());
8214ba319b5SDimitry Andric error.SetErrorString("passed a frame from another thread");
8224ba319b5SDimitry Andric return;
8239f2f44ceSEd Maste }
824ac7ddfbfSEd Maste
825*b5893f02SDimitry Andric Status new_plan_status;
826435933ddSDimitry Andric ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
827435933ddSDimitry Andric abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
828*b5893f02SDimitry Andric eVoteNoOpinion, frame_sp->GetFrameIndex(), new_plan_status));
829ac7ddfbfSEd Maste
830*b5893f02SDimitry Andric if (new_plan_status.Success())
8314ba319b5SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
832*b5893f02SDimitry Andric else
833*b5893f02SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
834ac7ddfbfSEd Maste }
835ac7ddfbfSEd Maste
StepInstruction(bool step_over)836435933ddSDimitry Andric void SBThread::StepInstruction(bool step_over) {
8374ba319b5SDimitry Andric SBError error; // Ignored
8384ba319b5SDimitry Andric StepInstruction(step_over, error);
8394ba319b5SDimitry Andric }
8404ba319b5SDimitry Andric
StepInstruction(bool step_over,SBError & error)8414ba319b5SDimitry Andric void SBThread::StepInstruction(bool step_over, SBError &error) {
842ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
843ac7ddfbfSEd Maste
8444bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
8454bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
846ac7ddfbfSEd Maste
847ac7ddfbfSEd Maste if (log)
8480127ef0fSEd Maste log->Printf("SBThread(%p)::StepInstruction (step_over=%i)",
8490127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()), step_over);
850ac7ddfbfSEd Maste
8514ba319b5SDimitry Andric if (!exe_ctx.HasThreadScope()) {
8524ba319b5SDimitry Andric error.SetErrorString("this SBThread object is invalid");
8534ba319b5SDimitry Andric return;
8544ba319b5SDimitry Andric }
8554ba319b5SDimitry Andric
856ac7ddfbfSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
857*b5893f02SDimitry Andric Status new_plan_status;
858*b5893f02SDimitry Andric ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepSingleInstruction(
859*b5893f02SDimitry Andric step_over, true, true, new_plan_status));
860ac7ddfbfSEd Maste
861*b5893f02SDimitry Andric if (new_plan_status.Success())
8624ba319b5SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
863*b5893f02SDimitry Andric else
864*b5893f02SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
865ac7ddfbfSEd Maste }
866ac7ddfbfSEd Maste
RunToAddress(lldb::addr_t addr)867435933ddSDimitry Andric void SBThread::RunToAddress(lldb::addr_t addr) {
8684ba319b5SDimitry Andric SBError error; // Ignored
8694ba319b5SDimitry Andric RunToAddress(addr, error);
8704ba319b5SDimitry Andric }
8714ba319b5SDimitry Andric
RunToAddress(lldb::addr_t addr,SBError & error)8724ba319b5SDimitry Andric void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) {
873ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
874ac7ddfbfSEd Maste
8754bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
8764bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
877ac7ddfbfSEd Maste
878ac7ddfbfSEd Maste if (log)
8790127ef0fSEd Maste log->Printf("SBThread(%p)::RunToAddress (addr=0x%" PRIx64 ")",
8800127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()), addr);
881ac7ddfbfSEd Maste
8824ba319b5SDimitry Andric if (!exe_ctx.HasThreadScope()) {
8834ba319b5SDimitry Andric error.SetErrorString("this SBThread object is invalid");
8844ba319b5SDimitry Andric return;
8854ba319b5SDimitry Andric }
8864ba319b5SDimitry Andric
887ac7ddfbfSEd Maste bool abort_other_plans = false;
888ac7ddfbfSEd Maste bool stop_other_threads = true;
889ac7ddfbfSEd Maste
890ac7ddfbfSEd Maste Address target_addr(addr);
891ac7ddfbfSEd Maste
892ac7ddfbfSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
893ac7ddfbfSEd Maste
894*b5893f02SDimitry Andric Status new_plan_status;
895435933ddSDimitry Andric ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
896*b5893f02SDimitry Andric abort_other_plans, target_addr, stop_other_threads, new_plan_status));
897ac7ddfbfSEd Maste
898*b5893f02SDimitry Andric if (new_plan_status.Success())
8994ba319b5SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
900*b5893f02SDimitry Andric else
901*b5893f02SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
902ac7ddfbfSEd Maste }
903ac7ddfbfSEd Maste
StepOverUntil(lldb::SBFrame & sb_frame,lldb::SBFileSpec & sb_file_spec,uint32_t line)904435933ddSDimitry Andric SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
905435933ddSDimitry Andric lldb::SBFileSpec &sb_file_spec, uint32_t line) {
906ac7ddfbfSEd Maste SBError sb_error;
907ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
908ac7ddfbfSEd Maste char path[PATH_MAX];
909ac7ddfbfSEd Maste
9104bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
9114bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
912ac7ddfbfSEd Maste
913ac7ddfbfSEd Maste StackFrameSP frame_sp(sb_frame.GetFrameSP());
914ac7ddfbfSEd Maste
915435933ddSDimitry Andric if (log) {
916ac7ddfbfSEd Maste SBStream frame_desc_strm;
917ac7ddfbfSEd Maste sb_frame.GetDescription(frame_desc_strm);
918ac7ddfbfSEd Maste sb_file_spec->GetPath(path, sizeof(path));
919435933ddSDimitry Andric log->Printf("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, "
920435933ddSDimitry Andric "file+line = %s:%u)",
9210127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
922435933ddSDimitry Andric static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData(),
923435933ddSDimitry Andric path, line);
924ac7ddfbfSEd Maste }
925ac7ddfbfSEd Maste
926435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
927ac7ddfbfSEd Maste Target *target = exe_ctx.GetTargetPtr();
928ac7ddfbfSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
929ac7ddfbfSEd Maste
930435933ddSDimitry Andric if (line == 0) {
931ac7ddfbfSEd Maste sb_error.SetErrorString("invalid line argument");
932ac7ddfbfSEd Maste return sb_error;
933ac7ddfbfSEd Maste }
934ac7ddfbfSEd Maste
935435933ddSDimitry Andric if (!frame_sp) {
936ac7ddfbfSEd Maste frame_sp = thread->GetSelectedFrame();
937ac7ddfbfSEd Maste if (!frame_sp)
938ac7ddfbfSEd Maste frame_sp = thread->GetStackFrameAtIndex(0);
939ac7ddfbfSEd Maste }
940ac7ddfbfSEd Maste
941ac7ddfbfSEd Maste SymbolContext frame_sc;
942435933ddSDimitry Andric if (!frame_sp) {
943ac7ddfbfSEd Maste sb_error.SetErrorString("no valid frames in thread to step");
944ac7ddfbfSEd Maste return sb_error;
945ac7ddfbfSEd Maste }
946ac7ddfbfSEd Maste
947ac7ddfbfSEd Maste // If we have a frame, get its line
948435933ddSDimitry Andric frame_sc = frame_sp->GetSymbolContext(
949435933ddSDimitry Andric eSymbolContextCompUnit | eSymbolContextFunction |
950435933ddSDimitry Andric eSymbolContextLineEntry | eSymbolContextSymbol);
951ac7ddfbfSEd Maste
952435933ddSDimitry Andric if (frame_sc.comp_unit == NULL) {
953435933ddSDimitry Andric sb_error.SetErrorStringWithFormat(
954435933ddSDimitry Andric "frame %u doesn't have debug information", frame_sp->GetFrameIndex());
955ac7ddfbfSEd Maste return sb_error;
956ac7ddfbfSEd Maste }
957ac7ddfbfSEd Maste
958ac7ddfbfSEd Maste FileSpec step_file_spec;
959435933ddSDimitry Andric if (sb_file_spec.IsValid()) {
960ac7ddfbfSEd Maste // The file spec passed in was valid, so use it
961ac7ddfbfSEd Maste step_file_spec = sb_file_spec.ref();
962435933ddSDimitry Andric } else {
963ac7ddfbfSEd Maste if (frame_sc.line_entry.IsValid())
964ac7ddfbfSEd Maste step_file_spec = frame_sc.line_entry.file;
965435933ddSDimitry Andric else {
966ac7ddfbfSEd Maste sb_error.SetErrorString("invalid file argument or no file for frame");
967ac7ddfbfSEd Maste return sb_error;
968ac7ddfbfSEd Maste }
969ac7ddfbfSEd Maste }
970ac7ddfbfSEd Maste
971ac7ddfbfSEd Maste // Grab the current function, then we will make sure the "until" address is
972ac7ddfbfSEd Maste // within the function. We discard addresses that are out of the current
973435933ddSDimitry Andric // function, and then if there are no addresses remaining, give an
9744ba319b5SDimitry Andric // appropriate error message.
975ac7ddfbfSEd Maste
976ac7ddfbfSEd Maste bool all_in_function = true;
977ac7ddfbfSEd Maste AddressRange fun_range = frame_sc.function->GetAddressRange();
978ac7ddfbfSEd Maste
979ac7ddfbfSEd Maste std::vector<addr_t> step_over_until_addrs;
980ac7ddfbfSEd Maste const bool abort_other_plans = false;
981ac7ddfbfSEd Maste const bool stop_other_threads = false;
982ac7ddfbfSEd Maste const bool check_inlines = true;
983ac7ddfbfSEd Maste const bool exact = false;
984ac7ddfbfSEd Maste
985ac7ddfbfSEd Maste SymbolContextList sc_list;
986435933ddSDimitry Andric const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext(
987435933ddSDimitry Andric step_file_spec, line, check_inlines, exact, eSymbolContextLineEntry,
988ac7ddfbfSEd Maste sc_list);
989435933ddSDimitry Andric if (num_matches > 0) {
990ac7ddfbfSEd Maste SymbolContext sc;
991435933ddSDimitry Andric for (uint32_t i = 0; i < num_matches; ++i) {
992435933ddSDimitry Andric if (sc_list.GetContextAtIndex(i, sc)) {
993435933ddSDimitry Andric addr_t step_addr =
994435933ddSDimitry Andric sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
995435933ddSDimitry Andric if (step_addr != LLDB_INVALID_ADDRESS) {
996ac7ddfbfSEd Maste if (fun_range.ContainsLoadAddress(step_addr, target))
997ac7ddfbfSEd Maste step_over_until_addrs.push_back(step_addr);
998ac7ddfbfSEd Maste else
999ac7ddfbfSEd Maste all_in_function = false;
1000ac7ddfbfSEd Maste }
1001ac7ddfbfSEd Maste }
1002ac7ddfbfSEd Maste }
1003ac7ddfbfSEd Maste }
1004ac7ddfbfSEd Maste
1005435933ddSDimitry Andric if (step_over_until_addrs.empty()) {
1006435933ddSDimitry Andric if (all_in_function) {
1007ac7ddfbfSEd Maste step_file_spec.GetPath(path, sizeof(path));
1008435933ddSDimitry Andric sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path,
1009435933ddSDimitry Andric line);
1010435933ddSDimitry Andric } else
1011ac7ddfbfSEd Maste sb_error.SetErrorString("step until target not in current function");
1012435933ddSDimitry Andric } else {
1013*b5893f02SDimitry Andric Status new_plan_status;
1014435933ddSDimitry Andric ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepUntil(
1015435933ddSDimitry Andric abort_other_plans, &step_over_until_addrs[0],
1016435933ddSDimitry Andric step_over_until_addrs.size(), stop_other_threads,
1017*b5893f02SDimitry Andric frame_sp->GetFrameIndex(), new_plan_status));
1018ac7ddfbfSEd Maste
1019*b5893f02SDimitry Andric if (new_plan_status.Success())
1020ac7ddfbfSEd Maste sb_error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
1021*b5893f02SDimitry Andric else
1022*b5893f02SDimitry Andric sb_error.SetErrorString(new_plan_status.AsCString());
1023ac7ddfbfSEd Maste }
1024435933ddSDimitry Andric } else {
1025ac7ddfbfSEd Maste sb_error.SetErrorString("this SBThread object is invalid");
1026ac7ddfbfSEd Maste }
1027ac7ddfbfSEd Maste return sb_error;
1028ac7ddfbfSEd Maste }
1029ac7ddfbfSEd Maste
StepUsingScriptedThreadPlan(const char * script_class_name)1030435933ddSDimitry Andric SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name) {
1031435933ddSDimitry Andric return StepUsingScriptedThreadPlan(script_class_name, true);
1032435933ddSDimitry Andric }
1033435933ddSDimitry Andric
StepUsingScriptedThreadPlan(const char * script_class_name,bool resume_immediately)1034435933ddSDimitry Andric SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
1035435933ddSDimitry Andric bool resume_immediately) {
10367aa51b79SEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1037*b5893f02SDimitry Andric SBError error;
10387aa51b79SEd Maste
10394bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
10404bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10417aa51b79SEd Maste
1042435933ddSDimitry Andric if (log) {
10437aa51b79SEd Maste log->Printf("SBThread(%p)::StepUsingScriptedThreadPlan: class name: %s",
1044435933ddSDimitry Andric static_cast<void *>(exe_ctx.GetThreadPtr()), script_class_name);
10457aa51b79SEd Maste }
10467aa51b79SEd Maste
1047435933ddSDimitry Andric if (!exe_ctx.HasThreadScope()) {
1048*b5893f02SDimitry Andric error.SetErrorString("this SBThread object is invalid");
1049*b5893f02SDimitry Andric return error;
10507aa51b79SEd Maste }
10517aa51b79SEd Maste
10527aa51b79SEd Maste Thread *thread = exe_ctx.GetThreadPtr();
1053*b5893f02SDimitry Andric Status new_plan_status;
1054*b5893f02SDimitry Andric ThreadPlanSP new_plan_sp = thread->QueueThreadPlanForStepScripted(
1055*b5893f02SDimitry Andric false, script_class_name, false, new_plan_status);
1056435933ddSDimitry Andric
1057*b5893f02SDimitry Andric if (new_plan_status.Fail()) {
1058*b5893f02SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
1059*b5893f02SDimitry Andric return error;
1060435933ddSDimitry Andric }
1061435933ddSDimitry Andric
1062*b5893f02SDimitry Andric if (!resume_immediately)
1063*b5893f02SDimitry Andric return error;
10647aa51b79SEd Maste
1065*b5893f02SDimitry Andric if (new_plan_status.Success())
1066*b5893f02SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
1067*b5893f02SDimitry Andric else
1068*b5893f02SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
10697aa51b79SEd Maste
1070*b5893f02SDimitry Andric return error;
10717aa51b79SEd Maste }
10727aa51b79SEd Maste
JumpToLine(lldb::SBFileSpec & file_spec,uint32_t line)1073435933ddSDimitry Andric SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) {
107435617911SEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
107535617911SEd Maste SBError sb_error;
107635617911SEd Maste
10774bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
10784bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
107935617911SEd Maste
108035617911SEd Maste if (log)
10810127ef0fSEd Maste log->Printf("SBThread(%p)::JumpToLine (file+line = %s:%u)",
10820127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
10830127ef0fSEd Maste file_spec->GetPath().c_str(), line);
108435617911SEd Maste
1085435933ddSDimitry Andric if (!exe_ctx.HasThreadScope()) {
108635617911SEd Maste sb_error.SetErrorString("this SBThread object is invalid");
108735617911SEd Maste return sb_error;
108835617911SEd Maste }
108935617911SEd Maste
109035617911SEd Maste Thread *thread = exe_ctx.GetThreadPtr();
109135617911SEd Maste
10925517e702SDimitry Andric Status err = thread->JumpToLine(file_spec.get(), line, true);
109335617911SEd Maste sb_error.SetError(err);
109435617911SEd Maste return sb_error;
109535617911SEd Maste }
109635617911SEd Maste
ReturnFromFrame(SBFrame & frame,SBValue & return_value)1097435933ddSDimitry Andric SBError SBThread::ReturnFromFrame(SBFrame &frame, SBValue &return_value) {
1098ac7ddfbfSEd Maste SBError sb_error;
1099ac7ddfbfSEd Maste
1100ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1101ac7ddfbfSEd Maste
11024bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
11034bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1104ac7ddfbfSEd Maste
1105ac7ddfbfSEd Maste if (log)
11060127ef0fSEd Maste log->Printf("SBThread(%p)::ReturnFromFrame (frame=%d)",
11070127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
11080127ef0fSEd Maste frame.GetFrameID());
1109ac7ddfbfSEd Maste
1110435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
1111ac7ddfbfSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
1112435933ddSDimitry Andric sb_error.SetError(
1113435933ddSDimitry Andric thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
1114ac7ddfbfSEd Maste }
1115ac7ddfbfSEd Maste
1116ac7ddfbfSEd Maste return sb_error;
1117ac7ddfbfSEd Maste }
1118ac7ddfbfSEd Maste
UnwindInnermostExpression()1119435933ddSDimitry Andric SBError SBThread::UnwindInnermostExpression() {
11204bb0738eSEd Maste SBError sb_error;
11214bb0738eSEd Maste
11224bb0738eSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
11234bb0738eSEd Maste
11244bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
11254bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
11264bb0738eSEd Maste
11274bb0738eSEd Maste if (log)
11284bb0738eSEd Maste log->Printf("SBThread(%p)::UnwindExpressionEvaluation",
11294bb0738eSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
11304bb0738eSEd Maste
1131435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
11324bb0738eSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
11334bb0738eSEd Maste sb_error.SetError(thread->UnwindInnermostExpression());
11344bb0738eSEd Maste if (sb_error.Success())
11354bb0738eSEd Maste thread->SetSelectedFrameByIndex(0, false);
11364bb0738eSEd Maste }
11374bb0738eSEd Maste
11384bb0738eSEd Maste return sb_error;
11394bb0738eSEd Maste }
1140ac7ddfbfSEd Maste
Suspend()1141435933ddSDimitry Andric bool SBThread::Suspend() {
11424ba319b5SDimitry Andric SBError error; // Ignored
11434ba319b5SDimitry Andric return Suspend(error);
11444ba319b5SDimitry Andric }
11454ba319b5SDimitry Andric
Suspend(SBError & error)11464ba319b5SDimitry Andric bool SBThread::Suspend(SBError &error) {
1147ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
11484bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
11494bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
11504bb0738eSEd Maste
1151ac7ddfbfSEd Maste bool result = false;
1152435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
1153ac7ddfbfSEd Maste Process::StopLocker stop_locker;
1154435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1155ac7ddfbfSEd Maste exe_ctx.GetThreadPtr()->SetResumeState(eStateSuspended);
1156ac7ddfbfSEd Maste result = true;
1157435933ddSDimitry Andric } else {
11584ba319b5SDimitry Andric error.SetErrorString("process is running");
1159ac7ddfbfSEd Maste if (log)
11600127ef0fSEd Maste log->Printf("SBThread(%p)::Suspend() => error: process is running",
11610127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
1162ac7ddfbfSEd Maste }
11634ba319b5SDimitry Andric } else
11644ba319b5SDimitry Andric error.SetErrorString("this SBThread object is invalid");
1165ac7ddfbfSEd Maste if (log)
11660127ef0fSEd Maste log->Printf("SBThread(%p)::Suspend() => %i",
11670127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()), result);
1168ac7ddfbfSEd Maste return result;
1169ac7ddfbfSEd Maste }
1170ac7ddfbfSEd Maste
Resume()1171435933ddSDimitry Andric bool SBThread::Resume() {
11724ba319b5SDimitry Andric SBError error; // Ignored
11734ba319b5SDimitry Andric return Resume(error);
11744ba319b5SDimitry Andric }
11754ba319b5SDimitry Andric
Resume(SBError & error)11764ba319b5SDimitry Andric bool SBThread::Resume(SBError &error) {
1177ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
11784bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
11794bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
11804bb0738eSEd Maste
1181ac7ddfbfSEd Maste bool result = false;
1182435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
1183ac7ddfbfSEd Maste Process::StopLocker stop_locker;
1184435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
11850127ef0fSEd Maste const bool override_suspend = true;
11860127ef0fSEd Maste exe_ctx.GetThreadPtr()->SetResumeState(eStateRunning, override_suspend);
1187ac7ddfbfSEd Maste result = true;
1188435933ddSDimitry Andric } else {
11894ba319b5SDimitry Andric error.SetErrorString("process is running");
1190ac7ddfbfSEd Maste if (log)
11910127ef0fSEd Maste log->Printf("SBThread(%p)::Resume() => error: process is running",
11920127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
1193ac7ddfbfSEd Maste }
11944ba319b5SDimitry Andric } else
11954ba319b5SDimitry Andric error.SetErrorString("this SBThread object is invalid");
1196ac7ddfbfSEd Maste if (log)
11970127ef0fSEd Maste log->Printf("SBThread(%p)::Resume() => %i",
11980127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()), result);
1199ac7ddfbfSEd Maste return result;
1200ac7ddfbfSEd Maste }
1201ac7ddfbfSEd Maste
IsSuspended()1202435933ddSDimitry Andric bool SBThread::IsSuspended() {
12034bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
12044bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12054bb0738eSEd Maste
1206ac7ddfbfSEd Maste if (exe_ctx.HasThreadScope())
1207ac7ddfbfSEd Maste return exe_ctx.GetThreadPtr()->GetResumeState() == eStateSuspended;
1208ac7ddfbfSEd Maste return false;
1209ac7ddfbfSEd Maste }
1210ac7ddfbfSEd Maste
IsStopped()1211435933ddSDimitry Andric bool SBThread::IsStopped() {
12124bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
12134bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12144bb0738eSEd Maste
1215ac7ddfbfSEd Maste if (exe_ctx.HasThreadScope())
1216ac7ddfbfSEd Maste return StateIsStoppedState(exe_ctx.GetThreadPtr()->GetState(), true);
1217ac7ddfbfSEd Maste return false;
1218ac7ddfbfSEd Maste }
1219ac7ddfbfSEd Maste
GetProcess()1220435933ddSDimitry Andric SBProcess SBThread::GetProcess() {
1221ac7ddfbfSEd Maste SBProcess sb_process;
12224bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
12234bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12244bb0738eSEd Maste
1225435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
1226435933ddSDimitry Andric // Have to go up to the target so we can get a shared pointer to our
1227435933ddSDimitry Andric // process...
1228ac7ddfbfSEd Maste sb_process.SetSP(exe_ctx.GetProcessSP());
1229ac7ddfbfSEd Maste }
1230ac7ddfbfSEd Maste
1231ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1232435933ddSDimitry Andric if (log) {
1233ac7ddfbfSEd Maste SBStream frame_desc_strm;
1234ac7ddfbfSEd Maste sb_process.GetDescription(frame_desc_strm);
12350127ef0fSEd Maste log->Printf("SBThread(%p)::GetProcess () => SBProcess(%p): %s",
12360127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
12370127ef0fSEd Maste static_cast<void *>(sb_process.GetSP().get()),
12380127ef0fSEd Maste frame_desc_strm.GetData());
1239ac7ddfbfSEd Maste }
1240ac7ddfbfSEd Maste
1241ac7ddfbfSEd Maste return sb_process;
1242ac7ddfbfSEd Maste }
1243ac7ddfbfSEd Maste
GetNumFrames()1244435933ddSDimitry Andric uint32_t SBThread::GetNumFrames() {
1245ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1246ac7ddfbfSEd Maste
1247ac7ddfbfSEd Maste uint32_t num_frames = 0;
12484bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
12494bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1250ac7ddfbfSEd Maste
1251435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
1252ac7ddfbfSEd Maste Process::StopLocker stop_locker;
1253435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1254ac7ddfbfSEd Maste num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount();
1255435933ddSDimitry Andric } else {
1256ac7ddfbfSEd Maste if (log)
12570127ef0fSEd Maste log->Printf("SBThread(%p)::GetNumFrames() => error: process is running",
12580127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
1259ac7ddfbfSEd Maste }
1260ac7ddfbfSEd Maste }
1261ac7ddfbfSEd Maste
1262ac7ddfbfSEd Maste if (log)
12630127ef0fSEd Maste log->Printf("SBThread(%p)::GetNumFrames () => %u",
12640127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()), num_frames);
1265ac7ddfbfSEd Maste
1266ac7ddfbfSEd Maste return num_frames;
1267ac7ddfbfSEd Maste }
1268ac7ddfbfSEd Maste
GetFrameAtIndex(uint32_t idx)1269435933ddSDimitry Andric SBFrame SBThread::GetFrameAtIndex(uint32_t idx) {
1270ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1271ac7ddfbfSEd Maste
1272ac7ddfbfSEd Maste SBFrame sb_frame;
1273ac7ddfbfSEd Maste StackFrameSP frame_sp;
12744bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
12754bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1276ac7ddfbfSEd Maste
1277435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
1278ac7ddfbfSEd Maste Process::StopLocker stop_locker;
1279435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1280ac7ddfbfSEd Maste frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx);
1281ac7ddfbfSEd Maste sb_frame.SetFrameSP(frame_sp);
1282435933ddSDimitry Andric } else {
1283ac7ddfbfSEd Maste if (log)
1284435933ddSDimitry Andric log->Printf(
1285435933ddSDimitry Andric "SBThread(%p)::GetFrameAtIndex() => error: process is running",
12860127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
1287ac7ddfbfSEd Maste }
1288ac7ddfbfSEd Maste }
1289ac7ddfbfSEd Maste
1290435933ddSDimitry Andric if (log) {
1291ac7ddfbfSEd Maste SBStream frame_desc_strm;
1292ac7ddfbfSEd Maste sb_frame.GetDescription(frame_desc_strm);
1293ac7ddfbfSEd Maste log->Printf("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s",
12940127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()), idx,
1295435933ddSDimitry Andric static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
1296ac7ddfbfSEd Maste }
1297ac7ddfbfSEd Maste
1298ac7ddfbfSEd Maste return sb_frame;
1299ac7ddfbfSEd Maste }
1300ac7ddfbfSEd Maste
GetSelectedFrame()1301435933ddSDimitry Andric lldb::SBFrame SBThread::GetSelectedFrame() {
1302ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1303ac7ddfbfSEd Maste
1304ac7ddfbfSEd Maste SBFrame sb_frame;
1305ac7ddfbfSEd Maste StackFrameSP frame_sp;
13064bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
13074bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1308ac7ddfbfSEd Maste
1309435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
1310ac7ddfbfSEd Maste Process::StopLocker stop_locker;
1311435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1312ac7ddfbfSEd Maste frame_sp = exe_ctx.GetThreadPtr()->GetSelectedFrame();
1313ac7ddfbfSEd Maste sb_frame.SetFrameSP(frame_sp);
1314435933ddSDimitry Andric } else {
1315ac7ddfbfSEd Maste if (log)
1316435933ddSDimitry Andric log->Printf(
1317435933ddSDimitry Andric "SBThread(%p)::GetSelectedFrame() => error: process is running",
13180127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
1319ac7ddfbfSEd Maste }
1320ac7ddfbfSEd Maste }
1321ac7ddfbfSEd Maste
1322435933ddSDimitry Andric if (log) {
1323ac7ddfbfSEd Maste SBStream frame_desc_strm;
1324ac7ddfbfSEd Maste sb_frame.GetDescription(frame_desc_strm);
1325ac7ddfbfSEd Maste log->Printf("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s",
13260127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
1327435933ddSDimitry Andric static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
1328ac7ddfbfSEd Maste }
1329ac7ddfbfSEd Maste
1330ac7ddfbfSEd Maste return sb_frame;
1331ac7ddfbfSEd Maste }
1332ac7ddfbfSEd Maste
SetSelectedFrame(uint32_t idx)1333435933ddSDimitry Andric lldb::SBFrame SBThread::SetSelectedFrame(uint32_t idx) {
1334ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1335ac7ddfbfSEd Maste
1336ac7ddfbfSEd Maste SBFrame sb_frame;
1337ac7ddfbfSEd Maste StackFrameSP frame_sp;
13384bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
13394bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1340ac7ddfbfSEd Maste
1341435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
1342ac7ddfbfSEd Maste Process::StopLocker stop_locker;
1343435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1344ac7ddfbfSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
1345ac7ddfbfSEd Maste frame_sp = thread->GetStackFrameAtIndex(idx);
1346435933ddSDimitry Andric if (frame_sp) {
1347ac7ddfbfSEd Maste thread->SetSelectedFrame(frame_sp.get());
1348ac7ddfbfSEd Maste sb_frame.SetFrameSP(frame_sp);
1349ac7ddfbfSEd Maste }
1350435933ddSDimitry Andric } else {
1351ac7ddfbfSEd Maste if (log)
1352435933ddSDimitry Andric log->Printf(
1353435933ddSDimitry Andric "SBThread(%p)::SetSelectedFrame() => error: process is running",
13540127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
1355ac7ddfbfSEd Maste }
1356ac7ddfbfSEd Maste }
1357ac7ddfbfSEd Maste
1358435933ddSDimitry Andric if (log) {
1359ac7ddfbfSEd Maste SBStream frame_desc_strm;
1360ac7ddfbfSEd Maste sb_frame.GetDescription(frame_desc_strm);
1361ac7ddfbfSEd Maste log->Printf("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s",
13620127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()), idx,
1363435933ddSDimitry Andric static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
1364ac7ddfbfSEd Maste }
1365ac7ddfbfSEd Maste return sb_frame;
1366ac7ddfbfSEd Maste }
1367ac7ddfbfSEd Maste
EventIsThreadEvent(const SBEvent & event)1368435933ddSDimitry Andric bool SBThread::EventIsThreadEvent(const SBEvent &event) {
1369ac7ddfbfSEd Maste return Thread::ThreadEventData::GetEventDataFromEvent(event.get()) != NULL;
1370ac7ddfbfSEd Maste }
1371ac7ddfbfSEd Maste
GetStackFrameFromEvent(const SBEvent & event)1372435933ddSDimitry Andric SBFrame SBThread::GetStackFrameFromEvent(const SBEvent &event) {
1373ac7ddfbfSEd Maste return Thread::ThreadEventData::GetStackFrameFromEvent(event.get());
1374ac7ddfbfSEd Maste }
1375ac7ddfbfSEd Maste
GetThreadFromEvent(const SBEvent & event)1376435933ddSDimitry Andric SBThread SBThread::GetThreadFromEvent(const SBEvent &event) {
1377ac7ddfbfSEd Maste return Thread::ThreadEventData::GetThreadFromEvent(event.get());
1378ac7ddfbfSEd Maste }
1379ac7ddfbfSEd Maste
operator ==(const SBThread & rhs) const1380435933ddSDimitry Andric bool SBThread::operator==(const SBThread &rhs) const {
1381435933ddSDimitry Andric return m_opaque_sp->GetThreadSP().get() ==
1382435933ddSDimitry Andric rhs.m_opaque_sp->GetThreadSP().get();
1383ac7ddfbfSEd Maste }
1384ac7ddfbfSEd Maste
operator !=(const SBThread & rhs) const1385435933ddSDimitry Andric bool SBThread::operator!=(const SBThread &rhs) const {
1386435933ddSDimitry Andric return m_opaque_sp->GetThreadSP().get() !=
1387435933ddSDimitry Andric rhs.m_opaque_sp->GetThreadSP().get();
1388ac7ddfbfSEd Maste }
1389ac7ddfbfSEd Maste
GetStatus(SBStream & status) const1390435933ddSDimitry Andric bool SBThread::GetStatus(SBStream &status) const {
1391ac7ddfbfSEd Maste Stream &strm = status.ref();
1392ac7ddfbfSEd Maste
13934bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
13944bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
13954bb0738eSEd Maste
1396435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
1397435933ddSDimitry Andric exe_ctx.GetThreadPtr()->GetStatus(strm, 0, 1, 1, true);
1398435933ddSDimitry Andric } else
1399ac7ddfbfSEd Maste strm.PutCString("No status");
1400ac7ddfbfSEd Maste
1401ac7ddfbfSEd Maste return true;
1402ac7ddfbfSEd Maste }
1403ac7ddfbfSEd Maste
GetDescription(SBStream & description) const1404435933ddSDimitry Andric bool SBThread::GetDescription(SBStream &description) const {
1405435933ddSDimitry Andric return GetDescription(description, false);
1406435933ddSDimitry Andric }
1407435933ddSDimitry Andric
GetDescription(SBStream & description,bool stop_format) const1408435933ddSDimitry Andric bool SBThread::GetDescription(SBStream &description, bool stop_format) const {
1409ac7ddfbfSEd Maste Stream &strm = description.ref();
1410ac7ddfbfSEd Maste
14114bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
14124bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
14134bb0738eSEd Maste
1414435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
1415435933ddSDimitry Andric exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat(strm,
1416435933ddSDimitry Andric LLDB_INVALID_THREAD_ID,
1417435933ddSDimitry Andric stop_format);
1418435933ddSDimitry Andric // strm.Printf("SBThread: tid = 0x%4.4" PRIx64,
1419435933ddSDimitry Andric // exe_ctx.GetThreadPtr()->GetID());
1420435933ddSDimitry Andric } else
1421ac7ddfbfSEd Maste strm.PutCString("No value");
1422ac7ddfbfSEd Maste
1423ac7ddfbfSEd Maste return true;
1424ac7ddfbfSEd Maste }
142535617911SEd Maste
GetExtendedBacktraceThread(const char * type)1426435933ddSDimitry Andric SBThread SBThread::GetExtendedBacktraceThread(const char *type) {
142735617911SEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
14284bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
14294bb0738eSEd Maste ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
143035617911SEd Maste SBThread sb_origin_thread;
143135617911SEd Maste
1432435933ddSDimitry Andric if (exe_ctx.HasThreadScope()) {
143335617911SEd Maste Process::StopLocker stop_locker;
1434435933ddSDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1435b952cd58SEd Maste ThreadSP real_thread(exe_ctx.GetThreadSP());
1436435933ddSDimitry Andric if (real_thread) {
143735617911SEd Maste ConstString type_const(type);
1438b952cd58SEd Maste Process *process = exe_ctx.GetProcessPtr();
1439435933ddSDimitry Andric if (process) {
1440b952cd58SEd Maste SystemRuntime *runtime = process->GetSystemRuntime();
1441435933ddSDimitry Andric if (runtime) {
1442435933ddSDimitry Andric ThreadSP new_thread_sp(
1443435933ddSDimitry Andric runtime->GetExtendedBacktraceThread(real_thread, type_const));
1444435933ddSDimitry Andric if (new_thread_sp) {
1445435933ddSDimitry Andric // Save this in the Process' ExtendedThreadList so a strong
14464ba319b5SDimitry Andric // pointer retains the object.
1447b952cd58SEd Maste process->GetExtendedThreadList().AddThread(new_thread_sp);
1448b952cd58SEd Maste sb_origin_thread.SetThread(new_thread_sp);
1449435933ddSDimitry Andric if (log) {
1450b952cd58SEd Maste const char *queue_name = new_thread_sp->GetQueueName();
1451b952cd58SEd Maste if (queue_name == NULL)
1452b952cd58SEd Maste queue_name = "";
1453435933ddSDimitry Andric log->Printf("SBThread(%p)::GetExtendedBacktraceThread() => new "
1454435933ddSDimitry Andric "extended Thread "
1455435933ddSDimitry Andric "created (%p) with queue_id 0x%" PRIx64
1456435933ddSDimitry Andric " queue name '%s'",
14570127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()),
14580127ef0fSEd Maste static_cast<void *>(new_thread_sp.get()),
1459435933ddSDimitry Andric new_thread_sp->GetQueueID(), queue_name);
1460b952cd58SEd Maste }
1461b952cd58SEd Maste }
1462b952cd58SEd Maste }
146335617911SEd Maste }
146435617911SEd Maste }
1465435933ddSDimitry Andric } else {
146635617911SEd Maste if (log)
1467435933ddSDimitry Andric log->Printf("SBThread(%p)::GetExtendedBacktraceThread() => error: "
1468435933ddSDimitry Andric "process is running",
14690127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
147035617911SEd Maste }
147135617911SEd Maste }
147235617911SEd Maste
1473*b5893f02SDimitry Andric if (log && !sb_origin_thread.IsValid())
1474435933ddSDimitry Andric log->Printf("SBThread(%p)::GetExtendedBacktraceThread() is not returning a "
1475435933ddSDimitry Andric "Valid thread",
14760127ef0fSEd Maste static_cast<void *>(exe_ctx.GetThreadPtr()));
147735617911SEd Maste return sb_origin_thread;
147835617911SEd Maste }
1479b952cd58SEd Maste
GetExtendedBacktraceOriginatingIndexID()1480435933ddSDimitry Andric uint32_t SBThread::GetExtendedBacktraceOriginatingIndexID() {
1481b952cd58SEd Maste ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
1482b952cd58SEd Maste if (thread_sp)
1483b952cd58SEd Maste return thread_sp->GetExtendedBacktraceOriginatingIndexID();
1484b952cd58SEd Maste return LLDB_INVALID_INDEX32;
1485b952cd58SEd Maste }
14860127ef0fSEd Maste
GetCurrentException()1487*b5893f02SDimitry Andric SBValue SBThread::GetCurrentException() {
1488*b5893f02SDimitry Andric ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
1489*b5893f02SDimitry Andric if (!thread_sp) return SBValue();
1490*b5893f02SDimitry Andric
1491*b5893f02SDimitry Andric return SBValue(thread_sp->GetCurrentException());
1492*b5893f02SDimitry Andric }
1493*b5893f02SDimitry Andric
GetCurrentExceptionBacktrace()1494*b5893f02SDimitry Andric SBThread SBThread::GetCurrentExceptionBacktrace() {
1495*b5893f02SDimitry Andric ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
1496*b5893f02SDimitry Andric if (!thread_sp) return SBThread();
1497*b5893f02SDimitry Andric
1498*b5893f02SDimitry Andric return SBThread(thread_sp->GetCurrentExceptionBacktrace());
1499*b5893f02SDimitry Andric }
1500*b5893f02SDimitry Andric
SafeToCallFunctions()1501435933ddSDimitry Andric bool SBThread::SafeToCallFunctions() {
15020127ef0fSEd Maste ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
15030127ef0fSEd Maste if (thread_sp)
15040127ef0fSEd Maste return thread_sp->SafeToCallFunctions();
15050127ef0fSEd Maste return true;
15060127ef0fSEd Maste }
15077aa51b79SEd Maste
operator ->()1508435933ddSDimitry Andric lldb_private::Thread *SBThread::operator->() {
15097aa51b79SEd Maste ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
15107aa51b79SEd Maste if (thread_sp)
15117aa51b79SEd Maste return thread_sp.get();
15127aa51b79SEd Maste else
15137aa51b79SEd Maste return NULL;
15147aa51b79SEd Maste }
15157aa51b79SEd Maste
get()1516435933ddSDimitry Andric lldb_private::Thread *SBThread::get() {
15177aa51b79SEd Maste ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
15187aa51b79SEd Maste if (thread_sp)
15197aa51b79SEd Maste return thread_sp.get();
15207aa51b79SEd Maste else
15217aa51b79SEd Maste return NULL;
15227aa51b79SEd Maste }
1523