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