1cfca06d7SDimitry Andric //===-- SBThread.cpp ------------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f034231aSEd Maste #include "lldb/API/SBThread.h"
105f29bb8aSDimitry Andric #include "Utils.h"
115f29bb8aSDimitry Andric #include "lldb/API/SBAddress.h"
125f29bb8aSDimitry Andric #include "lldb/API/SBDebugger.h"
135f29bb8aSDimitry Andric #include "lldb/API/SBEvent.h"
14f034231aSEd Maste #include "lldb/API/SBFileSpec.h"
15b1c73532SDimitry Andric #include "lldb/API/SBFormat.h"
165f29bb8aSDimitry Andric #include "lldb/API/SBFrame.h"
175f29bb8aSDimitry Andric #include "lldb/API/SBProcess.h"
18f034231aSEd Maste #include "lldb/API/SBStream.h"
19ead24645SDimitry Andric #include "lldb/API/SBStructuredData.h"
2014f1b3e8SDimitry Andric #include "lldb/API/SBSymbolContext.h"
215f29bb8aSDimitry Andric #include "lldb/API/SBThreadCollection.h"
225f29bb8aSDimitry Andric #include "lldb/API/SBThreadPlan.h"
235f29bb8aSDimitry Andric #include "lldb/API/SBValue.h"
24f034231aSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
25f034231aSEd Maste #include "lldb/Core/Debugger.h"
26ead24645SDimitry Andric #include "lldb/Core/StructuredDataImpl.h"
275e95aa85SEd Maste #include "lldb/Core/ValueObject.h"
28f034231aSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
295e95aa85SEd Maste #include "lldb/Symbol/CompileUnit.h"
3014f1b3e8SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
31f034231aSEd Maste #include "lldb/Target/Process.h"
320cac4ca3SEd Maste #include "lldb/Target/Queue.h"
33f034231aSEd Maste #include "lldb/Target/StopInfo.h"
3414f1b3e8SDimitry Andric #include "lldb/Target/SystemRuntime.h"
35f034231aSEd Maste #include "lldb/Target/Target.h"
3614f1b3e8SDimitry Andric #include "lldb/Target/Thread.h"
37f034231aSEd Maste #include "lldb/Target/ThreadPlan.h"
3814f1b3e8SDimitry Andric #include "lldb/Target/ThreadPlanStepInRange.h"
39f034231aSEd Maste #include "lldb/Target/ThreadPlanStepInstruction.h"
40f034231aSEd Maste #include "lldb/Target/ThreadPlanStepOut.h"
41f034231aSEd Maste #include "lldb/Target/ThreadPlanStepRange.h"
426f8fc217SDimitry Andric #include "lldb/Utility/Instrumentation.h"
4394994d37SDimitry Andric #include "lldb/Utility/State.h"
4474a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
451b306c26SDimitry Andric #include "lldb/Utility/StructuredData.h"
4661b440f5SDimitry Andric #include "lldb/lldb-enumerations.h"
47f034231aSEd Maste
485f29bb8aSDimitry Andric #include <memory>
495f29bb8aSDimitry Andric
50f034231aSEd Maste using namespace lldb;
51f034231aSEd Maste using namespace lldb_private;
52f034231aSEd Maste
GetBroadcasterClassName()5314f1b3e8SDimitry Andric const char *SBThread::GetBroadcasterClassName() {
546f8fc217SDimitry Andric LLDB_INSTRUMENT();
555f29bb8aSDimitry Andric
56ac9a064cSDimitry Andric return ConstString(Thread::GetStaticBroadcasterClass()).AsCString();
57f034231aSEd Maste }
58f034231aSEd Maste
59f034231aSEd Maste // Constructors
SBThread()605f29bb8aSDimitry Andric SBThread::SBThread() : m_opaque_sp(new ExecutionContextRef()) {
616f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
62f034231aSEd Maste }
63f034231aSEd Maste
SBThread(const ThreadSP & lldb_object_sp)645f29bb8aSDimitry Andric SBThread::SBThread(const ThreadSP &lldb_object_sp)
655f29bb8aSDimitry Andric : m_opaque_sp(new ExecutionContextRef(lldb_object_sp)) {
666f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, lldb_object_sp);
675f29bb8aSDimitry Andric }
685f29bb8aSDimitry Andric
SBThread(const SBThread & rhs)696f8fc217SDimitry Andric SBThread::SBThread(const SBThread &rhs) {
706f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, rhs);
715f29bb8aSDimitry Andric
725f29bb8aSDimitry Andric m_opaque_sp = clone(rhs.m_opaque_sp);
735f29bb8aSDimitry Andric }
745f29bb8aSDimitry Andric
755f29bb8aSDimitry Andric // Assignment operator
765f29bb8aSDimitry Andric
operator =(const SBThread & rhs)775f29bb8aSDimitry Andric const lldb::SBThread &SBThread::operator=(const SBThread &rhs) {
786f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, rhs);
795f29bb8aSDimitry Andric
805f29bb8aSDimitry Andric if (this != &rhs)
815f29bb8aSDimitry Andric m_opaque_sp = clone(rhs.m_opaque_sp);
826f8fc217SDimitry Andric return *this;
835f29bb8aSDimitry Andric }
845f29bb8aSDimitry Andric
85f034231aSEd Maste // Destructor
86cfca06d7SDimitry Andric SBThread::~SBThread() = default;
87f034231aSEd Maste
GetQueue() const8814f1b3e8SDimitry Andric lldb::SBQueue SBThread::GetQueue() const {
896f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
905f29bb8aSDimitry Andric
910cac4ca3SEd Maste SBQueue sb_queue;
920cac4ca3SEd Maste QueueSP queue_sp;
93f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
94f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
950cac4ca3SEd Maste
9614f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
970cac4ca3SEd Maste Process::StopLocker stop_locker;
9814f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
990cac4ca3SEd Maste queue_sp = exe_ctx.GetThreadPtr()->GetQueue();
10014f1b3e8SDimitry Andric if (queue_sp) {
1010cac4ca3SEd Maste sb_queue.SetQueue(queue_sp);
1020cac4ca3SEd Maste }
1030cac4ca3SEd Maste }
1040cac4ca3SEd Maste }
1050cac4ca3SEd Maste
1066f8fc217SDimitry Andric return sb_queue;
1070cac4ca3SEd Maste }
1080cac4ca3SEd Maste
IsValid() const10914f1b3e8SDimitry Andric bool SBThread::IsValid() const {
1106f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
1115f29bb8aSDimitry Andric return this->operator bool();
1125f29bb8aSDimitry Andric }
operator bool() const1135f29bb8aSDimitry Andric SBThread::operator bool() const {
1146f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
1155f29bb8aSDimitry Andric
116f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
117f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
118f3fbd1c0SDimitry Andric
119f3fbd1c0SDimitry Andric Target *target = exe_ctx.GetTargetPtr();
120f3fbd1c0SDimitry Andric Process *process = exe_ctx.GetProcessPtr();
12114f1b3e8SDimitry Andric if (target && process) {
122f3fbd1c0SDimitry Andric Process::StopLocker stop_locker;
123f3fbd1c0SDimitry Andric if (stop_locker.TryLock(&process->GetRunLock()))
1245f29bb8aSDimitry Andric return m_opaque_sp->GetThreadSP().get() != nullptr;
125f034231aSEd Maste }
126f3fbd1c0SDimitry Andric // Without a valid target & process, this thread can't be valid.
127f3fbd1c0SDimitry Andric return false;
128f3fbd1c0SDimitry Andric }
129f034231aSEd Maste
Clear()1305f29bb8aSDimitry Andric void SBThread::Clear() {
1316f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
1325f29bb8aSDimitry Andric
1335f29bb8aSDimitry Andric m_opaque_sp->Clear();
1345f29bb8aSDimitry Andric }
135f034231aSEd Maste
GetStopReason()13614f1b3e8SDimitry Andric StopReason SBThread::GetStopReason() {
1376f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
138f034231aSEd Maste
139f034231aSEd Maste StopReason reason = eStopReasonInvalid;
140f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
141f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
142f034231aSEd Maste
14314f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
144f034231aSEd Maste Process::StopLocker stop_locker;
14514f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
146f034231aSEd Maste return exe_ctx.GetThreadPtr()->GetStopReason();
147f034231aSEd Maste }
148f034231aSEd Maste }
149f034231aSEd Maste
150f034231aSEd Maste return reason;
151f034231aSEd Maste }
152f034231aSEd Maste
GetStopReasonDataCount()15314f1b3e8SDimitry Andric size_t SBThread::GetStopReasonDataCount() {
1546f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
1555f29bb8aSDimitry Andric
156f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
157f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
158f034231aSEd Maste
15914f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
160f034231aSEd Maste Process::StopLocker stop_locker;
16114f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
162f034231aSEd Maste StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
16314f1b3e8SDimitry Andric if (stop_info_sp) {
164f034231aSEd Maste StopReason reason = stop_info_sp->GetStopReason();
16514f1b3e8SDimitry Andric switch (reason) {
166f034231aSEd Maste case eStopReasonInvalid:
167f034231aSEd Maste case eStopReasonNone:
168f034231aSEd Maste case eStopReasonTrace:
169f034231aSEd Maste case eStopReasonExec:
170f034231aSEd Maste case eStopReasonPlanComplete:
171f034231aSEd Maste case eStopReasonThreadExiting:
172205afe67SEd Maste case eStopReasonInstrumentation:
173344a3780SDimitry Andric case eStopReasonProcessorTrace:
174344a3780SDimitry Andric case eStopReasonVForkDone:
175f034231aSEd Maste // There is no data for these stop reasons.
176f034231aSEd Maste return 0;
177f034231aSEd Maste
17814f1b3e8SDimitry Andric case eStopReasonBreakpoint: {
179f034231aSEd Maste break_id_t site_id = stop_info_sp->GetValue();
18014f1b3e8SDimitry Andric lldb::BreakpointSiteSP bp_site_sp(
18114f1b3e8SDimitry Andric exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
18214f1b3e8SDimitry Andric site_id));
183f034231aSEd Maste if (bp_site_sp)
184b1c73532SDimitry Andric return bp_site_sp->GetNumberOfConstituents() * 2;
185f034231aSEd Maste else
186f034231aSEd Maste return 0; // Breakpoint must have cleared itself...
18714f1b3e8SDimitry Andric } break;
188f034231aSEd Maste
189f034231aSEd Maste case eStopReasonWatchpoint:
190f034231aSEd Maste return 1;
191f034231aSEd Maste
192f034231aSEd Maste case eStopReasonSignal:
193f034231aSEd Maste return 1;
194f034231aSEd Maste
195f034231aSEd Maste case eStopReasonException:
196f034231aSEd Maste return 1;
197344a3780SDimitry Andric
198344a3780SDimitry Andric case eStopReasonFork:
199344a3780SDimitry Andric return 1;
200344a3780SDimitry Andric
201344a3780SDimitry Andric case eStopReasonVFork:
202344a3780SDimitry Andric return 1;
203f034231aSEd Maste }
204f034231aSEd Maste }
205f034231aSEd Maste }
206f034231aSEd Maste }
207f034231aSEd Maste return 0;
208f034231aSEd Maste }
209f034231aSEd Maste
GetStopReasonDataAtIndex(uint32_t idx)21014f1b3e8SDimitry Andric uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) {
2116f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, idx);
2125f29bb8aSDimitry Andric
213f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
214f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
215f034231aSEd Maste
21614f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
217f034231aSEd Maste Process::StopLocker stop_locker;
21814f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
219f034231aSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
220f034231aSEd Maste StopInfoSP stop_info_sp = thread->GetStopInfo();
22114f1b3e8SDimitry Andric if (stop_info_sp) {
222f034231aSEd Maste StopReason reason = stop_info_sp->GetStopReason();
22314f1b3e8SDimitry Andric switch (reason) {
224f034231aSEd Maste case eStopReasonInvalid:
225f034231aSEd Maste case eStopReasonNone:
226f034231aSEd Maste case eStopReasonTrace:
227f034231aSEd Maste case eStopReasonExec:
228f034231aSEd Maste case eStopReasonPlanComplete:
229f034231aSEd Maste case eStopReasonThreadExiting:
230205afe67SEd Maste case eStopReasonInstrumentation:
231344a3780SDimitry Andric case eStopReasonProcessorTrace:
232344a3780SDimitry Andric case eStopReasonVForkDone:
233f034231aSEd Maste // There is no data for these stop reasons.
234f034231aSEd Maste return 0;
235f034231aSEd Maste
23614f1b3e8SDimitry Andric case eStopReasonBreakpoint: {
237f034231aSEd Maste break_id_t site_id = stop_info_sp->GetValue();
23814f1b3e8SDimitry Andric lldb::BreakpointSiteSP bp_site_sp(
23914f1b3e8SDimitry Andric exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
24014f1b3e8SDimitry Andric site_id));
24114f1b3e8SDimitry Andric if (bp_site_sp) {
242f034231aSEd Maste uint32_t bp_index = idx / 2;
24314f1b3e8SDimitry Andric BreakpointLocationSP bp_loc_sp(
244b1c73532SDimitry Andric bp_site_sp->GetConstituentAtIndex(bp_index));
24514f1b3e8SDimitry Andric if (bp_loc_sp) {
24614f1b3e8SDimitry Andric if (idx & 1) {
247f034231aSEd Maste // Odd idx, return the breakpoint location ID
248f034231aSEd Maste return bp_loc_sp->GetID();
24914f1b3e8SDimitry Andric } else {
250f034231aSEd Maste // Even idx, return the breakpoint ID
251f034231aSEd Maste return bp_loc_sp->GetBreakpoint().GetID();
252f034231aSEd Maste }
253f034231aSEd Maste }
254f034231aSEd Maste }
255f034231aSEd Maste return LLDB_INVALID_BREAK_ID;
25614f1b3e8SDimitry Andric } break;
257f034231aSEd Maste
258f034231aSEd Maste case eStopReasonWatchpoint:
259f034231aSEd Maste return stop_info_sp->GetValue();
260f034231aSEd Maste
261f034231aSEd Maste case eStopReasonSignal:
262f034231aSEd Maste return stop_info_sp->GetValue();
263f034231aSEd Maste
264f034231aSEd Maste case eStopReasonException:
265f034231aSEd Maste return stop_info_sp->GetValue();
266344a3780SDimitry Andric
267344a3780SDimitry Andric case eStopReasonFork:
268344a3780SDimitry Andric return stop_info_sp->GetValue();
269344a3780SDimitry Andric
270344a3780SDimitry Andric case eStopReasonVFork:
271344a3780SDimitry Andric return stop_info_sp->GetValue();
272f034231aSEd Maste }
273f034231aSEd Maste }
274f034231aSEd Maste }
275f034231aSEd Maste }
276f034231aSEd Maste return 0;
277f034231aSEd Maste }
278f034231aSEd Maste
GetStopReasonExtendedInfoAsJSON(lldb::SBStream & stream)27914f1b3e8SDimitry Andric bool SBThread::GetStopReasonExtendedInfoAsJSON(lldb::SBStream &stream) {
2806f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, stream);
2815f29bb8aSDimitry Andric
282205afe67SEd Maste Stream &strm = stream.ref();
283205afe67SEd Maste
284f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
285f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
286f3fbd1c0SDimitry Andric
287205afe67SEd Maste if (!exe_ctx.HasThreadScope())
288205afe67SEd Maste return false;
289205afe67SEd Maste
290205afe67SEd Maste StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
291205afe67SEd Maste StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
292205afe67SEd Maste if (!info)
293205afe67SEd Maste return false;
294205afe67SEd Maste
295205afe67SEd Maste info->Dump(strm);
296205afe67SEd Maste
297205afe67SEd Maste return true;
298205afe67SEd Maste }
299205afe67SEd Maste
300f3fbd1c0SDimitry Andric SBThreadCollection
GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type)30114f1b3e8SDimitry Andric SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) {
3026f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, type);
3035f29bb8aSDimitry Andric
304cfca06d7SDimitry Andric SBThreadCollection threads;
305f3fbd1c0SDimitry Andric
306f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
307f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
308f3fbd1c0SDimitry Andric
309f3fbd1c0SDimitry Andric if (!exe_ctx.HasThreadScope())
3106f8fc217SDimitry Andric return SBThreadCollection();
311f3fbd1c0SDimitry Andric
312f3fbd1c0SDimitry Andric ProcessSP process_sp = exe_ctx.GetProcessSP();
313f3fbd1c0SDimitry Andric
314f3fbd1c0SDimitry Andric StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
315f3fbd1c0SDimitry Andric StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
316f3fbd1c0SDimitry Andric if (!info)
3176f8fc217SDimitry Andric return threads;
318f3fbd1c0SDimitry Andric
319cfca06d7SDimitry Andric threads = process_sp->GetInstrumentationRuntime(type)
320cfca06d7SDimitry Andric ->GetBacktracesFromExtendedStopInfo(info);
3216f8fc217SDimitry Andric return threads;
322f3fbd1c0SDimitry Andric }
323f3fbd1c0SDimitry Andric
GetStopDescription(char * dst,size_t dst_len)32414f1b3e8SDimitry Andric size_t SBThread::GetStopDescription(char *dst, size_t dst_len) {
3256f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, dst, dst_len);
326f034231aSEd Maste
327f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
328f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
329f034231aSEd Maste
330f034231aSEd Maste if (dst)
331f034231aSEd Maste *dst = 0;
332cfca06d7SDimitry Andric
333cfca06d7SDimitry Andric if (!exe_ctx.HasThreadScope())
334f034231aSEd Maste return 0;
335cfca06d7SDimitry Andric
336cfca06d7SDimitry Andric Process::StopLocker stop_locker;
337cfca06d7SDimitry Andric if (!stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
338cfca06d7SDimitry Andric return 0;
339cfca06d7SDimitry Andric
340cfca06d7SDimitry Andric std::string thread_stop_desc = exe_ctx.GetThreadPtr()->GetStopDescription();
341cfca06d7SDimitry Andric if (thread_stop_desc.empty())
342cfca06d7SDimitry Andric return 0;
343cfca06d7SDimitry Andric
344cfca06d7SDimitry Andric if (dst)
345cfca06d7SDimitry Andric return ::snprintf(dst, dst_len, "%s", thread_stop_desc.c_str()) + 1;
346cfca06d7SDimitry Andric
347cfca06d7SDimitry Andric // NULL dst passed in, return the length needed to contain the
348cfca06d7SDimitry Andric // description.
349cfca06d7SDimitry Andric return thread_stop_desc.size() + 1; // Include the NULL byte for size
350f034231aSEd Maste }
351f034231aSEd Maste
GetStopReturnValue()35214f1b3e8SDimitry Andric SBValue SBThread::GetStopReturnValue() {
3536f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
3545f29bb8aSDimitry Andric
355f034231aSEd Maste ValueObjectSP return_valobj_sp;
356f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
357f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
358f034231aSEd Maste
35914f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
360f034231aSEd Maste Process::StopLocker stop_locker;
36114f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
362f034231aSEd Maste StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
36314f1b3e8SDimitry Andric if (stop_info_sp) {
364f034231aSEd Maste return_valobj_sp = StopInfo::GetReturnValueObject(stop_info_sp);
365f034231aSEd Maste }
366f034231aSEd Maste }
367f034231aSEd Maste }
368f034231aSEd Maste
3696f8fc217SDimitry Andric return SBValue(return_valobj_sp);
370f034231aSEd Maste }
371f034231aSEd Maste
SetThread(const ThreadSP & lldb_object_sp)37214f1b3e8SDimitry Andric void SBThread::SetThread(const ThreadSP &lldb_object_sp) {
373f034231aSEd Maste m_opaque_sp->SetThreadSP(lldb_object_sp);
374f034231aSEd Maste }
375f034231aSEd Maste
GetThreadID() const37614f1b3e8SDimitry Andric lldb::tid_t SBThread::GetThreadID() const {
3776f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
3785f29bb8aSDimitry Andric
379f034231aSEd Maste ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
380f034231aSEd Maste if (thread_sp)
381f034231aSEd Maste return thread_sp->GetID();
382f034231aSEd Maste return LLDB_INVALID_THREAD_ID;
383f034231aSEd Maste }
384f034231aSEd Maste
GetIndexID() const38514f1b3e8SDimitry Andric uint32_t SBThread::GetIndexID() const {
3866f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
3875f29bb8aSDimitry Andric
388f034231aSEd Maste ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
389f034231aSEd Maste if (thread_sp)
390f034231aSEd Maste return thread_sp->GetIndexID();
391f034231aSEd Maste return LLDB_INVALID_INDEX32;
392f034231aSEd Maste }
393f034231aSEd Maste
GetName() const39414f1b3e8SDimitry Andric const char *SBThread::GetName() const {
3956f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
3965f29bb8aSDimitry Andric
397f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
398f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
399f034231aSEd Maste
4007fa27ce4SDimitry Andric if (!exe_ctx.HasThreadScope())
4017fa27ce4SDimitry Andric return nullptr;
402f034231aSEd Maste
4037fa27ce4SDimitry Andric Process::StopLocker stop_locker;
4047fa27ce4SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
4057fa27ce4SDimitry Andric return ConstString(exe_ctx.GetThreadPtr()->GetName()).GetCString();
4067fa27ce4SDimitry Andric
4077fa27ce4SDimitry Andric return nullptr;
408f034231aSEd Maste }
409f034231aSEd Maste
GetQueueName() const41014f1b3e8SDimitry Andric const char *SBThread::GetQueueName() const {
4116f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
4125f29bb8aSDimitry Andric
413f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
414f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
415f034231aSEd Maste
4167fa27ce4SDimitry Andric if (!exe_ctx.HasThreadScope())
4177fa27ce4SDimitry Andric return nullptr;
418f034231aSEd Maste
4197fa27ce4SDimitry Andric Process::StopLocker stop_locker;
4207fa27ce4SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
4217fa27ce4SDimitry Andric return ConstString(exe_ctx.GetThreadPtr()->GetQueueName()).GetCString();
4227fa27ce4SDimitry Andric
4237fa27ce4SDimitry Andric return nullptr;
424f034231aSEd Maste }
425f034231aSEd Maste
GetQueueID() const42614f1b3e8SDimitry Andric lldb::queue_id_t SBThread::GetQueueID() const {
4276f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
4285f29bb8aSDimitry Andric
429f21a844fSEd Maste queue_id_t id = LLDB_INVALID_QUEUE_ID;
430f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
431f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
432f21a844fSEd Maste
43314f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
434f21a844fSEd Maste Process::StopLocker stop_locker;
43514f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
436f21a844fSEd Maste id = exe_ctx.GetThreadPtr()->GetQueueID();
437f21a844fSEd Maste }
438f21a844fSEd Maste }
439f21a844fSEd Maste
440f21a844fSEd Maste return id;
441f21a844fSEd Maste }
442f21a844fSEd Maste
GetInfoItemByPathAsString(const char * path,SBStream & strm)44314f1b3e8SDimitry Andric bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) {
4446f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, path, strm);
4455f29bb8aSDimitry Andric
4460cac4ca3SEd Maste bool success = false;
447f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
448f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
4490cac4ca3SEd Maste
45014f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
4510cac4ca3SEd Maste Process::StopLocker stop_locker;
45214f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
4530cac4ca3SEd Maste Thread *thread = exe_ctx.GetThreadPtr();
4540cac4ca3SEd Maste StructuredData::ObjectSP info_root_sp = thread->GetExtendedInfo();
45514f1b3e8SDimitry Andric if (info_root_sp) {
45614f1b3e8SDimitry Andric StructuredData::ObjectSP node =
45714f1b3e8SDimitry Andric info_root_sp->GetObjectForDotSeparatedPath(path);
45814f1b3e8SDimitry Andric if (node) {
45961b440f5SDimitry Andric if (node->GetType() == eStructuredDataTypeString) {
4607fa27ce4SDimitry Andric strm.ref() << node->GetAsString()->GetValue();
4610cac4ca3SEd Maste success = true;
4620cac4ca3SEd Maste }
46361b440f5SDimitry Andric if (node->GetType() == eStructuredDataTypeInteger) {
4647fa27ce4SDimitry Andric strm.Printf("0x%" PRIx64, node->GetUnsignedIntegerValue());
4650cac4ca3SEd Maste success = true;
4660cac4ca3SEd Maste }
46761b440f5SDimitry Andric if (node->GetType() == eStructuredDataTypeFloat) {
4680cac4ca3SEd Maste strm.Printf("0x%f", node->GetAsFloat()->GetValue());
4690cac4ca3SEd Maste success = true;
4700cac4ca3SEd Maste }
47161b440f5SDimitry Andric if (node->GetType() == eStructuredDataTypeBoolean) {
47294994d37SDimitry Andric if (node->GetAsBoolean()->GetValue())
4730cac4ca3SEd Maste strm.Printf("true");
4740cac4ca3SEd Maste else
4750cac4ca3SEd Maste strm.Printf("false");
4760cac4ca3SEd Maste success = true;
4770cac4ca3SEd Maste }
47861b440f5SDimitry Andric if (node->GetType() == eStructuredDataTypeNull) {
4790cac4ca3SEd Maste strm.Printf("null");
4800cac4ca3SEd Maste success = true;
4810cac4ca3SEd Maste }
4820cac4ca3SEd Maste }
4830cac4ca3SEd Maste }
4840cac4ca3SEd Maste }
4850cac4ca3SEd Maste }
4860cac4ca3SEd Maste
4870cac4ca3SEd Maste return success;
4880cac4ca3SEd Maste }
4890cac4ca3SEd Maste
ResumeNewPlan(ExecutionContext & exe_ctx,ThreadPlan * new_plan)49014f1b3e8SDimitry Andric SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx,
49114f1b3e8SDimitry Andric ThreadPlan *new_plan) {
492f034231aSEd Maste SBError sb_error;
493f034231aSEd Maste
494f034231aSEd Maste Process *process = exe_ctx.GetProcessPtr();
49514f1b3e8SDimitry Andric if (!process) {
496f034231aSEd Maste sb_error.SetErrorString("No process in SBThread::ResumeNewPlan");
497f034231aSEd Maste return sb_error;
498f034231aSEd Maste }
499f034231aSEd Maste
500f034231aSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
50114f1b3e8SDimitry Andric if (!thread) {
502f034231aSEd Maste sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan");
503f034231aSEd Maste return sb_error;
504f034231aSEd Maste }
505f034231aSEd Maste
506c0981da4SDimitry Andric // User level plans should be Controlling Plans so they can be interrupted,
507c0981da4SDimitry Andric // other plans executed, and then a "continue" will resume the plan.
5085f29bb8aSDimitry Andric if (new_plan != nullptr) {
509c0981da4SDimitry Andric new_plan->SetIsControllingPlan(true);
510f034231aSEd Maste new_plan->SetOkayToDiscard(false);
511f034231aSEd Maste }
512f034231aSEd Maste
513f034231aSEd Maste // Why do we need to set the current thread by ID here???
514f034231aSEd Maste process->GetThreadList().SetSelectedThreadByID(thread->GetID());
515f034231aSEd Maste
516205afe67SEd Maste if (process->GetTarget().GetDebugger().GetAsyncExecution())
517205afe67SEd Maste sb_error.ref() = process->Resume();
518205afe67SEd Maste else
5195f29bb8aSDimitry Andric sb_error.ref() = process->ResumeSynchronous(nullptr);
520f034231aSEd Maste
521f034231aSEd Maste return sb_error;
522f034231aSEd Maste }
523f034231aSEd Maste
StepOver(lldb::RunMode stop_other_threads)52414f1b3e8SDimitry Andric void SBThread::StepOver(lldb::RunMode stop_other_threads) {
5256f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, stop_other_threads);
5265f29bb8aSDimitry Andric
527f73363f1SDimitry Andric SBError error; // Ignored
528f73363f1SDimitry Andric StepOver(stop_other_threads, error);
529f73363f1SDimitry Andric }
530f73363f1SDimitry Andric
StepOver(lldb::RunMode stop_other_threads,SBError & error)531f73363f1SDimitry Andric void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) {
5326f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, stop_other_threads, error);
533f034231aSEd Maste
534f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
535f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
536f034231aSEd Maste
537f73363f1SDimitry Andric if (!exe_ctx.HasThreadScope()) {
538f73363f1SDimitry Andric error.SetErrorString("this SBThread object is invalid");
539f73363f1SDimitry Andric return;
540f73363f1SDimitry Andric }
541f73363f1SDimitry Andric
542f034231aSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
543f034231aSEd Maste bool abort_other_plans = false;
544f034231aSEd Maste StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
545f034231aSEd Maste
54694994d37SDimitry Andric Status new_plan_status;
547f034231aSEd Maste ThreadPlanSP new_plan_sp;
54814f1b3e8SDimitry Andric if (frame_sp) {
54914f1b3e8SDimitry Andric if (frame_sp->HasDebugInformation()) {
5500cac4ca3SEd Maste const LazyBool avoid_no_debug = eLazyBoolCalculate;
551f034231aSEd Maste SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
55214f1b3e8SDimitry Andric new_plan_sp = thread->QueueThreadPlanForStepOverRange(
55314f1b3e8SDimitry Andric abort_other_plans, sc.line_entry, sc, stop_other_threads,
55494994d37SDimitry Andric new_plan_status, avoid_no_debug);
55514f1b3e8SDimitry Andric } else {
55614f1b3e8SDimitry Andric new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
55794994d37SDimitry Andric true, abort_other_plans, stop_other_threads, new_plan_status);
558f034231aSEd Maste }
559f034231aSEd Maste }
560f73363f1SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
561f034231aSEd Maste }
562f034231aSEd Maste
StepInto(lldb::RunMode stop_other_threads)56314f1b3e8SDimitry Andric void SBThread::StepInto(lldb::RunMode stop_other_threads) {
5646f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, stop_other_threads);
5655f29bb8aSDimitry Andric
5665f29bb8aSDimitry Andric StepInto(nullptr, stop_other_threads);
567f034231aSEd Maste }
568f034231aSEd Maste
StepInto(const char * target_name,lldb::RunMode stop_other_threads)56914f1b3e8SDimitry Andric void SBThread::StepInto(const char *target_name,
57014f1b3e8SDimitry Andric lldb::RunMode stop_other_threads) {
5716f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, target_name, stop_other_threads);
5725f29bb8aSDimitry Andric
573f73363f1SDimitry Andric SBError error; // Ignored
574f3fbd1c0SDimitry Andric StepInto(target_name, LLDB_INVALID_LINE_NUMBER, error, stop_other_threads);
575f3fbd1c0SDimitry Andric }
576f3fbd1c0SDimitry Andric
StepInto(const char * target_name,uint32_t end_line,SBError & error,lldb::RunMode stop_other_threads)57714f1b3e8SDimitry Andric void SBThread::StepInto(const char *target_name, uint32_t end_line,
57814f1b3e8SDimitry Andric SBError &error, lldb::RunMode stop_other_threads) {
5796f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, target_name, end_line, error, stop_other_threads);
580f034231aSEd Maste
581f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
582f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
583f034231aSEd Maste
584f73363f1SDimitry Andric if (!exe_ctx.HasThreadScope()) {
585f73363f1SDimitry Andric error.SetErrorString("this SBThread object is invalid");
586f73363f1SDimitry Andric return;
587f73363f1SDimitry Andric }
588f73363f1SDimitry Andric
589f034231aSEd Maste bool abort_other_plans = false;
590f034231aSEd Maste
591f034231aSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
592f034231aSEd Maste StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
593f034231aSEd Maste ThreadPlanSP new_plan_sp;
59494994d37SDimitry Andric Status new_plan_status;
595f034231aSEd Maste
59614f1b3e8SDimitry Andric if (frame_sp && frame_sp->HasDebugInformation()) {
597f3fbd1c0SDimitry Andric SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
598f3fbd1c0SDimitry Andric AddressRange range;
599f3fbd1c0SDimitry Andric if (end_line == LLDB_INVALID_LINE_NUMBER)
600f3fbd1c0SDimitry Andric range = sc.line_entry.range;
60114f1b3e8SDimitry Andric else {
602f3fbd1c0SDimitry Andric if (!sc.GetAddressRangeFromHereToEndLine(end_line, range, error.ref()))
603f3fbd1c0SDimitry Andric return;
604f3fbd1c0SDimitry Andric }
605f3fbd1c0SDimitry Andric
60614f1b3e8SDimitry Andric const LazyBool step_out_avoids_code_without_debug_info =
60714f1b3e8SDimitry Andric eLazyBoolCalculate;
60814f1b3e8SDimitry Andric const LazyBool step_in_avoids_code_without_debug_info =
60914f1b3e8SDimitry Andric eLazyBoolCalculate;
61014f1b3e8SDimitry Andric new_plan_sp = thread->QueueThreadPlanForStepInRange(
61114f1b3e8SDimitry Andric abort_other_plans, range, sc, target_name, stop_other_threads,
61294994d37SDimitry Andric new_plan_status, step_in_avoids_code_without_debug_info,
6130cac4ca3SEd Maste step_out_avoids_code_without_debug_info);
61414f1b3e8SDimitry Andric } else {
61514f1b3e8SDimitry Andric new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
61694994d37SDimitry Andric false, abort_other_plans, stop_other_threads, new_plan_status);
617f034231aSEd Maste }
61894994d37SDimitry Andric
61994994d37SDimitry Andric if (new_plan_status.Success())
620f3fbd1c0SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
62194994d37SDimitry Andric else
62294994d37SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
623f034231aSEd Maste }
624f034231aSEd Maste
StepOut()62514f1b3e8SDimitry Andric void SBThread::StepOut() {
6266f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
6275f29bb8aSDimitry Andric
628f73363f1SDimitry Andric SBError error; // Ignored
629f73363f1SDimitry Andric StepOut(error);
630f73363f1SDimitry Andric }
631f73363f1SDimitry Andric
StepOut(SBError & error)632f73363f1SDimitry Andric void SBThread::StepOut(SBError &error) {
6336f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, error);
634f034231aSEd Maste
635f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
636f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
637f034231aSEd Maste
638f73363f1SDimitry Andric if (!exe_ctx.HasThreadScope()) {
639f73363f1SDimitry Andric error.SetErrorString("this SBThread object is invalid");
640f73363f1SDimitry Andric return;
641f73363f1SDimitry Andric }
642f73363f1SDimitry Andric
643f034231aSEd Maste bool abort_other_plans = false;
644f034231aSEd Maste bool stop_other_threads = false;
645f034231aSEd Maste
646f034231aSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
647f034231aSEd Maste
6480cac4ca3SEd Maste const LazyBool avoid_no_debug = eLazyBoolCalculate;
64994994d37SDimitry Andric Status new_plan_status;
65014f1b3e8SDimitry Andric ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
6515f29bb8aSDimitry Andric abort_other_plans, nullptr, false, stop_other_threads, eVoteYes,
65294994d37SDimitry Andric eVoteNoOpinion, 0, new_plan_status, avoid_no_debug));
653f034231aSEd Maste
65494994d37SDimitry Andric if (new_plan_status.Success())
655f73363f1SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
65694994d37SDimitry Andric else
65794994d37SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
658f034231aSEd Maste }
659f034231aSEd Maste
StepOutOfFrame(SBFrame & sb_frame)660f73363f1SDimitry Andric void SBThread::StepOutOfFrame(SBFrame &sb_frame) {
6616f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, sb_frame);
6625f29bb8aSDimitry Andric
663f73363f1SDimitry Andric SBError error; // Ignored
664f73363f1SDimitry Andric StepOutOfFrame(sb_frame, error);
665f73363f1SDimitry Andric }
666f73363f1SDimitry Andric
StepOutOfFrame(SBFrame & sb_frame,SBError & error)667f73363f1SDimitry Andric void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) {
6686f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, sb_frame, error);
669f034231aSEd Maste
670f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
671f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
672f034231aSEd Maste
67314f1b3e8SDimitry Andric if (!sb_frame.IsValid()) {
674f73363f1SDimitry Andric error.SetErrorString("passed invalid SBFrame object");
675e81d9d49SDimitry Andric return;
676e81d9d49SDimitry Andric }
677e81d9d49SDimitry Andric
678f034231aSEd Maste StackFrameSP frame_sp(sb_frame.GetFrameSP());
679f034231aSEd Maste
680f73363f1SDimitry Andric if (!exe_ctx.HasThreadScope()) {
681f73363f1SDimitry Andric error.SetErrorString("this SBThread object is invalid");
682f73363f1SDimitry Andric return;
683f73363f1SDimitry Andric }
684f73363f1SDimitry Andric
685f034231aSEd Maste bool abort_other_plans = false;
686f034231aSEd Maste bool stop_other_threads = false;
687f034231aSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
68814f1b3e8SDimitry Andric if (sb_frame.GetThread().GetThreadID() != thread->GetID()) {
689f73363f1SDimitry Andric error.SetErrorString("passed a frame from another thread");
690f73363f1SDimitry Andric return;
691e81d9d49SDimitry Andric }
692f034231aSEd Maste
69394994d37SDimitry Andric Status new_plan_status;
69414f1b3e8SDimitry Andric ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
6955f29bb8aSDimitry Andric abort_other_plans, nullptr, false, stop_other_threads, eVoteYes,
69694994d37SDimitry Andric eVoteNoOpinion, frame_sp->GetFrameIndex(), new_plan_status));
697f034231aSEd Maste
69894994d37SDimitry Andric if (new_plan_status.Success())
699f73363f1SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
70094994d37SDimitry Andric else
70194994d37SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
702f034231aSEd Maste }
703f034231aSEd Maste
StepInstruction(bool step_over)70414f1b3e8SDimitry Andric void SBThread::StepInstruction(bool step_over) {
7056f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, step_over);
7065f29bb8aSDimitry Andric
707f73363f1SDimitry Andric SBError error; // Ignored
708f73363f1SDimitry Andric StepInstruction(step_over, error);
709f73363f1SDimitry Andric }
710f73363f1SDimitry Andric
StepInstruction(bool step_over,SBError & error)711f73363f1SDimitry Andric void SBThread::StepInstruction(bool step_over, SBError &error) {
7126f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, step_over, error);
713f034231aSEd Maste
714f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
715f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
716f034231aSEd Maste
717f73363f1SDimitry Andric if (!exe_ctx.HasThreadScope()) {
718f73363f1SDimitry Andric error.SetErrorString("this SBThread object is invalid");
719f73363f1SDimitry Andric return;
720f73363f1SDimitry Andric }
721f73363f1SDimitry Andric
722f034231aSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
72394994d37SDimitry Andric Status new_plan_status;
72494994d37SDimitry Andric ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepSingleInstruction(
725ac9a064cSDimitry Andric step_over, false, true, new_plan_status));
726f034231aSEd Maste
72794994d37SDimitry Andric if (new_plan_status.Success())
728f73363f1SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
72994994d37SDimitry Andric else
73094994d37SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
731f034231aSEd Maste }
732f034231aSEd Maste
RunToAddress(lldb::addr_t addr)73314f1b3e8SDimitry Andric void SBThread::RunToAddress(lldb::addr_t addr) {
7346f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, addr);
7355f29bb8aSDimitry Andric
736f73363f1SDimitry Andric SBError error; // Ignored
737f73363f1SDimitry Andric RunToAddress(addr, error);
738f73363f1SDimitry Andric }
739f73363f1SDimitry Andric
RunToAddress(lldb::addr_t addr,SBError & error)740f73363f1SDimitry Andric void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) {
7416f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, addr, error);
742f034231aSEd Maste
743f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
744f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
745f034231aSEd Maste
746f73363f1SDimitry Andric if (!exe_ctx.HasThreadScope()) {
747f73363f1SDimitry Andric error.SetErrorString("this SBThread object is invalid");
748f73363f1SDimitry Andric return;
749f73363f1SDimitry Andric }
750f73363f1SDimitry Andric
751f034231aSEd Maste bool abort_other_plans = false;
752f034231aSEd Maste bool stop_other_threads = true;
753f034231aSEd Maste
754f034231aSEd Maste Address target_addr(addr);
755f034231aSEd Maste
756f034231aSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
757f034231aSEd Maste
75894994d37SDimitry Andric Status new_plan_status;
75914f1b3e8SDimitry Andric ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
76094994d37SDimitry Andric abort_other_plans, target_addr, stop_other_threads, new_plan_status));
761f034231aSEd Maste
76294994d37SDimitry Andric if (new_plan_status.Success())
763f73363f1SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
76494994d37SDimitry Andric else
76594994d37SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
766f034231aSEd Maste }
767f034231aSEd Maste
StepOverUntil(lldb::SBFrame & sb_frame,lldb::SBFileSpec & sb_file_spec,uint32_t line)76814f1b3e8SDimitry Andric SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
76914f1b3e8SDimitry Andric lldb::SBFileSpec &sb_file_spec, uint32_t line) {
7706f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, sb_frame, sb_file_spec, line);
7715f29bb8aSDimitry Andric
772f034231aSEd Maste SBError sb_error;
773f034231aSEd Maste char path[PATH_MAX];
774f034231aSEd Maste
775f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
776f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
777f034231aSEd Maste
778f034231aSEd Maste StackFrameSP frame_sp(sb_frame.GetFrameSP());
779f034231aSEd Maste
78014f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
781f034231aSEd Maste Target *target = exe_ctx.GetTargetPtr();
782f034231aSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
783f034231aSEd Maste
78414f1b3e8SDimitry Andric if (line == 0) {
785f034231aSEd Maste sb_error.SetErrorString("invalid line argument");
7866f8fc217SDimitry Andric return sb_error;
787f034231aSEd Maste }
788f034231aSEd Maste
78914f1b3e8SDimitry Andric if (!frame_sp) {
7907fa27ce4SDimitry Andric // We don't want to run SelectMostRelevantFrame here, for instance if
7917fa27ce4SDimitry Andric // you called a sequence of StepOverUntil's you wouldn't want the
7927fa27ce4SDimitry Andric // frame changed out from under you because you stepped into a
7937fa27ce4SDimitry Andric // recognized frame.
7947fa27ce4SDimitry Andric frame_sp = thread->GetSelectedFrame(DoNoSelectMostRelevantFrame);
795f034231aSEd Maste if (!frame_sp)
796f034231aSEd Maste frame_sp = thread->GetStackFrameAtIndex(0);
797f034231aSEd Maste }
798f034231aSEd Maste
799f034231aSEd Maste SymbolContext frame_sc;
80014f1b3e8SDimitry Andric if (!frame_sp) {
801f034231aSEd Maste sb_error.SetErrorString("no valid frames in thread to step");
8026f8fc217SDimitry Andric return sb_error;
803f034231aSEd Maste }
804f034231aSEd Maste
805f034231aSEd Maste // If we have a frame, get its line
80614f1b3e8SDimitry Andric frame_sc = frame_sp->GetSymbolContext(
80714f1b3e8SDimitry Andric eSymbolContextCompUnit | eSymbolContextFunction |
80814f1b3e8SDimitry Andric eSymbolContextLineEntry | eSymbolContextSymbol);
809f034231aSEd Maste
8105f29bb8aSDimitry Andric if (frame_sc.comp_unit == nullptr) {
81114f1b3e8SDimitry Andric sb_error.SetErrorStringWithFormat(
81214f1b3e8SDimitry Andric "frame %u doesn't have debug information", frame_sp->GetFrameIndex());
8136f8fc217SDimitry Andric return sb_error;
814f034231aSEd Maste }
815f034231aSEd Maste
816f034231aSEd Maste FileSpec step_file_spec;
81714f1b3e8SDimitry Andric if (sb_file_spec.IsValid()) {
818f034231aSEd Maste // The file spec passed in was valid, so use it
819f034231aSEd Maste step_file_spec = sb_file_spec.ref();
82014f1b3e8SDimitry Andric } else {
821f034231aSEd Maste if (frame_sc.line_entry.IsValid())
822ac9a064cSDimitry Andric step_file_spec = frame_sc.line_entry.GetFile();
82314f1b3e8SDimitry Andric else {
824f034231aSEd Maste sb_error.SetErrorString("invalid file argument or no file for frame");
8256f8fc217SDimitry Andric return sb_error;
826f034231aSEd Maste }
827f034231aSEd Maste }
828f034231aSEd Maste
829f034231aSEd Maste // Grab the current function, then we will make sure the "until" address is
830f034231aSEd Maste // within the function. We discard addresses that are out of the current
83114f1b3e8SDimitry Andric // function, and then if there are no addresses remaining, give an
832f73363f1SDimitry Andric // appropriate error message.
833f034231aSEd Maste
834f034231aSEd Maste bool all_in_function = true;
835f034231aSEd Maste AddressRange fun_range = frame_sc.function->GetAddressRange();
836f034231aSEd Maste
837f034231aSEd Maste std::vector<addr_t> step_over_until_addrs;
838f034231aSEd Maste const bool abort_other_plans = false;
839f034231aSEd Maste const bool stop_other_threads = false;
840344a3780SDimitry Andric // TODO: Handle SourceLocationSpec column information
841344a3780SDimitry Andric SourceLocationSpec location_spec(
842e3b55780SDimitry Andric step_file_spec, line, /*column=*/std::nullopt, /*check_inlines=*/true,
843344a3780SDimitry Andric /*exact_match=*/false);
844f034231aSEd Maste
845f034231aSEd Maste SymbolContextList sc_list;
846344a3780SDimitry Andric frame_sc.comp_unit->ResolveSymbolContext(location_spec,
847706b4fc4SDimitry Andric eSymbolContextLineEntry, sc_list);
8487fa27ce4SDimitry Andric for (const SymbolContext &sc : sc_list) {
84914f1b3e8SDimitry Andric addr_t step_addr =
85014f1b3e8SDimitry Andric sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
85114f1b3e8SDimitry Andric if (step_addr != LLDB_INVALID_ADDRESS) {
852f034231aSEd Maste if (fun_range.ContainsLoadAddress(step_addr, target))
853f034231aSEd Maste step_over_until_addrs.push_back(step_addr);
854f034231aSEd Maste else
855f034231aSEd Maste all_in_function = false;
856f034231aSEd Maste }
857f034231aSEd Maste }
858f034231aSEd Maste
85914f1b3e8SDimitry Andric if (step_over_until_addrs.empty()) {
86014f1b3e8SDimitry Andric if (all_in_function) {
861f034231aSEd Maste step_file_spec.GetPath(path, sizeof(path));
86214f1b3e8SDimitry Andric sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path,
86314f1b3e8SDimitry Andric line);
86414f1b3e8SDimitry Andric } else
865f034231aSEd Maste sb_error.SetErrorString("step until target not in current function");
86614f1b3e8SDimitry Andric } else {
86794994d37SDimitry Andric Status new_plan_status;
86814f1b3e8SDimitry Andric ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepUntil(
86914f1b3e8SDimitry Andric abort_other_plans, &step_over_until_addrs[0],
87014f1b3e8SDimitry Andric step_over_until_addrs.size(), stop_other_threads,
87194994d37SDimitry Andric frame_sp->GetFrameIndex(), new_plan_status));
872f034231aSEd Maste
87394994d37SDimitry Andric if (new_plan_status.Success())
874f034231aSEd Maste sb_error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
87594994d37SDimitry Andric else
87694994d37SDimitry Andric sb_error.SetErrorString(new_plan_status.AsCString());
877f034231aSEd Maste }
87814f1b3e8SDimitry Andric } else {
879f034231aSEd Maste sb_error.SetErrorString("this SBThread object is invalid");
880f034231aSEd Maste }
8816f8fc217SDimitry Andric return sb_error;
882f034231aSEd Maste }
883f034231aSEd Maste
StepUsingScriptedThreadPlan(const char * script_class_name)88414f1b3e8SDimitry Andric SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name) {
8856f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, script_class_name);
8865f29bb8aSDimitry Andric
8876f8fc217SDimitry Andric return StepUsingScriptedThreadPlan(script_class_name, true);
88814f1b3e8SDimitry Andric }
88914f1b3e8SDimitry Andric
StepUsingScriptedThreadPlan(const char * script_class_name,bool resume_immediately)89014f1b3e8SDimitry Andric SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
89114f1b3e8SDimitry Andric bool resume_immediately) {
8926f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, script_class_name, resume_immediately);
8935f29bb8aSDimitry Andric
894ead24645SDimitry Andric lldb::SBStructuredData no_data;
8956f8fc217SDimitry Andric return StepUsingScriptedThreadPlan(script_class_name, no_data,
8966f8fc217SDimitry Andric resume_immediately);
897ead24645SDimitry Andric }
898ead24645SDimitry Andric
StepUsingScriptedThreadPlan(const char * script_class_name,SBStructuredData & args_data,bool resume_immediately)899ead24645SDimitry Andric SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
900ead24645SDimitry Andric SBStructuredData &args_data,
901ead24645SDimitry Andric bool resume_immediately) {
9026f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, script_class_name, args_data, resume_immediately);
903ead24645SDimitry Andric
90494994d37SDimitry Andric SBError error;
905205afe67SEd Maste
906f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
907f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
908205afe67SEd Maste
90914f1b3e8SDimitry Andric if (!exe_ctx.HasThreadScope()) {
91094994d37SDimitry Andric error.SetErrorString("this SBThread object is invalid");
9116f8fc217SDimitry Andric return error;
912205afe67SEd Maste }
913205afe67SEd Maste
914205afe67SEd Maste Thread *thread = exe_ctx.GetThreadPtr();
91594994d37SDimitry Andric Status new_plan_status;
916ead24645SDimitry Andric StructuredData::ObjectSP obj_sp = args_data.m_impl_up->GetObjectSP();
917ead24645SDimitry Andric
91894994d37SDimitry Andric ThreadPlanSP new_plan_sp = thread->QueueThreadPlanForStepScripted(
919ead24645SDimitry Andric false, script_class_name, obj_sp, false, new_plan_status);
92014f1b3e8SDimitry Andric
92194994d37SDimitry Andric if (new_plan_status.Fail()) {
92294994d37SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
9236f8fc217SDimitry Andric return error;
92414f1b3e8SDimitry Andric }
92514f1b3e8SDimitry Andric
92694994d37SDimitry Andric if (!resume_immediately)
9276f8fc217SDimitry Andric return error;
928205afe67SEd Maste
92994994d37SDimitry Andric if (new_plan_status.Success())
93094994d37SDimitry Andric error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
93194994d37SDimitry Andric else
93294994d37SDimitry Andric error.SetErrorString(new_plan_status.AsCString());
933205afe67SEd Maste
9346f8fc217SDimitry Andric return error;
935205afe67SEd Maste }
936205afe67SEd Maste
JumpToLine(lldb::SBFileSpec & file_spec,uint32_t line)93714f1b3e8SDimitry Andric SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) {
9386f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, file_spec, line);
9395f29bb8aSDimitry Andric
940f21a844fSEd Maste SBError sb_error;
941f21a844fSEd Maste
942f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
943f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
944f21a844fSEd Maste
94514f1b3e8SDimitry Andric if (!exe_ctx.HasThreadScope()) {
946f21a844fSEd Maste sb_error.SetErrorString("this SBThread object is invalid");
9476f8fc217SDimitry Andric return sb_error;
948f21a844fSEd Maste }
949f21a844fSEd Maste
950f21a844fSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
951f21a844fSEd Maste
952706b4fc4SDimitry Andric Status err = thread->JumpToLine(file_spec.ref(), line, true);
953f21a844fSEd Maste sb_error.SetError(err);
9546f8fc217SDimitry Andric return sb_error;
955f21a844fSEd Maste }
956f21a844fSEd Maste
ReturnFromFrame(SBFrame & frame,SBValue & return_value)95714f1b3e8SDimitry Andric SBError SBThread::ReturnFromFrame(SBFrame &frame, SBValue &return_value) {
9586f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, frame, return_value);
959f034231aSEd Maste
9605f29bb8aSDimitry Andric SBError sb_error;
961f034231aSEd Maste
962f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
963f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
964f034231aSEd Maste
96514f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
966f034231aSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
96714f1b3e8SDimitry Andric sb_error.SetError(
96814f1b3e8SDimitry Andric thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
969f034231aSEd Maste }
970f034231aSEd Maste
9716f8fc217SDimitry Andric return sb_error;
972f034231aSEd Maste }
973f034231aSEd Maste
UnwindInnermostExpression()97414f1b3e8SDimitry Andric SBError SBThread::UnwindInnermostExpression() {
9756f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
976f3fbd1c0SDimitry Andric
9775f29bb8aSDimitry Andric SBError sb_error;
978f3fbd1c0SDimitry Andric
979f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
980f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
981f3fbd1c0SDimitry Andric
98214f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
983f3fbd1c0SDimitry Andric Thread *thread = exe_ctx.GetThreadPtr();
984f3fbd1c0SDimitry Andric sb_error.SetError(thread->UnwindInnermostExpression());
985f3fbd1c0SDimitry Andric if (sb_error.Success())
986f3fbd1c0SDimitry Andric thread->SetSelectedFrameByIndex(0, false);
987f3fbd1c0SDimitry Andric }
988f3fbd1c0SDimitry Andric
9896f8fc217SDimitry Andric return sb_error;
990f3fbd1c0SDimitry Andric }
991f034231aSEd Maste
Suspend()99214f1b3e8SDimitry Andric bool SBThread::Suspend() {
9936f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
9945f29bb8aSDimitry Andric
995f73363f1SDimitry Andric SBError error; // Ignored
996f73363f1SDimitry Andric return Suspend(error);
997f73363f1SDimitry Andric }
998f73363f1SDimitry Andric
Suspend(SBError & error)999f73363f1SDimitry Andric bool SBThread::Suspend(SBError &error) {
10006f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, error);
10015f29bb8aSDimitry Andric
1002f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1003f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1004f3fbd1c0SDimitry Andric
1005f034231aSEd Maste bool result = false;
100614f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
1007f034231aSEd Maste Process::StopLocker stop_locker;
100814f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1009f034231aSEd Maste exe_ctx.GetThreadPtr()->SetResumeState(eStateSuspended);
1010f034231aSEd Maste result = true;
101114f1b3e8SDimitry Andric } else {
1012f73363f1SDimitry Andric error.SetErrorString("process is running");
1013f034231aSEd Maste }
1014f73363f1SDimitry Andric } else
1015f73363f1SDimitry Andric error.SetErrorString("this SBThread object is invalid");
1016f034231aSEd Maste return result;
1017f034231aSEd Maste }
1018f034231aSEd Maste
Resume()101914f1b3e8SDimitry Andric bool SBThread::Resume() {
10206f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
10215f29bb8aSDimitry Andric
1022f73363f1SDimitry Andric SBError error; // Ignored
1023f73363f1SDimitry Andric return Resume(error);
1024f73363f1SDimitry Andric }
1025f73363f1SDimitry Andric
Resume(SBError & error)1026f73363f1SDimitry Andric bool SBThread::Resume(SBError &error) {
10276f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, error);
10285f29bb8aSDimitry Andric
1029f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1030f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1031f3fbd1c0SDimitry Andric
1032f034231aSEd Maste bool result = false;
103314f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
1034f034231aSEd Maste Process::StopLocker stop_locker;
103514f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
10360cac4ca3SEd Maste const bool override_suspend = true;
10370cac4ca3SEd Maste exe_ctx.GetThreadPtr()->SetResumeState(eStateRunning, override_suspend);
1038f034231aSEd Maste result = true;
103914f1b3e8SDimitry Andric } else {
1040f73363f1SDimitry Andric error.SetErrorString("process is running");
1041f034231aSEd Maste }
1042f73363f1SDimitry Andric } else
1043f73363f1SDimitry Andric error.SetErrorString("this SBThread object is invalid");
1044f034231aSEd Maste return result;
1045f034231aSEd Maste }
1046f034231aSEd Maste
IsSuspended()104714f1b3e8SDimitry Andric bool SBThread::IsSuspended() {
10486f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
10495f29bb8aSDimitry Andric
1050f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1051f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1052f3fbd1c0SDimitry Andric
1053f034231aSEd Maste if (exe_ctx.HasThreadScope())
1054f034231aSEd Maste return exe_ctx.GetThreadPtr()->GetResumeState() == eStateSuspended;
1055f034231aSEd Maste return false;
1056f034231aSEd Maste }
1057f034231aSEd Maste
IsStopped()105814f1b3e8SDimitry Andric bool SBThread::IsStopped() {
10596f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
10605f29bb8aSDimitry Andric
1061f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1062f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1063f3fbd1c0SDimitry Andric
1064f034231aSEd Maste if (exe_ctx.HasThreadScope())
1065f034231aSEd Maste return StateIsStoppedState(exe_ctx.GetThreadPtr()->GetState(), true);
1066f034231aSEd Maste return false;
1067f034231aSEd Maste }
1068f034231aSEd Maste
GetProcess()106914f1b3e8SDimitry Andric SBProcess SBThread::GetProcess() {
10706f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
10715f29bb8aSDimitry Andric
1072f034231aSEd Maste SBProcess sb_process;
1073f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1074f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1075f3fbd1c0SDimitry Andric
107614f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
107714f1b3e8SDimitry Andric // Have to go up to the target so we can get a shared pointer to our
107814f1b3e8SDimitry Andric // process...
1079f034231aSEd Maste sb_process.SetSP(exe_ctx.GetProcessSP());
1080f034231aSEd Maste }
1081f034231aSEd Maste
10826f8fc217SDimitry Andric return sb_process;
1083f034231aSEd Maste }
1084f034231aSEd Maste
GetNumFrames()108514f1b3e8SDimitry Andric uint32_t SBThread::GetNumFrames() {
10866f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
1087f034231aSEd Maste
1088f034231aSEd Maste uint32_t num_frames = 0;
1089f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1090f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1091f034231aSEd Maste
109214f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
1093f034231aSEd Maste Process::StopLocker stop_locker;
109414f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1095f034231aSEd Maste num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount();
1096f034231aSEd Maste }
1097f034231aSEd Maste }
1098f034231aSEd Maste
1099f034231aSEd Maste return num_frames;
1100f034231aSEd Maste }
1101f034231aSEd Maste
GetFrameAtIndex(uint32_t idx)110214f1b3e8SDimitry Andric SBFrame SBThread::GetFrameAtIndex(uint32_t idx) {
11036f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, idx);
1104f034231aSEd Maste
1105f034231aSEd Maste SBFrame sb_frame;
1106f034231aSEd Maste StackFrameSP frame_sp;
1107f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1108f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1109f034231aSEd Maste
111014f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
1111f034231aSEd Maste Process::StopLocker stop_locker;
111214f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1113f034231aSEd Maste frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx);
1114f034231aSEd Maste sb_frame.SetFrameSP(frame_sp);
1115f034231aSEd Maste }
1116f034231aSEd Maste }
1117f034231aSEd Maste
11186f8fc217SDimitry Andric return sb_frame;
1119f034231aSEd Maste }
1120f034231aSEd Maste
GetSelectedFrame()112114f1b3e8SDimitry Andric lldb::SBFrame SBThread::GetSelectedFrame() {
11226f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
1123f034231aSEd Maste
1124f034231aSEd Maste SBFrame sb_frame;
1125f034231aSEd Maste StackFrameSP frame_sp;
1126f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1127f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1128f034231aSEd Maste
112914f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
1130f034231aSEd Maste Process::StopLocker stop_locker;
113114f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
11327fa27ce4SDimitry Andric frame_sp =
11337fa27ce4SDimitry Andric exe_ctx.GetThreadPtr()->GetSelectedFrame(SelectMostRelevantFrame);
1134f034231aSEd Maste sb_frame.SetFrameSP(frame_sp);
1135f034231aSEd Maste }
1136f034231aSEd Maste }
1137f034231aSEd Maste
11386f8fc217SDimitry Andric return sb_frame;
1139f034231aSEd Maste }
1140f034231aSEd Maste
SetSelectedFrame(uint32_t idx)114114f1b3e8SDimitry Andric lldb::SBFrame SBThread::SetSelectedFrame(uint32_t idx) {
11426f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, idx);
1143f034231aSEd Maste
1144f034231aSEd Maste SBFrame sb_frame;
1145f034231aSEd Maste StackFrameSP frame_sp;
1146f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1147f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1148f034231aSEd Maste
114914f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
1150f034231aSEd Maste Process::StopLocker stop_locker;
115114f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1152f034231aSEd Maste Thread *thread = exe_ctx.GetThreadPtr();
1153f034231aSEd Maste frame_sp = thread->GetStackFrameAtIndex(idx);
115414f1b3e8SDimitry Andric if (frame_sp) {
1155f034231aSEd Maste thread->SetSelectedFrame(frame_sp.get());
1156f034231aSEd Maste sb_frame.SetFrameSP(frame_sp);
1157f034231aSEd Maste }
1158f034231aSEd Maste }
1159f034231aSEd Maste }
1160f034231aSEd Maste
11616f8fc217SDimitry Andric return sb_frame;
1162f034231aSEd Maste }
1163f034231aSEd Maste
EventIsThreadEvent(const SBEvent & event)116414f1b3e8SDimitry Andric bool SBThread::EventIsThreadEvent(const SBEvent &event) {
11656f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(event);
11665f29bb8aSDimitry Andric
11675f29bb8aSDimitry Andric return Thread::ThreadEventData::GetEventDataFromEvent(event.get()) != nullptr;
1168f034231aSEd Maste }
1169f034231aSEd Maste
GetStackFrameFromEvent(const SBEvent & event)117014f1b3e8SDimitry Andric SBFrame SBThread::GetStackFrameFromEvent(const SBEvent &event) {
11716f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(event);
11725f29bb8aSDimitry Andric
11736f8fc217SDimitry Andric return Thread::ThreadEventData::GetStackFrameFromEvent(event.get());
1174f034231aSEd Maste }
1175f034231aSEd Maste
GetThreadFromEvent(const SBEvent & event)117614f1b3e8SDimitry Andric SBThread SBThread::GetThreadFromEvent(const SBEvent &event) {
11776f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(event);
11785f29bb8aSDimitry Andric
11796f8fc217SDimitry Andric return Thread::ThreadEventData::GetThreadFromEvent(event.get());
1180f034231aSEd Maste }
1181f034231aSEd Maste
operator ==(const SBThread & rhs) const118214f1b3e8SDimitry Andric bool SBThread::operator==(const SBThread &rhs) const {
11836f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, rhs);
11845f29bb8aSDimitry Andric
118514f1b3e8SDimitry Andric return m_opaque_sp->GetThreadSP().get() ==
118614f1b3e8SDimitry Andric rhs.m_opaque_sp->GetThreadSP().get();
1187f034231aSEd Maste }
1188f034231aSEd Maste
operator !=(const SBThread & rhs) const118914f1b3e8SDimitry Andric bool SBThread::operator!=(const SBThread &rhs) const {
11906f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, rhs);
11915f29bb8aSDimitry Andric
119214f1b3e8SDimitry Andric return m_opaque_sp->GetThreadSP().get() !=
119314f1b3e8SDimitry Andric rhs.m_opaque_sp->GetThreadSP().get();
1194f034231aSEd Maste }
1195f034231aSEd Maste
GetStatus(SBStream & status) const119614f1b3e8SDimitry Andric bool SBThread::GetStatus(SBStream &status) const {
11976f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, status);
11985f29bb8aSDimitry Andric
1199f034231aSEd Maste Stream &strm = status.ref();
1200f034231aSEd Maste
1201f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1202f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1203f3fbd1c0SDimitry Andric
120414f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
120514f1b3e8SDimitry Andric exe_ctx.GetThreadPtr()->GetStatus(strm, 0, 1, 1, true);
120614f1b3e8SDimitry Andric } else
1207f034231aSEd Maste strm.PutCString("No status");
1208f034231aSEd Maste
1209f034231aSEd Maste return true;
1210f034231aSEd Maste }
1211f034231aSEd Maste
GetDescription(SBStream & description) const121214f1b3e8SDimitry Andric bool SBThread::GetDescription(SBStream &description) const {
12136f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, description);
12145f29bb8aSDimitry Andric
121514f1b3e8SDimitry Andric return GetDescription(description, false);
121614f1b3e8SDimitry Andric }
121714f1b3e8SDimitry Andric
GetDescription(SBStream & description,bool stop_format) const121814f1b3e8SDimitry Andric bool SBThread::GetDescription(SBStream &description, bool stop_format) const {
12196f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, description, stop_format);
12205f29bb8aSDimitry Andric
1221f034231aSEd Maste Stream &strm = description.ref();
1222f034231aSEd Maste
1223f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1224f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1225f3fbd1c0SDimitry Andric
122614f1b3e8SDimitry Andric if (exe_ctx.HasThreadScope()) {
1227b1c73532SDimitry Andric exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat(
1228b1c73532SDimitry Andric strm, LLDB_INVALID_THREAD_ID, stop_format);
122914f1b3e8SDimitry Andric } else
1230f034231aSEd Maste strm.PutCString("No value");
1231f034231aSEd Maste
1232f034231aSEd Maste return true;
1233f034231aSEd Maste }
1234f21a844fSEd Maste
GetDescriptionWithFormat(const SBFormat & format,SBStream & output)1235b1c73532SDimitry Andric SBError SBThread::GetDescriptionWithFormat(const SBFormat &format,
1236b1c73532SDimitry Andric SBStream &output) {
1237b1c73532SDimitry Andric Stream &strm = output.ref();
1238b1c73532SDimitry Andric
1239b1c73532SDimitry Andric SBError error;
1240b1c73532SDimitry Andric if (!format) {
1241b1c73532SDimitry Andric error.SetErrorString("The provided SBFormat object is invalid");
1242b1c73532SDimitry Andric return error;
1243b1c73532SDimitry Andric }
1244b1c73532SDimitry Andric
1245b1c73532SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1246b1c73532SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1247b1c73532SDimitry Andric
1248b1c73532SDimitry Andric if (exe_ctx.HasThreadScope()) {
1249b1c73532SDimitry Andric if (exe_ctx.GetThreadPtr()->DumpUsingFormat(
1250b1c73532SDimitry Andric strm, LLDB_INVALID_THREAD_ID, format.GetFormatEntrySP().get())) {
1251b1c73532SDimitry Andric return error;
1252b1c73532SDimitry Andric }
1253b1c73532SDimitry Andric }
1254b1c73532SDimitry Andric
1255b1c73532SDimitry Andric error.SetErrorStringWithFormat(
1256b1c73532SDimitry Andric "It was not possible to generate a thread description with the given "
1257b1c73532SDimitry Andric "format string '%s'",
1258b1c73532SDimitry Andric format.GetFormatEntrySP()->string.c_str());
1259b1c73532SDimitry Andric return error;
1260b1c73532SDimitry Andric }
1261b1c73532SDimitry Andric
GetExtendedBacktraceThread(const char * type)126214f1b3e8SDimitry Andric SBThread SBThread::GetExtendedBacktraceThread(const char *type) {
12636f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, type);
12645f29bb8aSDimitry Andric
1265f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1266f3fbd1c0SDimitry Andric ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1267f21a844fSEd Maste SBThread sb_origin_thread;
1268f21a844fSEd Maste
1269f21a844fSEd Maste Process::StopLocker stop_locker;
127014f1b3e8SDimitry Andric if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
12715f29bb8aSDimitry Andric if (exe_ctx.HasThreadScope()) {
127286758c71SEd Maste ThreadSP real_thread(exe_ctx.GetThreadSP());
127314f1b3e8SDimitry Andric if (real_thread) {
1274f21a844fSEd Maste ConstString type_const(type);
127586758c71SEd Maste Process *process = exe_ctx.GetProcessPtr();
127614f1b3e8SDimitry Andric if (process) {
127786758c71SEd Maste SystemRuntime *runtime = process->GetSystemRuntime();
127814f1b3e8SDimitry Andric if (runtime) {
127914f1b3e8SDimitry Andric ThreadSP new_thread_sp(
128014f1b3e8SDimitry Andric runtime->GetExtendedBacktraceThread(real_thread, type_const));
128114f1b3e8SDimitry Andric if (new_thread_sp) {
128214f1b3e8SDimitry Andric // Save this in the Process' ExtendedThreadList so a strong
1283f73363f1SDimitry Andric // pointer retains the object.
128486758c71SEd Maste process->GetExtendedThreadList().AddThread(new_thread_sp);
128586758c71SEd Maste sb_origin_thread.SetThread(new_thread_sp);
128686758c71SEd Maste }
128786758c71SEd Maste }
128886758c71SEd Maste }
1289f21a844fSEd Maste }
1290f21a844fSEd Maste }
1291f21a844fSEd Maste }
1292f21a844fSEd Maste
12936f8fc217SDimitry Andric return sb_origin_thread;
1294f21a844fSEd Maste }
129586758c71SEd Maste
GetExtendedBacktraceOriginatingIndexID()129614f1b3e8SDimitry Andric uint32_t SBThread::GetExtendedBacktraceOriginatingIndexID() {
12976f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
12985f29bb8aSDimitry Andric
129986758c71SEd Maste ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
130086758c71SEd Maste if (thread_sp)
130186758c71SEd Maste return thread_sp->GetExtendedBacktraceOriginatingIndexID();
130286758c71SEd Maste return LLDB_INVALID_INDEX32;
130386758c71SEd Maste }
13040cac4ca3SEd Maste
GetCurrentException()130594994d37SDimitry Andric SBValue SBThread::GetCurrentException() {
13066f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
130794994d37SDimitry Andric
13085f29bb8aSDimitry Andric ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
13095f29bb8aSDimitry Andric if (!thread_sp)
13106f8fc217SDimitry Andric return SBValue();
13115f29bb8aSDimitry Andric
13126f8fc217SDimitry Andric return SBValue(thread_sp->GetCurrentException());
131394994d37SDimitry Andric }
131494994d37SDimitry Andric
GetCurrentExceptionBacktrace()131594994d37SDimitry Andric SBThread SBThread::GetCurrentExceptionBacktrace() {
13166f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
131794994d37SDimitry Andric
13185f29bb8aSDimitry Andric ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
13195f29bb8aSDimitry Andric if (!thread_sp)
13206f8fc217SDimitry Andric return SBThread();
13215f29bb8aSDimitry Andric
13226f8fc217SDimitry Andric return SBThread(thread_sp->GetCurrentExceptionBacktrace());
132394994d37SDimitry Andric }
132494994d37SDimitry Andric
SafeToCallFunctions()132514f1b3e8SDimitry Andric bool SBThread::SafeToCallFunctions() {
13266f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
13275f29bb8aSDimitry Andric
13280cac4ca3SEd Maste ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
13290cac4ca3SEd Maste if (thread_sp)
13300cac4ca3SEd Maste return thread_sp->SafeToCallFunctions();
13310cac4ca3SEd Maste return true;
13320cac4ca3SEd Maste }
1333205afe67SEd Maste
operator ->()133414f1b3e8SDimitry Andric lldb_private::Thread *SBThread::operator->() {
13355f29bb8aSDimitry Andric return get();
1336205afe67SEd Maste }
1337205afe67SEd Maste
get()133814f1b3e8SDimitry Andric lldb_private::Thread *SBThread::get() {
13395f29bb8aSDimitry Andric return m_opaque_sp->GetThreadSP().get();
13405f29bb8aSDimitry Andric }
13415f29bb8aSDimitry Andric
GetSiginfo()1342ecbca9f5SDimitry Andric SBValue SBThread::GetSiginfo() {
1343ecbca9f5SDimitry Andric LLDB_INSTRUMENT_VA(this);
13445f29bb8aSDimitry Andric
13456f8fc217SDimitry Andric ThreadSP thread_sp = m_opaque_sp->GetThreadSP();
1346ecbca9f5SDimitry Andric if (!thread_sp)
1347ecbca9f5SDimitry Andric return SBValue();
1348ecbca9f5SDimitry Andric return thread_sp->GetSiginfoValue();
1349205afe67SEd Maste }
1350