15ffd83dbSDimitry Andric //===-- Thread.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/Target/Thread.h" 100b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h" 110b57cec5SDimitry Andric #include "lldb/Core/Debugger.h" 120b57cec5SDimitry Andric #include "lldb/Core/FormatEntity.h" 130b57cec5SDimitry Andric #include "lldb/Core/Module.h" 149dba64beSDimitry Andric #include "lldb/Core/StructuredDataImpl.h" 150b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h" 161fd87a68SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h" 170b57cec5SDimitry Andric #include "lldb/Host/Host.h" 180b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueFileSpecList.h" 190b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueProperties.h" 200b57cec5SDimitry Andric #include "lldb/Interpreter/Property.h" 210b57cec5SDimitry Andric #include "lldb/Symbol/Function.h" 220b57cec5SDimitry Andric #include "lldb/Target/ABI.h" 230b57cec5SDimitry Andric #include "lldb/Target/DynamicLoader.h" 240b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h" 250b57cec5SDimitry Andric #include "lldb/Target/LanguageRuntime.h" 260b57cec5SDimitry Andric #include "lldb/Target/Process.h" 270b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h" 280b57cec5SDimitry Andric #include "lldb/Target/StackFrameRecognizer.h" 290b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h" 300b57cec5SDimitry Andric #include "lldb/Target/SystemRuntime.h" 310b57cec5SDimitry Andric #include "lldb/Target/Target.h" 320b57cec5SDimitry Andric #include "lldb/Target/ThreadPlan.h" 330b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanBase.h" 340b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanCallFunction.h" 350b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanPython.h" 360b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanRunToAddress.h" 375ffd83dbSDimitry Andric #include "lldb/Target/ThreadPlanStack.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/ThreadPlanStepOverBreakpoint.h" 420b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepOverRange.h" 430b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepThrough.h" 440b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepUntil.h" 450b57cec5SDimitry Andric #include "lldb/Target/ThreadSpec.h" 465ffd83dbSDimitry Andric #include "lldb/Target/UnwindLLDB.h" 4781ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 480b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 490b57cec5SDimitry Andric #include "lldb/Utility/RegularExpression.h" 500b57cec5SDimitry Andric #include "lldb/Utility/State.h" 510b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 520b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 530b57cec5SDimitry Andric #include "lldb/lldb-enumerations.h" 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric #include <memory> 56bdd1243dSDimitry Andric #include <optional> 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric using namespace lldb; 590b57cec5SDimitry Andric using namespace lldb_private; 600b57cec5SDimitry Andric 61349cc55cSDimitry Andric ThreadProperties &Thread::GetGlobalProperties() { 620b57cec5SDimitry Andric // NOTE: intentional leak so we don't crash if global destructor chain gets 630b57cec5SDimitry Andric // called as other threads still use the result of this function 64349cc55cSDimitry Andric static ThreadProperties *g_settings_ptr = new ThreadProperties(true); 65349cc55cSDimitry Andric return *g_settings_ptr; 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric 689dba64beSDimitry Andric #define LLDB_PROPERTIES_thread 699dba64beSDimitry Andric #include "TargetProperties.inc" 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric enum { 729dba64beSDimitry Andric #define LLDB_PROPERTIES_thread 739dba64beSDimitry Andric #include "TargetPropertiesEnum.inc" 740b57cec5SDimitry Andric }; 750b57cec5SDimitry Andric 76fe6060f1SDimitry Andric class ThreadOptionValueProperties 77fe6060f1SDimitry Andric : public Cloneable<ThreadOptionValueProperties, OptionValueProperties> { 780b57cec5SDimitry Andric public: 795f757f3fSDimitry Andric ThreadOptionValueProperties(llvm::StringRef name) : Cloneable(name) {} 800b57cec5SDimitry Andric 8106c3fb27SDimitry Andric const Property * 8206c3fb27SDimitry Andric GetPropertyAtIndex(size_t idx, 8306c3fb27SDimitry Andric const ExecutionContext *exe_ctx) const override { 840b57cec5SDimitry Andric // When getting the value for a key from the thread options, we will always 850b57cec5SDimitry Andric // try and grab the setting from the current thread if there is one. Else 860b57cec5SDimitry Andric // we just use the one from this instance. 870b57cec5SDimitry Andric if (exe_ctx) { 880b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr(); 890b57cec5SDimitry Andric if (thread) { 900b57cec5SDimitry Andric ThreadOptionValueProperties *instance_properties = 910b57cec5SDimitry Andric static_cast<ThreadOptionValueProperties *>( 920b57cec5SDimitry Andric thread->GetValueProperties().get()); 930b57cec5SDimitry Andric if (this != instance_properties) 940b57cec5SDimitry Andric return instance_properties->ProtectedGetPropertyAtIndex(idx); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric return ProtectedGetPropertyAtIndex(idx); 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric }; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric ThreadProperties::ThreadProperties(bool is_global) : Properties() { 1020b57cec5SDimitry Andric if (is_global) { 1035f757f3fSDimitry Andric m_collection_sp = std::make_shared<ThreadOptionValueProperties>("thread"); 1049dba64beSDimitry Andric m_collection_sp->Initialize(g_thread_properties); 1050b57cec5SDimitry Andric } else 106fe6060f1SDimitry Andric m_collection_sp = 107349cc55cSDimitry Andric OptionValueProperties::CreateLocalCopy(Thread::GetGlobalProperties()); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric ThreadProperties::~ThreadProperties() = default; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric const RegularExpression *ThreadProperties::GetSymbolsToAvoidRegexp() { 1130b57cec5SDimitry Andric const uint32_t idx = ePropertyStepAvoidRegex; 11406c3fb27SDimitry Andric return GetPropertyAtIndexAs<const RegularExpression *>(idx); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric FileSpecList ThreadProperties::GetLibrariesToAvoid() const { 1180b57cec5SDimitry Andric const uint32_t idx = ePropertyStepAvoidLibraries; 11906c3fb27SDimitry Andric return GetPropertyAtIndexAs<FileSpecList>(idx, {}); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric bool ThreadProperties::GetTraceEnabledState() const { 1230b57cec5SDimitry Andric const uint32_t idx = ePropertyEnableThreadTrace; 12406c3fb27SDimitry Andric return GetPropertyAtIndexAs<bool>( 12506c3fb27SDimitry Andric idx, g_thread_properties[idx].default_uint_value != 0); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric bool ThreadProperties::GetStepInAvoidsNoDebug() const { 1290b57cec5SDimitry Andric const uint32_t idx = ePropertyStepInAvoidsNoDebug; 13006c3fb27SDimitry Andric return GetPropertyAtIndexAs<bool>( 13106c3fb27SDimitry Andric idx, g_thread_properties[idx].default_uint_value != 0); 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric bool ThreadProperties::GetStepOutAvoidsNoDebug() const { 1350b57cec5SDimitry Andric const uint32_t idx = ePropertyStepOutAvoidsNoDebug; 13606c3fb27SDimitry Andric return GetPropertyAtIndexAs<bool>( 13706c3fb27SDimitry Andric idx, g_thread_properties[idx].default_uint_value != 0); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric uint64_t ThreadProperties::GetMaxBacktraceDepth() const { 1410b57cec5SDimitry Andric const uint32_t idx = ePropertyMaxBacktraceDepth; 14206c3fb27SDimitry Andric return GetPropertyAtIndexAs<uint64_t>( 14306c3fb27SDimitry Andric idx, g_thread_properties[idx].default_uint_value); 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric // Thread Event Data 1470b57cec5SDimitry Andric 14806c3fb27SDimitry Andric llvm::StringRef Thread::ThreadEventData::GetFlavorString() { 14906c3fb27SDimitry Andric return "Thread::ThreadEventData"; 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric Thread::ThreadEventData::ThreadEventData(const lldb::ThreadSP thread_sp) 1530b57cec5SDimitry Andric : m_thread_sp(thread_sp), m_stack_id() {} 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric Thread::ThreadEventData::ThreadEventData(const lldb::ThreadSP thread_sp, 1560b57cec5SDimitry Andric const StackID &stack_id) 1570b57cec5SDimitry Andric : m_thread_sp(thread_sp), m_stack_id(stack_id) {} 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric Thread::ThreadEventData::ThreadEventData() : m_thread_sp(), m_stack_id() {} 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric Thread::ThreadEventData::~ThreadEventData() = default; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric void Thread::ThreadEventData::Dump(Stream *s) const {} 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric const Thread::ThreadEventData * 1660b57cec5SDimitry Andric Thread::ThreadEventData::GetEventDataFromEvent(const Event *event_ptr) { 1670b57cec5SDimitry Andric if (event_ptr) { 1680b57cec5SDimitry Andric const EventData *event_data = event_ptr->GetData(); 1690b57cec5SDimitry Andric if (event_data && 1700b57cec5SDimitry Andric event_data->GetFlavor() == ThreadEventData::GetFlavorString()) 1710b57cec5SDimitry Andric return static_cast<const ThreadEventData *>(event_ptr->GetData()); 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric return nullptr; 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric ThreadSP Thread::ThreadEventData::GetThreadFromEvent(const Event *event_ptr) { 1770b57cec5SDimitry Andric ThreadSP thread_sp; 1780b57cec5SDimitry Andric const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr); 1790b57cec5SDimitry Andric if (event_data) 1800b57cec5SDimitry Andric thread_sp = event_data->GetThread(); 1810b57cec5SDimitry Andric return thread_sp; 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric StackID Thread::ThreadEventData::GetStackIDFromEvent(const Event *event_ptr) { 1850b57cec5SDimitry Andric StackID stack_id; 1860b57cec5SDimitry Andric const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr); 1870b57cec5SDimitry Andric if (event_data) 1880b57cec5SDimitry Andric stack_id = event_data->GetStackID(); 1890b57cec5SDimitry Andric return stack_id; 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric StackFrameSP 1930b57cec5SDimitry Andric Thread::ThreadEventData::GetStackFrameFromEvent(const Event *event_ptr) { 1940b57cec5SDimitry Andric const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr); 1950b57cec5SDimitry Andric StackFrameSP frame_sp; 1960b57cec5SDimitry Andric if (event_data) { 1970b57cec5SDimitry Andric ThreadSP thread_sp = event_data->GetThread(); 1980b57cec5SDimitry Andric if (thread_sp) { 1990b57cec5SDimitry Andric frame_sp = thread_sp->GetStackFrameList()->GetFrameWithStackID( 2000b57cec5SDimitry Andric event_data->GetStackID()); 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric return frame_sp; 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric // Thread class 2070b57cec5SDimitry Andric 208*0fca6ea1SDimitry Andric llvm::StringRef Thread::GetStaticBroadcasterClass() { 209*0fca6ea1SDimitry Andric static constexpr llvm::StringLiteral class_name("lldb.thread"); 2100b57cec5SDimitry Andric return class_name; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric Thread::Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id) 2140b57cec5SDimitry Andric : ThreadProperties(false), UserID(tid), 2150b57cec5SDimitry Andric Broadcaster(process.GetTarget().GetDebugger().GetBroadcasterManager(), 216*0fca6ea1SDimitry Andric Thread::GetStaticBroadcasterClass().str()), 2170b57cec5SDimitry Andric m_process_wp(process.shared_from_this()), m_stop_info_sp(), 2180b57cec5SDimitry Andric m_stop_info_stop_id(0), m_stop_info_override_stop_id(0), 219bdd1243dSDimitry Andric m_should_run_before_public_stop(false), 2200b57cec5SDimitry Andric m_index_id(use_invalid_index_id ? LLDB_INVALID_INDEX32 2210b57cec5SDimitry Andric : process.GetNextThreadIndexID(tid)), 2220b57cec5SDimitry Andric m_reg_context_sp(), m_state(eStateUnloaded), m_state_mutex(), 2235ffd83dbSDimitry Andric m_frame_mutex(), m_curr_frames_sp(), m_prev_frames_sp(), 224*0fca6ea1SDimitry Andric m_prev_framezero_pc(), m_resume_signal(LLDB_INVALID_SIGNAL_NUMBER), 2250b57cec5SDimitry Andric m_resume_state(eStateRunning), m_temporary_resume_state(eStateRunning), 2260b57cec5SDimitry Andric m_unwinder_up(), m_destroy_called(false), 2270b57cec5SDimitry Andric m_override_should_notify(eLazyBoolCalculate), 2280b57cec5SDimitry Andric m_extended_info_fetched(false), m_extended_info() { 22981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Object); 2309dba64beSDimitry Andric LLDB_LOGF(log, "%p Thread::Thread(tid = 0x%4.4" PRIx64 ")", 2310b57cec5SDimitry Andric static_cast<void *>(this), GetID()); 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric CheckInWithManager(); 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric Thread::~Thread() { 23781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Object); 2389dba64beSDimitry Andric LLDB_LOGF(log, "%p Thread::~Thread(tid = 0x%4.4" PRIx64 ")", 2390b57cec5SDimitry Andric static_cast<void *>(this), GetID()); 2400b57cec5SDimitry Andric /// If you hit this assert, it means your derived class forgot to call 2410b57cec5SDimitry Andric /// DoDestroy in its destructor. 2420b57cec5SDimitry Andric assert(m_destroy_called); 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric void Thread::DestroyThread() { 2460b57cec5SDimitry Andric m_destroy_called = true; 2470b57cec5SDimitry Andric m_stop_info_sp.reset(); 2480b57cec5SDimitry Andric m_reg_context_sp.reset(); 2490b57cec5SDimitry Andric m_unwinder_up.reset(); 2500b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_frame_mutex); 2510b57cec5SDimitry Andric m_curr_frames_sp.reset(); 2520b57cec5SDimitry Andric m_prev_frames_sp.reset(); 253*0fca6ea1SDimitry Andric m_prev_framezero_pc.reset(); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric void Thread::BroadcastSelectedFrameChange(StackID &new_frame_id) { 2577a6dacacSDimitry Andric if (EventTypeHasListeners(eBroadcastBitSelectedFrameChanged)) { 2587a6dacacSDimitry Andric auto data_sp = 2597a6dacacSDimitry Andric std::make_shared<ThreadEventData>(shared_from_this(), new_frame_id); 2607a6dacacSDimitry Andric BroadcastEvent(eBroadcastBitSelectedFrameChanged, data_sp); 2617a6dacacSDimitry Andric } 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric 26406c3fb27SDimitry Andric lldb::StackFrameSP 26506c3fb27SDimitry Andric Thread::GetSelectedFrame(SelectMostRelevant select_most_relevant) { 2660b57cec5SDimitry Andric StackFrameListSP stack_frame_list_sp(GetStackFrameList()); 2670b57cec5SDimitry Andric StackFrameSP frame_sp = stack_frame_list_sp->GetFrameAtIndex( 26806c3fb27SDimitry Andric stack_frame_list_sp->GetSelectedFrameIndex(select_most_relevant)); 2695ffd83dbSDimitry Andric FrameSelectedCallback(frame_sp.get()); 2700b57cec5SDimitry Andric return frame_sp; 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric uint32_t Thread::SetSelectedFrame(lldb_private::StackFrame *frame, 2740b57cec5SDimitry Andric bool broadcast) { 2750b57cec5SDimitry Andric uint32_t ret_value = GetStackFrameList()->SetSelectedFrame(frame); 2760b57cec5SDimitry Andric if (broadcast) 2770b57cec5SDimitry Andric BroadcastSelectedFrameChange(frame->GetStackID()); 2785ffd83dbSDimitry Andric FrameSelectedCallback(frame); 2790b57cec5SDimitry Andric return ret_value; 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric bool Thread::SetSelectedFrameByIndex(uint32_t frame_idx, bool broadcast) { 2830b57cec5SDimitry Andric StackFrameSP frame_sp(GetStackFrameList()->GetFrameAtIndex(frame_idx)); 2840b57cec5SDimitry Andric if (frame_sp) { 2850b57cec5SDimitry Andric GetStackFrameList()->SetSelectedFrame(frame_sp.get()); 2860b57cec5SDimitry Andric if (broadcast) 2870b57cec5SDimitry Andric BroadcastSelectedFrameChange(frame_sp->GetStackID()); 2885ffd83dbSDimitry Andric FrameSelectedCallback(frame_sp.get()); 2890b57cec5SDimitry Andric return true; 2900b57cec5SDimitry Andric } else 2910b57cec5SDimitry Andric return false; 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric bool Thread::SetSelectedFrameByIndexNoisily(uint32_t frame_idx, 2950b57cec5SDimitry Andric Stream &output_stream) { 2960b57cec5SDimitry Andric const bool broadcast = true; 2970b57cec5SDimitry Andric bool success = SetSelectedFrameByIndex(frame_idx, broadcast); 2980b57cec5SDimitry Andric if (success) { 29906c3fb27SDimitry Andric StackFrameSP frame_sp = GetSelectedFrame(DoNoSelectMostRelevantFrame); 3000b57cec5SDimitry Andric if (frame_sp) { 3010b57cec5SDimitry Andric bool already_shown = false; 3020b57cec5SDimitry Andric SymbolContext frame_sc( 3030b57cec5SDimitry Andric frame_sp->GetSymbolContext(eSymbolContextLineEntry)); 30406c3fb27SDimitry Andric const Debugger &debugger = GetProcess()->GetTarget().GetDebugger(); 305*0fca6ea1SDimitry Andric if (debugger.GetUseExternalEditor() && frame_sc.line_entry.GetFile() && 30606c3fb27SDimitry Andric frame_sc.line_entry.line != 0) { 30706c3fb27SDimitry Andric if (llvm::Error e = Host::OpenFileInExternalEditor( 308*0fca6ea1SDimitry Andric debugger.GetExternalEditor(), frame_sc.line_entry.GetFile(), 30906c3fb27SDimitry Andric frame_sc.line_entry.line)) { 31006c3fb27SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e), 31106c3fb27SDimitry Andric "OpenFileInExternalEditor failed: {0}"); 31206c3fb27SDimitry Andric } else { 31306c3fb27SDimitry Andric already_shown = true; 31406c3fb27SDimitry Andric } 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric bool show_frame_info = true; 3180b57cec5SDimitry Andric bool show_source = !already_shown; 3195ffd83dbSDimitry Andric FrameSelectedCallback(frame_sp.get()); 3200b57cec5SDimitry Andric return frame_sp->GetStatus(output_stream, show_frame_info, show_source); 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric return false; 3230b57cec5SDimitry Andric } else 3240b57cec5SDimitry Andric return false; 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 3275ffd83dbSDimitry Andric void Thread::FrameSelectedCallback(StackFrame *frame) { 3285ffd83dbSDimitry Andric if (!frame) 3295ffd83dbSDimitry Andric return; 3305ffd83dbSDimitry Andric 3315ffd83dbSDimitry Andric if (frame->HasDebugInformation() && 3325ffd83dbSDimitry Andric (GetProcess()->GetWarningsOptimization() || 3335ffd83dbSDimitry Andric GetProcess()->GetWarningsUnsupportedLanguage())) { 3340b57cec5SDimitry Andric SymbolContext sc = 3350b57cec5SDimitry Andric frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextModule); 3360b57cec5SDimitry Andric GetProcess()->PrintWarningOptimization(sc); 3375ffd83dbSDimitry Andric GetProcess()->PrintWarningUnsupportedLanguage(sc); 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric lldb::StopInfoSP Thread::GetStopInfo() { 3420b57cec5SDimitry Andric if (m_destroy_called) 3430b57cec5SDimitry Andric return m_stop_info_sp; 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric ThreadPlanSP completed_plan_sp(GetCompletedPlan()); 3460b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 3470b57cec5SDimitry Andric const uint32_t stop_id = process_sp ? process_sp->GetStopID() : UINT32_MAX; 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric // Here we select the stop info according to priorirty: - m_stop_info_sp (if 3500b57cec5SDimitry Andric // not trace) - preset value - completed plan stop info - new value with plan 3510b57cec5SDimitry Andric // from completed plan stack - m_stop_info_sp (trace stop reason is OK now) - 3520b57cec5SDimitry Andric // ask GetPrivateStopInfo to set stop info 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric bool have_valid_stop_info = m_stop_info_sp && 3550b57cec5SDimitry Andric m_stop_info_sp ->IsValid() && 3560b57cec5SDimitry Andric m_stop_info_stop_id == stop_id; 3570b57cec5SDimitry Andric bool have_valid_completed_plan = completed_plan_sp && completed_plan_sp->PlanSucceeded(); 3580b57cec5SDimitry Andric bool plan_failed = completed_plan_sp && !completed_plan_sp->PlanSucceeded(); 3590b57cec5SDimitry Andric bool plan_overrides_trace = 3600b57cec5SDimitry Andric have_valid_stop_info && have_valid_completed_plan 3610b57cec5SDimitry Andric && (m_stop_info_sp->GetStopReason() == eStopReasonTrace); 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric if (have_valid_stop_info && !plan_overrides_trace && !plan_failed) { 3640b57cec5SDimitry Andric return m_stop_info_sp; 3650b57cec5SDimitry Andric } else if (completed_plan_sp) { 3660b57cec5SDimitry Andric return StopInfo::CreateStopReasonWithPlan( 3670b57cec5SDimitry Andric completed_plan_sp, GetReturnValueObject(), GetExpressionVariable()); 3680b57cec5SDimitry Andric } else { 3690b57cec5SDimitry Andric GetPrivateStopInfo(); 3700b57cec5SDimitry Andric return m_stop_info_sp; 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 3749dba64beSDimitry Andric void Thread::CalculatePublicStopInfo() { 3759dba64beSDimitry Andric ResetStopInfo(); 3769dba64beSDimitry Andric SetStopInfo(GetStopInfo()); 3779dba64beSDimitry Andric } 3789dba64beSDimitry Andric 379bdd1243dSDimitry Andric lldb::StopInfoSP Thread::GetPrivateStopInfo(bool calculate) { 380bdd1243dSDimitry Andric if (!calculate) 381bdd1243dSDimitry Andric return m_stop_info_sp; 382bdd1243dSDimitry Andric 3830b57cec5SDimitry Andric if (m_destroy_called) 3840b57cec5SDimitry Andric return m_stop_info_sp; 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 3870b57cec5SDimitry Andric if (process_sp) { 3880b57cec5SDimitry Andric const uint32_t process_stop_id = process_sp->GetStopID(); 3890b57cec5SDimitry Andric if (m_stop_info_stop_id != process_stop_id) { 390bdd1243dSDimitry Andric // We preserve the old stop info for a variety of reasons: 391bdd1243dSDimitry Andric // 1) Someone has already updated it by the time we get here 392bdd1243dSDimitry Andric // 2) We didn't get to execute the breakpoint instruction we stopped at 393bdd1243dSDimitry Andric // 3) This is a virtual step so we didn't actually run 394bdd1243dSDimitry Andric // 4) If this thread wasn't allowed to run the last time round. 3950b57cec5SDimitry Andric if (m_stop_info_sp) { 3960b57cec5SDimitry Andric if (m_stop_info_sp->IsValid() || IsStillAtLastBreakpointHit() || 397bdd1243dSDimitry Andric GetCurrentPlan()->IsVirtualStep() 398bdd1243dSDimitry Andric || GetTemporaryResumeState() == eStateSuspended) 3990b57cec5SDimitry Andric SetStopInfo(m_stop_info_sp); 4000b57cec5SDimitry Andric else 4010b57cec5SDimitry Andric m_stop_info_sp.reset(); 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric if (!m_stop_info_sp) { 4050b57cec5SDimitry Andric if (!CalculateStopInfo()) 4060b57cec5SDimitry Andric SetStopInfo(StopInfoSP()); 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric // The stop info can be manually set by calling Thread::SetStopInfo() prior 4110b57cec5SDimitry Andric // to this function ever getting called, so we can't rely on 4120b57cec5SDimitry Andric // "m_stop_info_stop_id != process_stop_id" as the condition for the if 4130b57cec5SDimitry Andric // statement below, we must also check the stop info to see if we need to 4140b57cec5SDimitry Andric // override it. See the header documentation in 4155ffd83dbSDimitry Andric // Architecture::OverrideStopInfo() for more information on the stop 4160b57cec5SDimitry Andric // info override callback. 4170b57cec5SDimitry Andric if (m_stop_info_override_stop_id != process_stop_id) { 4180b57cec5SDimitry Andric m_stop_info_override_stop_id = process_stop_id; 4190b57cec5SDimitry Andric if (m_stop_info_sp) { 4200b57cec5SDimitry Andric if (const Architecture *arch = 4210b57cec5SDimitry Andric process_sp->GetTarget().GetArchitecturePlugin()) 4220b57cec5SDimitry Andric arch->OverrideStopInfo(*this); 4230b57cec5SDimitry Andric } 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric } 426*0fca6ea1SDimitry Andric 427*0fca6ea1SDimitry Andric // If we were resuming the process and it was interrupted, 428*0fca6ea1SDimitry Andric // return no stop reason. This thread would like to resume. 429*0fca6ea1SDimitry Andric if (m_stop_info_sp && m_stop_info_sp->WasContinueInterrupted(*this)) 430*0fca6ea1SDimitry Andric return {}; 431*0fca6ea1SDimitry Andric 4320b57cec5SDimitry Andric return m_stop_info_sp; 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric lldb::StopReason Thread::GetStopReason() { 4360b57cec5SDimitry Andric lldb::StopInfoSP stop_info_sp(GetStopInfo()); 4370b57cec5SDimitry Andric if (stop_info_sp) 4380b57cec5SDimitry Andric return stop_info_sp->GetStopReason(); 4390b57cec5SDimitry Andric return eStopReasonNone; 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric bool Thread::StopInfoIsUpToDate() const { 4430b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 4440b57cec5SDimitry Andric if (process_sp) 4450b57cec5SDimitry Andric return m_stop_info_stop_id == process_sp->GetStopID(); 4460b57cec5SDimitry Andric else 4470b57cec5SDimitry Andric return true; // Process is no longer around so stop info is always up to 4480b57cec5SDimitry Andric // date... 4490b57cec5SDimitry Andric } 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric void Thread::ResetStopInfo() { 4520b57cec5SDimitry Andric if (m_stop_info_sp) { 4530b57cec5SDimitry Andric m_stop_info_sp.reset(); 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric void Thread::SetStopInfo(const lldb::StopInfoSP &stop_info_sp) { 4580b57cec5SDimitry Andric m_stop_info_sp = stop_info_sp; 4590b57cec5SDimitry Andric if (m_stop_info_sp) { 4600b57cec5SDimitry Andric m_stop_info_sp->MakeStopInfoValid(); 4610b57cec5SDimitry Andric // If we are overriding the ShouldReportStop, do that here: 4620b57cec5SDimitry Andric if (m_override_should_notify != eLazyBoolCalculate) 4630b57cec5SDimitry Andric m_stop_info_sp->OverrideShouldNotify(m_override_should_notify == 4640b57cec5SDimitry Andric eLazyBoolYes); 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 4680b57cec5SDimitry Andric if (process_sp) 4690b57cec5SDimitry Andric m_stop_info_stop_id = process_sp->GetStopID(); 4700b57cec5SDimitry Andric else 4710b57cec5SDimitry Andric m_stop_info_stop_id = UINT32_MAX; 47281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 4739dba64beSDimitry Andric LLDB_LOGF(log, "%p: tid = 0x%" PRIx64 ": stop info = %s (stop_id = %u)", 4740b57cec5SDimitry Andric static_cast<void *>(this), GetID(), 4750b57cec5SDimitry Andric stop_info_sp ? stop_info_sp->GetDescription() : "<NULL>", 4760b57cec5SDimitry Andric m_stop_info_stop_id); 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric void Thread::SetShouldReportStop(Vote vote) { 4800b57cec5SDimitry Andric if (vote == eVoteNoOpinion) 4810b57cec5SDimitry Andric return; 4820b57cec5SDimitry Andric else { 4830b57cec5SDimitry Andric m_override_should_notify = (vote == eVoteYes ? eLazyBoolYes : eLazyBoolNo); 4840b57cec5SDimitry Andric if (m_stop_info_sp) 4850b57cec5SDimitry Andric m_stop_info_sp->OverrideShouldNotify(m_override_should_notify == 4860b57cec5SDimitry Andric eLazyBoolYes); 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric void Thread::SetStopInfoToNothing() { 4910b57cec5SDimitry Andric // Note, we can't just NULL out the private reason, or the native thread 4920b57cec5SDimitry Andric // implementation will try to go calculate it again. For now, just set it to 4930b57cec5SDimitry Andric // a Unix Signal with an invalid signal number. 4940b57cec5SDimitry Andric SetStopInfo( 4950b57cec5SDimitry Andric StopInfo::CreateStopReasonWithSignal(*this, LLDB_INVALID_SIGNAL_NUMBER)); 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 49804eeddc0SDimitry Andric bool Thread::ThreadStoppedForAReason() { return (bool)GetPrivateStopInfo(); } 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric bool Thread::CheckpointThreadState(ThreadStateCheckpoint &saved_state) { 5010b57cec5SDimitry Andric saved_state.register_backup_sp.reset(); 5020b57cec5SDimitry Andric lldb::StackFrameSP frame_sp(GetStackFrameAtIndex(0)); 5030b57cec5SDimitry Andric if (frame_sp) { 5040b57cec5SDimitry Andric lldb::RegisterCheckpointSP reg_checkpoint_sp( 5050b57cec5SDimitry Andric new RegisterCheckpoint(RegisterCheckpoint::Reason::eExpression)); 5060b57cec5SDimitry Andric if (reg_checkpoint_sp) { 5070b57cec5SDimitry Andric lldb::RegisterContextSP reg_ctx_sp(frame_sp->GetRegisterContext()); 5080b57cec5SDimitry Andric if (reg_ctx_sp && reg_ctx_sp->ReadAllRegisterValues(*reg_checkpoint_sp)) 5090b57cec5SDimitry Andric saved_state.register_backup_sp = reg_checkpoint_sp; 5100b57cec5SDimitry Andric } 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric if (!saved_state.register_backup_sp) 5130b57cec5SDimitry Andric return false; 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric saved_state.stop_info_sp = GetStopInfo(); 5160b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 5170b57cec5SDimitry Andric if (process_sp) 5180b57cec5SDimitry Andric saved_state.orig_stop_id = process_sp->GetStopID(); 5190b57cec5SDimitry Andric saved_state.current_inlined_depth = GetCurrentInlinedDepth(); 5205ffd83dbSDimitry Andric saved_state.m_completed_plan_checkpoint = 5215ffd83dbSDimitry Andric GetPlans().CheckpointCompletedPlans(); 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric return true; 5240b57cec5SDimitry Andric } 5250b57cec5SDimitry Andric 5260b57cec5SDimitry Andric bool Thread::RestoreRegisterStateFromCheckpoint( 5270b57cec5SDimitry Andric ThreadStateCheckpoint &saved_state) { 5280b57cec5SDimitry Andric if (saved_state.register_backup_sp) { 5290b57cec5SDimitry Andric lldb::StackFrameSP frame_sp(GetStackFrameAtIndex(0)); 5300b57cec5SDimitry Andric if (frame_sp) { 5310b57cec5SDimitry Andric lldb::RegisterContextSP reg_ctx_sp(frame_sp->GetRegisterContext()); 5320b57cec5SDimitry Andric if (reg_ctx_sp) { 5330b57cec5SDimitry Andric bool ret = 5340b57cec5SDimitry Andric reg_ctx_sp->WriteAllRegisterValues(*saved_state.register_backup_sp); 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric // Clear out all stack frames as our world just changed. 5370b57cec5SDimitry Andric ClearStackFrames(); 5380b57cec5SDimitry Andric reg_ctx_sp->InvalidateIfNeeded(true); 5390b57cec5SDimitry Andric if (m_unwinder_up) 5400b57cec5SDimitry Andric m_unwinder_up->Clear(); 5410b57cec5SDimitry Andric return ret; 5420b57cec5SDimitry Andric } 5430b57cec5SDimitry Andric } 5440b57cec5SDimitry Andric } 5450b57cec5SDimitry Andric return false; 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric 548fe6060f1SDimitry Andric void Thread::RestoreThreadStateFromCheckpoint( 5490b57cec5SDimitry Andric ThreadStateCheckpoint &saved_state) { 5500b57cec5SDimitry Andric if (saved_state.stop_info_sp) 5510b57cec5SDimitry Andric saved_state.stop_info_sp->MakeStopInfoValid(); 5520b57cec5SDimitry Andric SetStopInfo(saved_state.stop_info_sp); 5530b57cec5SDimitry Andric GetStackFrameList()->SetCurrentInlinedDepth( 5540b57cec5SDimitry Andric saved_state.current_inlined_depth); 5555ffd83dbSDimitry Andric GetPlans().RestoreCompletedPlanCheckpoint( 5565ffd83dbSDimitry Andric saved_state.m_completed_plan_checkpoint); 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric StateType Thread::GetState() const { 5600b57cec5SDimitry Andric // If any other threads access this we will need a mutex for it 5610b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_state_mutex); 5620b57cec5SDimitry Andric return m_state; 5630b57cec5SDimitry Andric } 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric void Thread::SetState(StateType state) { 5660b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_state_mutex); 5670b57cec5SDimitry Andric m_state = state; 5680b57cec5SDimitry Andric } 5690b57cec5SDimitry Andric 5705ffd83dbSDimitry Andric std::string Thread::GetStopDescription() { 5715ffd83dbSDimitry Andric StackFrameSP frame_sp = GetStackFrameAtIndex(0); 5725ffd83dbSDimitry Andric 5735ffd83dbSDimitry Andric if (!frame_sp) 5745ffd83dbSDimitry Andric return GetStopDescriptionRaw(); 5755ffd83dbSDimitry Andric 5765ffd83dbSDimitry Andric auto recognized_frame_sp = frame_sp->GetRecognizedFrame(); 5775ffd83dbSDimitry Andric 5785ffd83dbSDimitry Andric if (!recognized_frame_sp) 5795ffd83dbSDimitry Andric return GetStopDescriptionRaw(); 5805ffd83dbSDimitry Andric 5815ffd83dbSDimitry Andric std::string recognized_stop_description = 5825ffd83dbSDimitry Andric recognized_frame_sp->GetStopDescription(); 5835ffd83dbSDimitry Andric 5845ffd83dbSDimitry Andric if (!recognized_stop_description.empty()) 5855ffd83dbSDimitry Andric return recognized_stop_description; 5865ffd83dbSDimitry Andric 5875ffd83dbSDimitry Andric return GetStopDescriptionRaw(); 5885ffd83dbSDimitry Andric } 5895ffd83dbSDimitry Andric 5905ffd83dbSDimitry Andric std::string Thread::GetStopDescriptionRaw() { 5915ffd83dbSDimitry Andric StopInfoSP stop_info_sp = GetStopInfo(); 5925ffd83dbSDimitry Andric std::string raw_stop_description; 5935ffd83dbSDimitry Andric if (stop_info_sp && stop_info_sp->IsValid()) { 5945ffd83dbSDimitry Andric raw_stop_description = stop_info_sp->GetDescription(); 5955ffd83dbSDimitry Andric assert((!raw_stop_description.empty() || 5965ffd83dbSDimitry Andric stop_info_sp->GetStopReason() == eStopReasonNone) && 5975ffd83dbSDimitry Andric "StopInfo returned an empty description."); 5985ffd83dbSDimitry Andric } 5995ffd83dbSDimitry Andric return raw_stop_description; 6005ffd83dbSDimitry Andric } 6015ffd83dbSDimitry Andric 6020b57cec5SDimitry Andric void Thread::WillStop() { 6030b57cec5SDimitry Andric ThreadPlan *current_plan = GetCurrentPlan(); 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric // FIXME: I may decide to disallow threads with no plans. In which 6060b57cec5SDimitry Andric // case this should go to an assert. 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric if (!current_plan) 6090b57cec5SDimitry Andric return; 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric current_plan->WillStop(); 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric void Thread::SetupForResume() { 6150b57cec5SDimitry Andric if (GetResumeState() != eStateSuspended) { 6160b57cec5SDimitry Andric // If we're at a breakpoint push the step-over breakpoint plan. Do this 6170b57cec5SDimitry Andric // before telling the current plan it will resume, since we might change 6180b57cec5SDimitry Andric // what the current plan is. 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext()); 6210b57cec5SDimitry Andric if (reg_ctx_sp) { 6220b57cec5SDimitry Andric const addr_t thread_pc = reg_ctx_sp->GetPC(); 6230b57cec5SDimitry Andric BreakpointSiteSP bp_site_sp = 6240b57cec5SDimitry Andric GetProcess()->GetBreakpointSiteList().FindByAddress(thread_pc); 6250b57cec5SDimitry Andric if (bp_site_sp) { 6260b57cec5SDimitry Andric // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the 6270b57cec5SDimitry Andric // target may not require anything special to step over a breakpoint. 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric ThreadPlan *cur_plan = GetCurrentPlan(); 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric bool push_step_over_bp_plan = false; 6320b57cec5SDimitry Andric if (cur_plan->GetKind() == ThreadPlan::eKindStepOverBreakpoint) { 6330b57cec5SDimitry Andric ThreadPlanStepOverBreakpoint *bp_plan = 6340b57cec5SDimitry Andric (ThreadPlanStepOverBreakpoint *)cur_plan; 6350b57cec5SDimitry Andric if (bp_plan->GetBreakpointLoadAddress() != thread_pc) 6360b57cec5SDimitry Andric push_step_over_bp_plan = true; 6370b57cec5SDimitry Andric } else 6380b57cec5SDimitry Andric push_step_over_bp_plan = true; 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric if (push_step_over_bp_plan) { 6410b57cec5SDimitry Andric ThreadPlanSP step_bp_plan_sp(new ThreadPlanStepOverBreakpoint(*this)); 6420b57cec5SDimitry Andric if (step_bp_plan_sp) { 6430b57cec5SDimitry Andric step_bp_plan_sp->SetPrivate(true); 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric if (GetCurrentPlan()->RunState() != eStateStepping) { 6460b57cec5SDimitry Andric ThreadPlanStepOverBreakpoint *step_bp_plan = 6470b57cec5SDimitry Andric static_cast<ThreadPlanStepOverBreakpoint *>( 6480b57cec5SDimitry Andric step_bp_plan_sp.get()); 6490b57cec5SDimitry Andric step_bp_plan->SetAutoContinue(true); 6500b57cec5SDimitry Andric } 6510b57cec5SDimitry Andric QueueThreadPlan(step_bp_plan_sp, false); 6520b57cec5SDimitry Andric } 6530b57cec5SDimitry Andric } 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric } 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric bool Thread::ShouldResume(StateType resume_state) { 6600b57cec5SDimitry Andric // At this point clear the completed plan stack. 6615ffd83dbSDimitry Andric GetPlans().WillResume(); 6620b57cec5SDimitry Andric m_override_should_notify = eLazyBoolCalculate; 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric StateType prev_resume_state = GetTemporaryResumeState(); 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric SetTemporaryResumeState(resume_state); 6670b57cec5SDimitry Andric 6680b57cec5SDimitry Andric lldb::ThreadSP backing_thread_sp(GetBackingThread()); 6690b57cec5SDimitry Andric if (backing_thread_sp) 6700b57cec5SDimitry Andric backing_thread_sp->SetTemporaryResumeState(resume_state); 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric // Make sure m_stop_info_sp is valid. Don't do this for threads we suspended 6730b57cec5SDimitry Andric // in the previous run. 6740b57cec5SDimitry Andric if (prev_resume_state != eStateSuspended) 6750b57cec5SDimitry Andric GetPrivateStopInfo(); 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric // This is a little dubious, but we are trying to limit how often we actually 6780b57cec5SDimitry Andric // fetch stop info from the target, 'cause that slows down single stepping. 6790b57cec5SDimitry Andric // So assume that if we got to the point where we're about to resume, and we 6800b57cec5SDimitry Andric // haven't yet had to fetch the stop reason, then it doesn't need to know 6810b57cec5SDimitry Andric // about the fact that we are resuming... 6820b57cec5SDimitry Andric const uint32_t process_stop_id = GetProcess()->GetStopID(); 6830b57cec5SDimitry Andric if (m_stop_info_stop_id == process_stop_id && 6840b57cec5SDimitry Andric (m_stop_info_sp && m_stop_info_sp->IsValid())) { 6850b57cec5SDimitry Andric StopInfo *stop_info = GetPrivateStopInfo().get(); 6860b57cec5SDimitry Andric if (stop_info) 6870b57cec5SDimitry Andric stop_info->WillResume(resume_state); 6880b57cec5SDimitry Andric } 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric // Tell all the plans that we are about to resume in case they need to clear 6910b57cec5SDimitry Andric // any state. We distinguish between the plan on the top of the stack and the 6920b57cec5SDimitry Andric // lower plans in case a plan needs to do any special business before it 6930b57cec5SDimitry Andric // runs. 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric bool need_to_resume = false; 6960b57cec5SDimitry Andric ThreadPlan *plan_ptr = GetCurrentPlan(); 6970b57cec5SDimitry Andric if (plan_ptr) { 6980b57cec5SDimitry Andric need_to_resume = plan_ptr->WillResume(resume_state, true); 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr) { 7010b57cec5SDimitry Andric plan_ptr->WillResume(resume_state, false); 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric // If the WillResume for the plan says we are faking a resume, then it will 7050b57cec5SDimitry Andric // have set an appropriate stop info. In that case, don't reset it here. 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric if (need_to_resume && resume_state != eStateSuspended) { 7080b57cec5SDimitry Andric m_stop_info_sp.reset(); 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric if (need_to_resume) { 7130b57cec5SDimitry Andric ClearStackFrames(); 7140b57cec5SDimitry Andric // Let Thread subclasses do any special work they need to prior to resuming 7150b57cec5SDimitry Andric WillResume(resume_state); 7160b57cec5SDimitry Andric } 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric return need_to_resume; 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 721bdd1243dSDimitry Andric void Thread::DidResume() { 722bdd1243dSDimitry Andric SetResumeSignal(LLDB_INVALID_SIGNAL_NUMBER); 723bdd1243dSDimitry Andric // This will get recomputed each time when we stop. 724bdd1243dSDimitry Andric SetShouldRunBeforePublicStop(false); 725bdd1243dSDimitry Andric } 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric void Thread::DidStop() { SetState(eStateStopped); } 7280b57cec5SDimitry Andric 7290b57cec5SDimitry Andric bool Thread::ShouldStop(Event *event_ptr) { 7300b57cec5SDimitry Andric ThreadPlan *current_plan = GetCurrentPlan(); 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric bool should_stop = true; 7330b57cec5SDimitry Andric 73481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric if (GetResumeState() == eStateSuspended) { 7379dba64beSDimitry Andric LLDB_LOGF(log, 7389dba64beSDimitry Andric "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 7390b57cec5SDimitry Andric ", should_stop = 0 (ignore since thread was suspended)", 7400b57cec5SDimitry Andric __FUNCTION__, GetID(), GetProtocolID()); 7410b57cec5SDimitry Andric return false; 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric if (GetTemporaryResumeState() == eStateSuspended) { 7459dba64beSDimitry Andric LLDB_LOGF(log, 7469dba64beSDimitry Andric "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 7470b57cec5SDimitry Andric ", should_stop = 0 (ignore since thread was suspended)", 7480b57cec5SDimitry Andric __FUNCTION__, GetID(), GetProtocolID()); 7490b57cec5SDimitry Andric return false; 7500b57cec5SDimitry Andric } 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric // Based on the current thread plan and process stop info, check if this 7530b57cec5SDimitry Andric // thread caused the process to stop. NOTE: this must take place before the 7540b57cec5SDimitry Andric // plan is moved from the current plan stack to the completed plan stack. 7550b57cec5SDimitry Andric if (!ThreadStoppedForAReason()) { 7569dba64beSDimitry Andric LLDB_LOGF(log, 7579dba64beSDimitry Andric "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 7580b57cec5SDimitry Andric ", pc = 0x%16.16" PRIx64 7590b57cec5SDimitry Andric ", should_stop = 0 (ignore since no stop reason)", 7600b57cec5SDimitry Andric __FUNCTION__, GetID(), GetProtocolID(), 7610b57cec5SDimitry Andric GetRegisterContext() ? GetRegisterContext()->GetPC() 7620b57cec5SDimitry Andric : LLDB_INVALID_ADDRESS); 7630b57cec5SDimitry Andric return false; 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric 766bdd1243dSDimitry Andric // Clear the "must run me before stop" if it was set: 767bdd1243dSDimitry Andric SetShouldRunBeforePublicStop(false); 768bdd1243dSDimitry Andric 7690b57cec5SDimitry Andric if (log) { 7709dba64beSDimitry Andric LLDB_LOGF(log, 7719dba64beSDimitry Andric "Thread::%s(%p) for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 7720b57cec5SDimitry Andric ", pc = 0x%16.16" PRIx64, 7739dba64beSDimitry Andric __FUNCTION__, static_cast<void *>(this), GetID(), GetProtocolID(), 7740b57cec5SDimitry Andric GetRegisterContext() ? GetRegisterContext()->GetPC() 7750b57cec5SDimitry Andric : LLDB_INVALID_ADDRESS); 7769dba64beSDimitry Andric LLDB_LOGF(log, "^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^"); 7770b57cec5SDimitry Andric StreamString s; 7780b57cec5SDimitry Andric s.IndentMore(); 7795ffd83dbSDimitry Andric GetProcess()->DumpThreadPlansForTID( 7805ffd83dbSDimitry Andric s, GetID(), eDescriptionLevelVerbose, true /* internal */, 7815ffd83dbSDimitry Andric false /* condense_trivial */, true /* skip_unreported */); 7829dba64beSDimitry Andric LLDB_LOGF(log, "Plan stack initial state:\n%s", s.GetData()); 7830b57cec5SDimitry Andric } 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric // The top most plan always gets to do the trace log... 7860b57cec5SDimitry Andric current_plan->DoTraceLog(); 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric // First query the stop info's ShouldStopSynchronous. This handles 7890b57cec5SDimitry Andric // "synchronous" stop reasons, for example the breakpoint command on internal 7900b57cec5SDimitry Andric // breakpoints. If a synchronous stop reason says we should not stop, then 7910b57cec5SDimitry Andric // we don't have to do any more work on this stop. 7920b57cec5SDimitry Andric StopInfoSP private_stop_info(GetPrivateStopInfo()); 7930b57cec5SDimitry Andric if (private_stop_info && 7940b57cec5SDimitry Andric !private_stop_info->ShouldStopSynchronous(event_ptr)) { 7959dba64beSDimitry Andric LLDB_LOGF(log, "StopInfo::ShouldStop async callback says we should not " 7960b57cec5SDimitry Andric "stop, returning ShouldStop of false."); 7970b57cec5SDimitry Andric return false; 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric // If we've already been restarted, don't query the plans since the state 8010b57cec5SDimitry Andric // they would examine is not current. 8020b57cec5SDimitry Andric if (Process::ProcessEventData::GetRestartedFromEvent(event_ptr)) 8030b57cec5SDimitry Andric return false; 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric // Before the plans see the state of the world, calculate the current inlined 8060b57cec5SDimitry Andric // depth. 8070b57cec5SDimitry Andric GetStackFrameList()->CalculateCurrentInlinedDepth(); 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric // If the base plan doesn't understand why we stopped, then we have to find a 8100b57cec5SDimitry Andric // plan that does. If that plan is still working, then we don't need to do 8110b57cec5SDimitry Andric // any more work. If the plan that explains the stop is done, then we should 8120b57cec5SDimitry Andric // pop all the plans below it, and pop it, and then let the plans above it 8130b57cec5SDimitry Andric // decide whether they still need to do more work. 8140b57cec5SDimitry Andric 8150b57cec5SDimitry Andric bool done_processing_current_plan = false; 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric if (!current_plan->PlanExplainsStop(event_ptr)) { 8180b57cec5SDimitry Andric if (current_plan->TracerExplainsStop()) { 8190b57cec5SDimitry Andric done_processing_current_plan = true; 8200b57cec5SDimitry Andric should_stop = false; 8210b57cec5SDimitry Andric } else { 8220b57cec5SDimitry Andric // If the current plan doesn't explain the stop, then find one that does 8230b57cec5SDimitry Andric // and let it handle the situation. 8240b57cec5SDimitry Andric ThreadPlan *plan_ptr = current_plan; 8250b57cec5SDimitry Andric while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr) { 8260b57cec5SDimitry Andric if (plan_ptr->PlanExplainsStop(event_ptr)) { 827fe6060f1SDimitry Andric LLDB_LOGF(log, "Plan %s explains stop.", plan_ptr->GetName()); 828fe6060f1SDimitry Andric 8290b57cec5SDimitry Andric should_stop = plan_ptr->ShouldStop(event_ptr); 8300b57cec5SDimitry Andric 8310b57cec5SDimitry Andric // plan_ptr explains the stop, next check whether plan_ptr is done, 8320b57cec5SDimitry Andric // if so, then we should take it and all the plans below it off the 8330b57cec5SDimitry Andric // stack. 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric if (plan_ptr->MischiefManaged()) { 8360b57cec5SDimitry Andric // We're going to pop the plans up to and including the plan that 8370b57cec5SDimitry Andric // explains the stop. 8380b57cec5SDimitry Andric ThreadPlan *prev_plan_ptr = GetPreviousPlan(plan_ptr); 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric do { 8410b57cec5SDimitry Andric if (should_stop) 8420b57cec5SDimitry Andric current_plan->WillStop(); 8430b57cec5SDimitry Andric PopPlan(); 8440b57cec5SDimitry Andric } while ((current_plan = GetCurrentPlan()) != prev_plan_ptr); 8450b57cec5SDimitry Andric // Now, if the responsible plan was not "Okay to discard" then 8460b57cec5SDimitry Andric // we're done, otherwise we forward this to the next plan in the 8470b57cec5SDimitry Andric // stack below. 8480b57cec5SDimitry Andric done_processing_current_plan = 849349cc55cSDimitry Andric (plan_ptr->IsControllingPlan() && !plan_ptr->OkayToDiscard()); 850bdd1243dSDimitry Andric } else { 851bdd1243dSDimitry Andric bool should_force_run = plan_ptr->ShouldRunBeforePublicStop(); 852bdd1243dSDimitry Andric if (should_force_run) { 853bdd1243dSDimitry Andric SetShouldRunBeforePublicStop(true); 854bdd1243dSDimitry Andric should_stop = false; 855bdd1243dSDimitry Andric } 8560b57cec5SDimitry Andric done_processing_current_plan = true; 857bdd1243dSDimitry Andric } 8580b57cec5SDimitry Andric break; 8590b57cec5SDimitry Andric } 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric } 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric if (!done_processing_current_plan) { 865fe6060f1SDimitry Andric bool override_stop = false; 8660b57cec5SDimitry Andric 8670b57cec5SDimitry Andric // We're starting from the base plan, so just let it decide; 8685ffd83dbSDimitry Andric if (current_plan->IsBasePlan()) { 8690b57cec5SDimitry Andric should_stop = current_plan->ShouldStop(event_ptr); 8709dba64beSDimitry Andric LLDB_LOGF(log, "Base plan says should stop: %i.", should_stop); 8710b57cec5SDimitry Andric } else { 8720b57cec5SDimitry Andric // Otherwise, don't let the base plan override what the other plans say 8730b57cec5SDimitry Andric // to do, since presumably if there were other plans they would know what 8740b57cec5SDimitry Andric // to do... 8750b57cec5SDimitry Andric while (true) { 8765ffd83dbSDimitry Andric if (current_plan->IsBasePlan()) 8770b57cec5SDimitry Andric break; 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric should_stop = current_plan->ShouldStop(event_ptr); 8809dba64beSDimitry Andric LLDB_LOGF(log, "Plan %s should stop: %d.", current_plan->GetName(), 8810b57cec5SDimitry Andric should_stop); 8820b57cec5SDimitry Andric if (current_plan->MischiefManaged()) { 8830b57cec5SDimitry Andric if (should_stop) 8840b57cec5SDimitry Andric current_plan->WillStop(); 8850b57cec5SDimitry Andric 886fe6060f1SDimitry Andric if (current_plan->ShouldAutoContinue(event_ptr)) { 887fe6060f1SDimitry Andric override_stop = true; 888fe6060f1SDimitry Andric LLDB_LOGF(log, "Plan %s auto-continue: true.", 889fe6060f1SDimitry Andric current_plan->GetName()); 890fe6060f1SDimitry Andric } 8910b57cec5SDimitry Andric 892349cc55cSDimitry Andric // If a Controlling Plan wants to stop, we let it. Otherwise, see if 893349cc55cSDimitry Andric // the plan's parent wants to stop. 894fe6060f1SDimitry Andric 895fe6060f1SDimitry Andric PopPlan(); 896349cc55cSDimitry Andric if (should_stop && current_plan->IsControllingPlan() && 8970b57cec5SDimitry Andric !current_plan->OkayToDiscard()) { 8980b57cec5SDimitry Andric break; 899fe6060f1SDimitry Andric } 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric current_plan = GetCurrentPlan(); 9020b57cec5SDimitry Andric if (current_plan == nullptr) { 9030b57cec5SDimitry Andric break; 9040b57cec5SDimitry Andric } 9050b57cec5SDimitry Andric } else { 9060b57cec5SDimitry Andric break; 9070b57cec5SDimitry Andric } 9080b57cec5SDimitry Andric } 9090b57cec5SDimitry Andric } 9100b57cec5SDimitry Andric 911fe6060f1SDimitry Andric if (override_stop) 9120b57cec5SDimitry Andric should_stop = false; 9130b57cec5SDimitry Andric } 9140b57cec5SDimitry Andric 915349cc55cSDimitry Andric // One other potential problem is that we set up a controlling plan, then stop 916349cc55cSDimitry Andric // in before it is complete - for instance by hitting a breakpoint during a 9170b57cec5SDimitry Andric // step-over - then do some step/finish/etc operations that wind up past the 9180b57cec5SDimitry Andric // end point condition of the initial plan. We don't want to strand the 9190b57cec5SDimitry Andric // original plan on the stack, This code clears stale plans off the stack. 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric if (should_stop) { 9220b57cec5SDimitry Andric ThreadPlan *plan_ptr = GetCurrentPlan(); 9230b57cec5SDimitry Andric 9240b57cec5SDimitry Andric // Discard the stale plans and all plans below them in the stack, plus move 9250b57cec5SDimitry Andric // the completed plans to the completed plan stack 9265ffd83dbSDimitry Andric while (!plan_ptr->IsBasePlan()) { 9270b57cec5SDimitry Andric bool stale = plan_ptr->IsPlanStale(); 9280b57cec5SDimitry Andric ThreadPlan *examined_plan = plan_ptr; 9290b57cec5SDimitry Andric plan_ptr = GetPreviousPlan(examined_plan); 9300b57cec5SDimitry Andric 9310b57cec5SDimitry Andric if (stale) { 9329dba64beSDimitry Andric LLDB_LOGF( 9339dba64beSDimitry Andric log, 9340b57cec5SDimitry Andric "Plan %s being discarded in cleanup, it says it is already done.", 9350b57cec5SDimitry Andric examined_plan->GetName()); 9360b57cec5SDimitry Andric while (GetCurrentPlan() != examined_plan) { 9370b57cec5SDimitry Andric DiscardPlan(); 9380b57cec5SDimitry Andric } 9390b57cec5SDimitry Andric if (examined_plan->IsPlanComplete()) { 9400b57cec5SDimitry Andric // plan is complete but does not explain the stop (example: step to a 9410b57cec5SDimitry Andric // line with breakpoint), let us move the plan to 9420b57cec5SDimitry Andric // completed_plan_stack anyway 9430b57cec5SDimitry Andric PopPlan(); 9440b57cec5SDimitry Andric } else 9450b57cec5SDimitry Andric DiscardPlan(); 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric } 9480b57cec5SDimitry Andric } 9490b57cec5SDimitry Andric 9500b57cec5SDimitry Andric if (log) { 9510b57cec5SDimitry Andric StreamString s; 9520b57cec5SDimitry Andric s.IndentMore(); 9535ffd83dbSDimitry Andric GetProcess()->DumpThreadPlansForTID( 9545ffd83dbSDimitry Andric s, GetID(), eDescriptionLevelVerbose, true /* internal */, 9555ffd83dbSDimitry Andric false /* condense_trivial */, true /* skip_unreported */); 9569dba64beSDimitry Andric LLDB_LOGF(log, "Plan stack final state:\n%s", s.GetData()); 9579dba64beSDimitry Andric LLDB_LOGF(log, "vvvvvvvv Thread::ShouldStop End (returning %i) vvvvvvvv", 9580b57cec5SDimitry Andric should_stop); 9590b57cec5SDimitry Andric } 9600b57cec5SDimitry Andric return should_stop; 9610b57cec5SDimitry Andric } 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric Vote Thread::ShouldReportStop(Event *event_ptr) { 9640b57cec5SDimitry Andric StateType thread_state = GetResumeState(); 9650b57cec5SDimitry Andric StateType temp_thread_state = GetTemporaryResumeState(); 9660b57cec5SDimitry Andric 96781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 9680b57cec5SDimitry Andric 9690b57cec5SDimitry Andric if (thread_state == eStateSuspended || thread_state == eStateInvalid) { 9709dba64beSDimitry Andric LLDB_LOGF(log, 9719dba64beSDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 9720b57cec5SDimitry Andric ": returning vote %i (state was suspended or invalid)", 9730b57cec5SDimitry Andric GetID(), eVoteNoOpinion); 9740b57cec5SDimitry Andric return eVoteNoOpinion; 9750b57cec5SDimitry Andric } 9760b57cec5SDimitry Andric 9770b57cec5SDimitry Andric if (temp_thread_state == eStateSuspended || 9780b57cec5SDimitry Andric temp_thread_state == eStateInvalid) { 9799dba64beSDimitry Andric LLDB_LOGF(log, 9800b57cec5SDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 9810b57cec5SDimitry Andric ": returning vote %i (temporary state was suspended or invalid)", 9820b57cec5SDimitry Andric GetID(), eVoteNoOpinion); 9830b57cec5SDimitry Andric return eVoteNoOpinion; 9840b57cec5SDimitry Andric } 9850b57cec5SDimitry Andric 9860b57cec5SDimitry Andric if (!ThreadStoppedForAReason()) { 9879dba64beSDimitry Andric LLDB_LOGF(log, 9889dba64beSDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 9890b57cec5SDimitry Andric ": returning vote %i (thread didn't stop for a reason.)", 9900b57cec5SDimitry Andric GetID(), eVoteNoOpinion); 9910b57cec5SDimitry Andric return eVoteNoOpinion; 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric 9945ffd83dbSDimitry Andric if (GetPlans().AnyCompletedPlans()) { 9955ffd83dbSDimitry Andric // Pass skip_private = false to GetCompletedPlan, since we want to ask 9965ffd83dbSDimitry Andric // the last plan, regardless of whether it is private or not. 9979dba64beSDimitry Andric LLDB_LOGF(log, 9989dba64beSDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 9990b57cec5SDimitry Andric ": returning vote for complete stack's back plan", 10000b57cec5SDimitry Andric GetID()); 10015ffd83dbSDimitry Andric return GetPlans().GetCompletedPlan(false)->ShouldReportStop(event_ptr); 10020b57cec5SDimitry Andric } else { 10030b57cec5SDimitry Andric Vote thread_vote = eVoteNoOpinion; 10040b57cec5SDimitry Andric ThreadPlan *plan_ptr = GetCurrentPlan(); 10050b57cec5SDimitry Andric while (true) { 10060b57cec5SDimitry Andric if (plan_ptr->PlanExplainsStop(event_ptr)) { 10070b57cec5SDimitry Andric thread_vote = plan_ptr->ShouldReportStop(event_ptr); 10080b57cec5SDimitry Andric break; 10090b57cec5SDimitry Andric } 10105ffd83dbSDimitry Andric if (plan_ptr->IsBasePlan()) 10110b57cec5SDimitry Andric break; 10120b57cec5SDimitry Andric else 10130b57cec5SDimitry Andric plan_ptr = GetPreviousPlan(plan_ptr); 10140b57cec5SDimitry Andric } 10159dba64beSDimitry Andric LLDB_LOGF(log, 10169dba64beSDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 10170b57cec5SDimitry Andric ": returning vote %i for current plan", 10180b57cec5SDimitry Andric GetID(), thread_vote); 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric return thread_vote; 10210b57cec5SDimitry Andric } 10220b57cec5SDimitry Andric } 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric Vote Thread::ShouldReportRun(Event *event_ptr) { 10250b57cec5SDimitry Andric StateType thread_state = GetResumeState(); 10260b57cec5SDimitry Andric 10270b57cec5SDimitry Andric if (thread_state == eStateSuspended || thread_state == eStateInvalid) { 10280b57cec5SDimitry Andric return eVoteNoOpinion; 10290b57cec5SDimitry Andric } 10300b57cec5SDimitry Andric 103181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 10325ffd83dbSDimitry Andric if (GetPlans().AnyCompletedPlans()) { 10335ffd83dbSDimitry Andric // Pass skip_private = false to GetCompletedPlan, since we want to ask 10345ffd83dbSDimitry Andric // the last plan, regardless of whether it is private or not. 10359dba64beSDimitry Andric LLDB_LOGF(log, 10369dba64beSDimitry Andric "Current Plan for thread %d(%p) (0x%4.4" PRIx64 10370b57cec5SDimitry Andric ", %s): %s being asked whether we should report run.", 10380b57cec5SDimitry Andric GetIndexID(), static_cast<void *>(this), GetID(), 10390b57cec5SDimitry Andric StateAsCString(GetTemporaryResumeState()), 10405ffd83dbSDimitry Andric GetCompletedPlan()->GetName()); 10410b57cec5SDimitry Andric 10425ffd83dbSDimitry Andric return GetPlans().GetCompletedPlan(false)->ShouldReportRun(event_ptr); 10430b57cec5SDimitry Andric } else { 10449dba64beSDimitry Andric LLDB_LOGF(log, 10459dba64beSDimitry Andric "Current Plan for thread %d(%p) (0x%4.4" PRIx64 10460b57cec5SDimitry Andric ", %s): %s being asked whether we should report run.", 10470b57cec5SDimitry Andric GetIndexID(), static_cast<void *>(this), GetID(), 10480b57cec5SDimitry Andric StateAsCString(GetTemporaryResumeState()), 10490b57cec5SDimitry Andric GetCurrentPlan()->GetName()); 10500b57cec5SDimitry Andric 10510b57cec5SDimitry Andric return GetCurrentPlan()->ShouldReportRun(event_ptr); 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric } 10540b57cec5SDimitry Andric 10550b57cec5SDimitry Andric bool Thread::MatchesSpec(const ThreadSpec *spec) { 10560b57cec5SDimitry Andric return (spec == nullptr) ? true : spec->ThreadPassesBasicTests(*this); 10570b57cec5SDimitry Andric } 10580b57cec5SDimitry Andric 10595ffd83dbSDimitry Andric ThreadPlanStack &Thread::GetPlans() const { 10605ffd83dbSDimitry Andric ThreadPlanStack *plans = GetProcess()->FindThreadPlans(GetID()); 10615ffd83dbSDimitry Andric if (plans) 10625ffd83dbSDimitry Andric return *plans; 10630b57cec5SDimitry Andric 10645ffd83dbSDimitry Andric // History threads don't have a thread plan, but they do ask get asked to 10655ffd83dbSDimitry Andric // describe themselves, which usually involves pulling out the stop reason. 10665ffd83dbSDimitry Andric // That in turn will check for a completed plan on the ThreadPlanStack. 10675ffd83dbSDimitry Andric // Instead of special-casing at that point, we return a Stack with a 10685ffd83dbSDimitry Andric // ThreadPlanNull as its base plan. That will give the right answers to the 10695ffd83dbSDimitry Andric // queries GetDescription makes, and only assert if you try to run the thread. 10705ffd83dbSDimitry Andric if (!m_null_plan_stack_up) 10715ffd83dbSDimitry Andric m_null_plan_stack_up = std::make_unique<ThreadPlanStack>(*this, true); 1072bdd1243dSDimitry Andric return *m_null_plan_stack_up; 10735ffd83dbSDimitry Andric } 10745ffd83dbSDimitry Andric 10755ffd83dbSDimitry Andric void Thread::PushPlan(ThreadPlanSP thread_plan_sp) { 10765ffd83dbSDimitry Andric assert(thread_plan_sp && "Don't push an empty thread plan."); 10770b57cec5SDimitry Andric 107881ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 10790b57cec5SDimitry Andric if (log) { 10800b57cec5SDimitry Andric StreamString s; 10810b57cec5SDimitry Andric thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull); 10829dba64beSDimitry Andric LLDB_LOGF(log, "Thread::PushPlan(0x%p): \"%s\", tid = 0x%4.4" PRIx64 ".", 10830b57cec5SDimitry Andric static_cast<void *>(this), s.GetData(), 10840b57cec5SDimitry Andric thread_plan_sp->GetThread().GetID()); 10850b57cec5SDimitry Andric } 10865ffd83dbSDimitry Andric 10875ffd83dbSDimitry Andric GetPlans().PushPlan(std::move(thread_plan_sp)); 10880b57cec5SDimitry Andric } 10890b57cec5SDimitry Andric 10900b57cec5SDimitry Andric void Thread::PopPlan() { 109181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 10925ffd83dbSDimitry Andric ThreadPlanSP popped_plan_sp = GetPlans().PopPlan(); 10930b57cec5SDimitry Andric if (log) { 10949dba64beSDimitry Andric LLDB_LOGF(log, "Popping plan: \"%s\", tid = 0x%4.4" PRIx64 ".", 10955ffd83dbSDimitry Andric popped_plan_sp->GetName(), popped_plan_sp->GetThread().GetID()); 10960b57cec5SDimitry Andric } 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric 10990b57cec5SDimitry Andric void Thread::DiscardPlan() { 110081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 110181ad6265SDimitry Andric ThreadPlanSP discarded_plan_sp = GetPlans().DiscardPlan(); 11025ffd83dbSDimitry Andric 11039dba64beSDimitry Andric LLDB_LOGF(log, "Discarding plan: \"%s\", tid = 0x%4.4" PRIx64 ".", 11045ffd83dbSDimitry Andric discarded_plan_sp->GetName(), 11055ffd83dbSDimitry Andric discarded_plan_sp->GetThread().GetID()); 11060b57cec5SDimitry Andric } 11070b57cec5SDimitry Andric 1108e8d8bef9SDimitry Andric void Thread::AutoCompleteThreadPlans(CompletionRequest &request) const { 1109e8d8bef9SDimitry Andric const ThreadPlanStack &plans = GetPlans(); 1110e8d8bef9SDimitry Andric if (!plans.AnyPlans()) 1111e8d8bef9SDimitry Andric return; 1112e8d8bef9SDimitry Andric 1113e8d8bef9SDimitry Andric // Iterate from the second plan (index: 1) to skip the base plan. 1114e8d8bef9SDimitry Andric ThreadPlanSP p; 1115e8d8bef9SDimitry Andric uint32_t i = 1; 1116e8d8bef9SDimitry Andric while ((p = plans.GetPlanByIndex(i, false))) { 1117e8d8bef9SDimitry Andric StreamString strm; 1118e8d8bef9SDimitry Andric p->GetDescription(&strm, eDescriptionLevelInitial); 1119e8d8bef9SDimitry Andric request.TryCompleteCurrentArg(std::to_string(i), strm.GetString()); 1120e8d8bef9SDimitry Andric i++; 1121e8d8bef9SDimitry Andric } 1122e8d8bef9SDimitry Andric } 1123e8d8bef9SDimitry Andric 11245ffd83dbSDimitry Andric ThreadPlan *Thread::GetCurrentPlan() const { 11255ffd83dbSDimitry Andric return GetPlans().GetCurrentPlan().get(); 11260b57cec5SDimitry Andric } 11270b57cec5SDimitry Andric 11285ffd83dbSDimitry Andric ThreadPlanSP Thread::GetCompletedPlan() const { 11295ffd83dbSDimitry Andric return GetPlans().GetCompletedPlan(); 11300b57cec5SDimitry Andric } 11310b57cec5SDimitry Andric 11325ffd83dbSDimitry Andric ValueObjectSP Thread::GetReturnValueObject() const { 11335ffd83dbSDimitry Andric return GetPlans().GetReturnValueObject(); 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric 11365ffd83dbSDimitry Andric ExpressionVariableSP Thread::GetExpressionVariable() const { 11375ffd83dbSDimitry Andric return GetPlans().GetExpressionVariable(); 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric 11405ffd83dbSDimitry Andric bool Thread::IsThreadPlanDone(ThreadPlan *plan) const { 11415ffd83dbSDimitry Andric return GetPlans().IsPlanDone(plan); 11420b57cec5SDimitry Andric } 11430b57cec5SDimitry Andric 11445ffd83dbSDimitry Andric bool Thread::WasThreadPlanDiscarded(ThreadPlan *plan) const { 11455ffd83dbSDimitry Andric return GetPlans().WasPlanDiscarded(plan); 11460b57cec5SDimitry Andric } 11470b57cec5SDimitry Andric 11485ffd83dbSDimitry Andric bool Thread::CompletedPlanOverridesBreakpoint() const { 11495ffd83dbSDimitry Andric return GetPlans().AnyCompletedPlans(); 11500b57cec5SDimitry Andric } 11510b57cec5SDimitry Andric 11525ffd83dbSDimitry Andric ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) const{ 11535ffd83dbSDimitry Andric return GetPlans().GetPreviousPlan(current_plan); 11540b57cec5SDimitry Andric } 11550b57cec5SDimitry Andric 11560b57cec5SDimitry Andric Status Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp, 11570b57cec5SDimitry Andric bool abort_other_plans) { 11580b57cec5SDimitry Andric Status status; 11590b57cec5SDimitry Andric StreamString s; 11600b57cec5SDimitry Andric if (!thread_plan_sp->ValidatePlan(&s)) { 11610b57cec5SDimitry Andric DiscardThreadPlansUpToPlan(thread_plan_sp); 11620b57cec5SDimitry Andric thread_plan_sp.reset(); 11630b57cec5SDimitry Andric status.SetErrorString(s.GetString()); 11640b57cec5SDimitry Andric return status; 11650b57cec5SDimitry Andric } 11660b57cec5SDimitry Andric 11670b57cec5SDimitry Andric if (abort_other_plans) 11680b57cec5SDimitry Andric DiscardThreadPlans(true); 11690b57cec5SDimitry Andric 11700b57cec5SDimitry Andric PushPlan(thread_plan_sp); 11710b57cec5SDimitry Andric 11720b57cec5SDimitry Andric // This seems a little funny, but I don't want to have to split up the 11730b57cec5SDimitry Andric // constructor and the DidPush in the scripted plan, that seems annoying. 11740b57cec5SDimitry Andric // That means the constructor has to be in DidPush. So I have to validate the 11750b57cec5SDimitry Andric // plan AFTER pushing it, and then take it off again... 11760b57cec5SDimitry Andric if (!thread_plan_sp->ValidatePlan(&s)) { 11770b57cec5SDimitry Andric DiscardThreadPlansUpToPlan(thread_plan_sp); 11780b57cec5SDimitry Andric thread_plan_sp.reset(); 11790b57cec5SDimitry Andric status.SetErrorString(s.GetString()); 11800b57cec5SDimitry Andric return status; 11810b57cec5SDimitry Andric } 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric return status; 11840b57cec5SDimitry Andric } 11850b57cec5SDimitry Andric 11865ffd83dbSDimitry Andric bool Thread::DiscardUserThreadPlansUpToIndex(uint32_t plan_index) { 11870b57cec5SDimitry Andric // Count the user thread plans from the back end to get the number of the one 11880b57cec5SDimitry Andric // we want to discard: 11890b57cec5SDimitry Andric 11905ffd83dbSDimitry Andric ThreadPlan *up_to_plan_ptr = GetPlans().GetPlanByIndex(plan_index).get(); 11910b57cec5SDimitry Andric if (up_to_plan_ptr == nullptr) 11920b57cec5SDimitry Andric return false; 11930b57cec5SDimitry Andric 11940b57cec5SDimitry Andric DiscardThreadPlansUpToPlan(up_to_plan_ptr); 11950b57cec5SDimitry Andric return true; 11960b57cec5SDimitry Andric } 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andric void Thread::DiscardThreadPlansUpToPlan(lldb::ThreadPlanSP &up_to_plan_sp) { 11990b57cec5SDimitry Andric DiscardThreadPlansUpToPlan(up_to_plan_sp.get()); 12000b57cec5SDimitry Andric } 12010b57cec5SDimitry Andric 12020b57cec5SDimitry Andric void Thread::DiscardThreadPlansUpToPlan(ThreadPlan *up_to_plan_ptr) { 120381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 12049dba64beSDimitry Andric LLDB_LOGF(log, 12059dba64beSDimitry Andric "Discarding thread plans for thread tid = 0x%4.4" PRIx64 12060b57cec5SDimitry Andric ", up to %p", 12070b57cec5SDimitry Andric GetID(), static_cast<void *>(up_to_plan_ptr)); 12085ffd83dbSDimitry Andric GetPlans().DiscardPlansUpToPlan(up_to_plan_ptr); 12090b57cec5SDimitry Andric } 12100b57cec5SDimitry Andric 12110b57cec5SDimitry Andric void Thread::DiscardThreadPlans(bool force) { 121281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 12130b57cec5SDimitry Andric if (log) { 12149dba64beSDimitry Andric LLDB_LOGF(log, 12159dba64beSDimitry Andric "Discarding thread plans for thread (tid = 0x%4.4" PRIx64 12160b57cec5SDimitry Andric ", force %d)", 12170b57cec5SDimitry Andric GetID(), force); 12180b57cec5SDimitry Andric } 12190b57cec5SDimitry Andric 12200b57cec5SDimitry Andric if (force) { 12215ffd83dbSDimitry Andric GetPlans().DiscardAllPlans(); 12220b57cec5SDimitry Andric return; 12230b57cec5SDimitry Andric } 1224349cc55cSDimitry Andric GetPlans().DiscardConsultingControllingPlans(); 12250b57cec5SDimitry Andric } 12260b57cec5SDimitry Andric 12270b57cec5SDimitry Andric Status Thread::UnwindInnermostExpression() { 12280b57cec5SDimitry Andric Status error; 12295ffd83dbSDimitry Andric ThreadPlan *innermost_expr_plan = GetPlans().GetInnermostExpression(); 12305ffd83dbSDimitry Andric if (!innermost_expr_plan) { 12315ffd83dbSDimitry Andric error.SetErrorString("No expressions currently active on this thread"); 12320b57cec5SDimitry Andric return error; 12330b57cec5SDimitry Andric } 12345ffd83dbSDimitry Andric DiscardThreadPlansUpToPlan(innermost_expr_plan); 12350b57cec5SDimitry Andric return error; 12360b57cec5SDimitry Andric } 12370b57cec5SDimitry Andric 1238fe6060f1SDimitry Andric ThreadPlanSP Thread::QueueBasePlan(bool abort_other_plans) { 12390b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanBase(*this)); 12400b57cec5SDimitry Andric QueueThreadPlan(thread_plan_sp, abort_other_plans); 12410b57cec5SDimitry Andric return thread_plan_sp; 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric 12440b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction( 12450b57cec5SDimitry Andric bool step_over, bool abort_other_plans, bool stop_other_threads, 12460b57cec5SDimitry Andric Status &status) { 12470b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepInstruction( 12480b57cec5SDimitry Andric *this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion)); 12490b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans); 12500b57cec5SDimitry Andric return thread_plan_sp; 12510b57cec5SDimitry Andric } 12520b57cec5SDimitry Andric 12530b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepOverRange( 12540b57cec5SDimitry Andric bool abort_other_plans, const AddressRange &range, 12550b57cec5SDimitry Andric const SymbolContext &addr_context, lldb::RunMode stop_other_threads, 12560b57cec5SDimitry Andric Status &status, LazyBool step_out_avoids_code_withoug_debug_info) { 12570b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp; 12580b57cec5SDimitry Andric thread_plan_sp = std::make_shared<ThreadPlanStepOverRange>( 12590b57cec5SDimitry Andric *this, range, addr_context, stop_other_threads, 12600b57cec5SDimitry Andric step_out_avoids_code_withoug_debug_info); 12610b57cec5SDimitry Andric 12620b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans); 12630b57cec5SDimitry Andric return thread_plan_sp; 12640b57cec5SDimitry Andric } 12650b57cec5SDimitry Andric 12660b57cec5SDimitry Andric // Call the QueueThreadPlanForStepOverRange method which takes an address 12670b57cec5SDimitry Andric // range. 12680b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepOverRange( 12690b57cec5SDimitry Andric bool abort_other_plans, const LineEntry &line_entry, 12700b57cec5SDimitry Andric const SymbolContext &addr_context, lldb::RunMode stop_other_threads, 12710b57cec5SDimitry Andric Status &status, LazyBool step_out_avoids_code_withoug_debug_info) { 12720b57cec5SDimitry Andric const bool include_inlined_functions = true; 12730b57cec5SDimitry Andric auto address_range = 12740b57cec5SDimitry Andric line_entry.GetSameLineContiguousAddressRange(include_inlined_functions); 12750b57cec5SDimitry Andric return QueueThreadPlanForStepOverRange( 12760b57cec5SDimitry Andric abort_other_plans, address_range, addr_context, stop_other_threads, 12770b57cec5SDimitry Andric status, step_out_avoids_code_withoug_debug_info); 12780b57cec5SDimitry Andric } 12790b57cec5SDimitry Andric 12800b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepInRange( 12810b57cec5SDimitry Andric bool abort_other_plans, const AddressRange &range, 12820b57cec5SDimitry Andric const SymbolContext &addr_context, const char *step_in_target, 12830b57cec5SDimitry Andric lldb::RunMode stop_other_threads, Status &status, 12840b57cec5SDimitry Andric LazyBool step_in_avoids_code_without_debug_info, 12850b57cec5SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) { 1286fe6060f1SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepInRange( 1287fe6060f1SDimitry Andric *this, range, addr_context, step_in_target, stop_other_threads, 12880b57cec5SDimitry Andric step_in_avoids_code_without_debug_info, 12890b57cec5SDimitry Andric step_out_avoids_code_without_debug_info)); 12900b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans); 12910b57cec5SDimitry Andric return thread_plan_sp; 12920b57cec5SDimitry Andric } 12930b57cec5SDimitry Andric 12940b57cec5SDimitry Andric // Call the QueueThreadPlanForStepInRange method which takes an address range. 12950b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepInRange( 12960b57cec5SDimitry Andric bool abort_other_plans, const LineEntry &line_entry, 12970b57cec5SDimitry Andric const SymbolContext &addr_context, const char *step_in_target, 12980b57cec5SDimitry Andric lldb::RunMode stop_other_threads, Status &status, 12990b57cec5SDimitry Andric LazyBool step_in_avoids_code_without_debug_info, 13000b57cec5SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) { 13010b57cec5SDimitry Andric const bool include_inlined_functions = false; 13020b57cec5SDimitry Andric return QueueThreadPlanForStepInRange( 13030b57cec5SDimitry Andric abort_other_plans, 13040b57cec5SDimitry Andric line_entry.GetSameLineContiguousAddressRange(include_inlined_functions), 13050b57cec5SDimitry Andric addr_context, step_in_target, stop_other_threads, status, 13060b57cec5SDimitry Andric step_in_avoids_code_without_debug_info, 13070b57cec5SDimitry Andric step_out_avoids_code_without_debug_info); 13080b57cec5SDimitry Andric } 13090b57cec5SDimitry Andric 13100b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepOut( 13110b57cec5SDimitry Andric bool abort_other_plans, SymbolContext *addr_context, bool first_insn, 1312fe6060f1SDimitry Andric bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote, 1313fe6060f1SDimitry Andric uint32_t frame_idx, Status &status, 1314fe6060f1SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) { 13150b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut( 1316fe6060f1SDimitry Andric *this, addr_context, first_insn, stop_other_threads, report_stop_vote, 1317fe6060f1SDimitry Andric report_run_vote, frame_idx, step_out_avoids_code_without_debug_info)); 13180b57cec5SDimitry Andric 13190b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans); 13200b57cec5SDimitry Andric return thread_plan_sp; 13210b57cec5SDimitry Andric } 13220b57cec5SDimitry Andric 13230b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepOutNoShouldStop( 13240b57cec5SDimitry Andric bool abort_other_plans, SymbolContext *addr_context, bool first_insn, 1325fe6060f1SDimitry Andric bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote, 1326fe6060f1SDimitry Andric uint32_t frame_idx, Status &status, bool continue_to_next_branch) { 13270b57cec5SDimitry Andric const bool calculate_return_value = 13280b57cec5SDimitry Andric false; // No need to calculate the return value here. 13290b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut( 1330fe6060f1SDimitry Andric *this, addr_context, first_insn, stop_other_threads, report_stop_vote, 1331fe6060f1SDimitry Andric report_run_vote, frame_idx, eLazyBoolNo, continue_to_next_branch, 1332fe6060f1SDimitry Andric calculate_return_value)); 13330b57cec5SDimitry Andric 13340b57cec5SDimitry Andric ThreadPlanStepOut *new_plan = 13350b57cec5SDimitry Andric static_cast<ThreadPlanStepOut *>(thread_plan_sp.get()); 13360b57cec5SDimitry Andric new_plan->ClearShouldStopHereCallbacks(); 13370b57cec5SDimitry Andric 13380b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans); 13390b57cec5SDimitry Andric return thread_plan_sp; 13400b57cec5SDimitry Andric } 13410b57cec5SDimitry Andric 13420b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepThrough(StackID &return_stack_id, 13430b57cec5SDimitry Andric bool abort_other_plans, 13440b57cec5SDimitry Andric bool stop_other_threads, 13450b57cec5SDimitry Andric Status &status) { 13460b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp( 13470b57cec5SDimitry Andric new ThreadPlanStepThrough(*this, return_stack_id, stop_other_threads)); 13480b57cec5SDimitry Andric if (!thread_plan_sp || !thread_plan_sp->ValidatePlan(nullptr)) 13490b57cec5SDimitry Andric return ThreadPlanSP(); 13500b57cec5SDimitry Andric 13510b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans); 13520b57cec5SDimitry Andric return thread_plan_sp; 13530b57cec5SDimitry Andric } 13540b57cec5SDimitry Andric 13550b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForRunToAddress(bool abort_other_plans, 13560b57cec5SDimitry Andric Address &target_addr, 13570b57cec5SDimitry Andric bool stop_other_threads, 13580b57cec5SDimitry Andric Status &status) { 13590b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp( 13600b57cec5SDimitry Andric new ThreadPlanRunToAddress(*this, target_addr, stop_other_threads)); 13610b57cec5SDimitry Andric 13620b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans); 13630b57cec5SDimitry Andric return thread_plan_sp; 13640b57cec5SDimitry Andric } 13650b57cec5SDimitry Andric 13660b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepUntil( 13670b57cec5SDimitry Andric bool abort_other_plans, lldb::addr_t *address_list, size_t num_addresses, 13680b57cec5SDimitry Andric bool stop_other_threads, uint32_t frame_idx, Status &status) { 13690b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepUntil( 13700b57cec5SDimitry Andric *this, address_list, num_addresses, stop_other_threads, frame_idx)); 13710b57cec5SDimitry Andric 13720b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans); 13730b57cec5SDimitry Andric return thread_plan_sp; 13740b57cec5SDimitry Andric } 13750b57cec5SDimitry Andric 13760b57cec5SDimitry Andric lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted( 13779dba64beSDimitry Andric bool abort_other_plans, const char *class_name, 13789dba64beSDimitry Andric StructuredData::ObjectSP extra_args_sp, bool stop_other_threads, 13790b57cec5SDimitry Andric Status &status) { 13809dba64beSDimitry Andric 13810eae32dcSDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanPython( 13820eae32dcSDimitry Andric *this, class_name, StructuredDataImpl(extra_args_sp))); 1383e8d8bef9SDimitry Andric thread_plan_sp->SetStopOthers(stop_other_threads); 13840b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans); 13850b57cec5SDimitry Andric return thread_plan_sp; 13860b57cec5SDimitry Andric } 13870b57cec5SDimitry Andric 13880b57cec5SDimitry Andric uint32_t Thread::GetIndexID() const { return m_index_id; } 13890b57cec5SDimitry Andric 13900b57cec5SDimitry Andric TargetSP Thread::CalculateTarget() { 13910b57cec5SDimitry Andric TargetSP target_sp; 13920b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 13930b57cec5SDimitry Andric if (process_sp) 13940b57cec5SDimitry Andric target_sp = process_sp->CalculateTarget(); 13950b57cec5SDimitry Andric return target_sp; 13960b57cec5SDimitry Andric } 13970b57cec5SDimitry Andric 13980b57cec5SDimitry Andric ProcessSP Thread::CalculateProcess() { return GetProcess(); } 13990b57cec5SDimitry Andric 14000b57cec5SDimitry Andric ThreadSP Thread::CalculateThread() { return shared_from_this(); } 14010b57cec5SDimitry Andric 14020b57cec5SDimitry Andric StackFrameSP Thread::CalculateStackFrame() { return StackFrameSP(); } 14030b57cec5SDimitry Andric 14040b57cec5SDimitry Andric void Thread::CalculateExecutionContext(ExecutionContext &exe_ctx) { 14050b57cec5SDimitry Andric exe_ctx.SetContext(shared_from_this()); 14060b57cec5SDimitry Andric } 14070b57cec5SDimitry Andric 14080b57cec5SDimitry Andric StackFrameListSP Thread::GetStackFrameList() { 14090b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_frame_mutex); 14100b57cec5SDimitry Andric 14110b57cec5SDimitry Andric if (!m_curr_frames_sp) 14120b57cec5SDimitry Andric m_curr_frames_sp = 14130b57cec5SDimitry Andric std::make_shared<StackFrameList>(*this, m_prev_frames_sp, true); 14140b57cec5SDimitry Andric 14150b57cec5SDimitry Andric return m_curr_frames_sp; 14160b57cec5SDimitry Andric } 14170b57cec5SDimitry Andric 1418*0fca6ea1SDimitry Andric std::optional<addr_t> Thread::GetPreviousFrameZeroPC() { 1419*0fca6ea1SDimitry Andric return m_prev_framezero_pc; 1420*0fca6ea1SDimitry Andric } 1421*0fca6ea1SDimitry Andric 14220b57cec5SDimitry Andric void Thread::ClearStackFrames() { 14230b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_frame_mutex); 14240b57cec5SDimitry Andric 14255ffd83dbSDimitry Andric GetUnwinder().Clear(); 1426*0fca6ea1SDimitry Andric m_prev_framezero_pc.reset(); 1427*0fca6ea1SDimitry Andric if (RegisterContextSP reg_ctx_sp = GetRegisterContext()) 1428*0fca6ea1SDimitry Andric m_prev_framezero_pc = reg_ctx_sp->GetPC(); 14290b57cec5SDimitry Andric 14300b57cec5SDimitry Andric // Only store away the old "reference" StackFrameList if we got all its 14310b57cec5SDimitry Andric // frames: 14320b57cec5SDimitry Andric // FIXME: At some point we can try to splice in the frames we have fetched 1433*0fca6ea1SDimitry Andric // into the new frame as we make it, but let's not try that now. 14340b57cec5SDimitry Andric if (m_curr_frames_sp && m_curr_frames_sp->GetAllFramesFetched()) 14350b57cec5SDimitry Andric m_prev_frames_sp.swap(m_curr_frames_sp); 14360b57cec5SDimitry Andric m_curr_frames_sp.reset(); 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric m_extended_info.reset(); 14390b57cec5SDimitry Andric m_extended_info_fetched = false; 14400b57cec5SDimitry Andric } 14410b57cec5SDimitry Andric 14420b57cec5SDimitry Andric lldb::StackFrameSP Thread::GetFrameWithConcreteFrameIndex(uint32_t unwind_idx) { 14430b57cec5SDimitry Andric return GetStackFrameList()->GetFrameWithConcreteFrameIndex(unwind_idx); 14440b57cec5SDimitry Andric } 14450b57cec5SDimitry Andric 14460b57cec5SDimitry Andric Status Thread::ReturnFromFrameWithIndex(uint32_t frame_idx, 14470b57cec5SDimitry Andric lldb::ValueObjectSP return_value_sp, 14480b57cec5SDimitry Andric bool broadcast) { 14490b57cec5SDimitry Andric StackFrameSP frame_sp = GetStackFrameAtIndex(frame_idx); 14500b57cec5SDimitry Andric Status return_error; 14510b57cec5SDimitry Andric 14520b57cec5SDimitry Andric if (!frame_sp) { 14530b57cec5SDimitry Andric return_error.SetErrorStringWithFormat( 14540b57cec5SDimitry Andric "Could not find frame with index %d in thread 0x%" PRIx64 ".", 14550b57cec5SDimitry Andric frame_idx, GetID()); 14560b57cec5SDimitry Andric } 14570b57cec5SDimitry Andric 14580b57cec5SDimitry Andric return ReturnFromFrame(frame_sp, return_value_sp, broadcast); 14590b57cec5SDimitry Andric } 14600b57cec5SDimitry Andric 14610b57cec5SDimitry Andric Status Thread::ReturnFromFrame(lldb::StackFrameSP frame_sp, 14620b57cec5SDimitry Andric lldb::ValueObjectSP return_value_sp, 14630b57cec5SDimitry Andric bool broadcast) { 14640b57cec5SDimitry Andric Status return_error; 14650b57cec5SDimitry Andric 14660b57cec5SDimitry Andric if (!frame_sp) { 14670b57cec5SDimitry Andric return_error.SetErrorString("Can't return to a null frame."); 14680b57cec5SDimitry Andric return return_error; 14690b57cec5SDimitry Andric } 14700b57cec5SDimitry Andric 14710b57cec5SDimitry Andric Thread *thread = frame_sp->GetThread().get(); 14720b57cec5SDimitry Andric uint32_t older_frame_idx = frame_sp->GetFrameIndex() + 1; 14730b57cec5SDimitry Andric StackFrameSP older_frame_sp = thread->GetStackFrameAtIndex(older_frame_idx); 14740b57cec5SDimitry Andric if (!older_frame_sp) { 14750b57cec5SDimitry Andric return_error.SetErrorString("No older frame to return to."); 14760b57cec5SDimitry Andric return return_error; 14770b57cec5SDimitry Andric } 14780b57cec5SDimitry Andric 14790b57cec5SDimitry Andric if (return_value_sp) { 14800b57cec5SDimitry Andric lldb::ABISP abi = thread->GetProcess()->GetABI(); 14810b57cec5SDimitry Andric if (!abi) { 14820b57cec5SDimitry Andric return_error.SetErrorString("Could not find ABI to set return value."); 14830b57cec5SDimitry Andric return return_error; 14840b57cec5SDimitry Andric } 14850b57cec5SDimitry Andric SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextFunction); 14860b57cec5SDimitry Andric 14870b57cec5SDimitry Andric // FIXME: ValueObject::Cast doesn't currently work correctly, at least not 14880b57cec5SDimitry Andric // for scalars. 14890b57cec5SDimitry Andric // Turn that back on when that works. 14900b57cec5SDimitry Andric if (/* DISABLES CODE */ (false) && sc.function != nullptr) { 14910b57cec5SDimitry Andric Type *function_type = sc.function->GetType(); 14920b57cec5SDimitry Andric if (function_type) { 14930b57cec5SDimitry Andric CompilerType return_type = 14940b57cec5SDimitry Andric sc.function->GetCompilerType().GetFunctionReturnType(); 14950b57cec5SDimitry Andric if (return_type) { 14960b57cec5SDimitry Andric StreamString s; 14970b57cec5SDimitry Andric return_type.DumpTypeDescription(&s); 14980b57cec5SDimitry Andric ValueObjectSP cast_value_sp = return_value_sp->Cast(return_type); 14990b57cec5SDimitry Andric if (cast_value_sp) { 15000b57cec5SDimitry Andric cast_value_sp->SetFormat(eFormatHex); 15010b57cec5SDimitry Andric return_value_sp = cast_value_sp; 15020b57cec5SDimitry Andric } 15030b57cec5SDimitry Andric } 15040b57cec5SDimitry Andric } 15050b57cec5SDimitry Andric } 15060b57cec5SDimitry Andric 15070b57cec5SDimitry Andric return_error = abi->SetReturnValueObject(older_frame_sp, return_value_sp); 15080b57cec5SDimitry Andric if (!return_error.Success()) 15090b57cec5SDimitry Andric return return_error; 15100b57cec5SDimitry Andric } 15110b57cec5SDimitry Andric 15120b57cec5SDimitry Andric // Now write the return registers for the chosen frame: Note, we can't use 15130b57cec5SDimitry Andric // ReadAllRegisterValues->WriteAllRegisterValues, since the read & write cook 15140b57cec5SDimitry Andric // their data 15150b57cec5SDimitry Andric 15160b57cec5SDimitry Andric StackFrameSP youngest_frame_sp = thread->GetStackFrameAtIndex(0); 15170b57cec5SDimitry Andric if (youngest_frame_sp) { 15180b57cec5SDimitry Andric lldb::RegisterContextSP reg_ctx_sp(youngest_frame_sp->GetRegisterContext()); 15190b57cec5SDimitry Andric if (reg_ctx_sp) { 15200b57cec5SDimitry Andric bool copy_success = reg_ctx_sp->CopyFromRegisterContext( 15210b57cec5SDimitry Andric older_frame_sp->GetRegisterContext()); 15220b57cec5SDimitry Andric if (copy_success) { 15230b57cec5SDimitry Andric thread->DiscardThreadPlans(true); 15240b57cec5SDimitry Andric thread->ClearStackFrames(); 15257a6dacacSDimitry Andric if (broadcast && EventTypeHasListeners(eBroadcastBitStackChanged)) { 15267a6dacacSDimitry Andric auto data_sp = std::make_shared<ThreadEventData>(shared_from_this()); 15277a6dacacSDimitry Andric BroadcastEvent(eBroadcastBitStackChanged, data_sp); 15287a6dacacSDimitry Andric } 15290b57cec5SDimitry Andric } else { 15300b57cec5SDimitry Andric return_error.SetErrorString("Could not reset register values."); 15310b57cec5SDimitry Andric } 15320b57cec5SDimitry Andric } else { 15330b57cec5SDimitry Andric return_error.SetErrorString("Frame has no register context."); 15340b57cec5SDimitry Andric } 15350b57cec5SDimitry Andric } else { 15360b57cec5SDimitry Andric return_error.SetErrorString("Returned past top frame."); 15370b57cec5SDimitry Andric } 15380b57cec5SDimitry Andric return return_error; 15390b57cec5SDimitry Andric } 15400b57cec5SDimitry Andric 15410b57cec5SDimitry Andric static void DumpAddressList(Stream &s, const std::vector<Address> &list, 15420b57cec5SDimitry Andric ExecutionContextScope *exe_scope) { 15430b57cec5SDimitry Andric for (size_t n = 0; n < list.size(); n++) { 15440b57cec5SDimitry Andric s << "\t"; 15450b57cec5SDimitry Andric list[n].Dump(&s, exe_scope, Address::DumpStyleResolvedDescription, 15460b57cec5SDimitry Andric Address::DumpStyleSectionNameOffset); 15470b57cec5SDimitry Andric s << "\n"; 15480b57cec5SDimitry Andric } 15490b57cec5SDimitry Andric } 15500b57cec5SDimitry Andric 15510b57cec5SDimitry Andric Status Thread::JumpToLine(const FileSpec &file, uint32_t line, 15520b57cec5SDimitry Andric bool can_leave_function, std::string *warnings) { 15530b57cec5SDimitry Andric ExecutionContext exe_ctx(GetStackFrameAtIndex(0)); 15540b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr(); 15550b57cec5SDimitry Andric TargetSP target_sp = exe_ctx.GetTargetSP(); 15560b57cec5SDimitry Andric RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); 15570b57cec5SDimitry Andric StackFrame *frame = exe_ctx.GetFramePtr(); 15580b57cec5SDimitry Andric const SymbolContext &sc = frame->GetSymbolContext(eSymbolContextFunction); 15590b57cec5SDimitry Andric 15600b57cec5SDimitry Andric // Find candidate locations. 15610b57cec5SDimitry Andric std::vector<Address> candidates, within_function, outside_function; 15620b57cec5SDimitry Andric target->GetImages().FindAddressesForLine(target_sp, file, line, sc.function, 15630b57cec5SDimitry Andric within_function, outside_function); 15640b57cec5SDimitry Andric 15650b57cec5SDimitry Andric // If possible, we try and stay within the current function. Within a 15660b57cec5SDimitry Andric // function, we accept multiple locations (optimized code may do this, 15670b57cec5SDimitry Andric // there's no solution here so we do the best we can). However if we're 15680b57cec5SDimitry Andric // trying to leave the function, we don't know how to pick the right 15690b57cec5SDimitry Andric // location, so if there's more than one then we bail. 15700b57cec5SDimitry Andric if (!within_function.empty()) 15710b57cec5SDimitry Andric candidates = within_function; 15720b57cec5SDimitry Andric else if (outside_function.size() == 1 && can_leave_function) 15730b57cec5SDimitry Andric candidates = outside_function; 15740b57cec5SDimitry Andric 15750b57cec5SDimitry Andric // Check if we got anything. 15760b57cec5SDimitry Andric if (candidates.empty()) { 15770b57cec5SDimitry Andric if (outside_function.empty()) { 15780b57cec5SDimitry Andric return Status("Cannot locate an address for %s:%i.", 15790b57cec5SDimitry Andric file.GetFilename().AsCString(), line); 15800b57cec5SDimitry Andric } else if (outside_function.size() == 1) { 15810b57cec5SDimitry Andric return Status("%s:%i is outside the current function.", 15820b57cec5SDimitry Andric file.GetFilename().AsCString(), line); 15830b57cec5SDimitry Andric } else { 15840b57cec5SDimitry Andric StreamString sstr; 15850b57cec5SDimitry Andric DumpAddressList(sstr, outside_function, target); 15860b57cec5SDimitry Andric return Status("%s:%i has multiple candidate locations:\n%s", 15870b57cec5SDimitry Andric file.GetFilename().AsCString(), line, sstr.GetData()); 15880b57cec5SDimitry Andric } 15890b57cec5SDimitry Andric } 15900b57cec5SDimitry Andric 15910b57cec5SDimitry Andric // Accept the first location, warn about any others. 15920b57cec5SDimitry Andric Address dest = candidates[0]; 15930b57cec5SDimitry Andric if (warnings && candidates.size() > 1) { 15940b57cec5SDimitry Andric StreamString sstr; 15950b57cec5SDimitry Andric sstr.Printf("%s:%i appears multiple times in this function, selecting the " 15960b57cec5SDimitry Andric "first location:\n", 15970b57cec5SDimitry Andric file.GetFilename().AsCString(), line); 15980b57cec5SDimitry Andric DumpAddressList(sstr, candidates, target); 15995ffd83dbSDimitry Andric *warnings = std::string(sstr.GetString()); 16000b57cec5SDimitry Andric } 16010b57cec5SDimitry Andric 16020b57cec5SDimitry Andric if (!reg_ctx->SetPC(dest)) 16030b57cec5SDimitry Andric return Status("Cannot change PC to target address."); 16040b57cec5SDimitry Andric 16050b57cec5SDimitry Andric return Status(); 16060b57cec5SDimitry Andric } 16070b57cec5SDimitry Andric 16085f757f3fSDimitry Andric bool Thread::DumpUsingFormat(Stream &strm, uint32_t frame_idx, 16095f757f3fSDimitry Andric const FormatEntity::Entry *format) { 16100b57cec5SDimitry Andric ExecutionContext exe_ctx(shared_from_this()); 16110b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 16125f757f3fSDimitry Andric if (!process || !format) 16135f757f3fSDimitry Andric return false; 16140b57cec5SDimitry Andric 16150b57cec5SDimitry Andric StackFrameSP frame_sp; 16160b57cec5SDimitry Andric SymbolContext frame_sc; 16170b57cec5SDimitry Andric if (frame_idx != LLDB_INVALID_FRAME_ID) { 16180b57cec5SDimitry Andric frame_sp = GetStackFrameAtIndex(frame_idx); 16190b57cec5SDimitry Andric if (frame_sp) { 16200b57cec5SDimitry Andric exe_ctx.SetFrameSP(frame_sp); 16210b57cec5SDimitry Andric frame_sc = frame_sp->GetSymbolContext(eSymbolContextEverything); 16220b57cec5SDimitry Andric } 16230b57cec5SDimitry Andric } 16240b57cec5SDimitry Andric 16255f757f3fSDimitry Andric return FormatEntity::Format(*format, strm, frame_sp ? &frame_sc : nullptr, 16265f757f3fSDimitry Andric &exe_ctx, nullptr, nullptr, false, false); 16275f757f3fSDimitry Andric } 16285f757f3fSDimitry Andric 16295f757f3fSDimitry Andric void Thread::DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx, 16305f757f3fSDimitry Andric bool stop_format) { 16315f757f3fSDimitry Andric ExecutionContext exe_ctx(shared_from_this()); 16325f757f3fSDimitry Andric 16330b57cec5SDimitry Andric const FormatEntity::Entry *thread_format; 16340b57cec5SDimitry Andric if (stop_format) 16350b57cec5SDimitry Andric thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadStopFormat(); 16360b57cec5SDimitry Andric else 16370b57cec5SDimitry Andric thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat(); 16380b57cec5SDimitry Andric 16390b57cec5SDimitry Andric assert(thread_format); 16400b57cec5SDimitry Andric 16415f757f3fSDimitry Andric DumpUsingFormat(strm, frame_idx, thread_format); 16420b57cec5SDimitry Andric } 16430b57cec5SDimitry Andric 16440b57cec5SDimitry Andric void Thread::SettingsInitialize() {} 16450b57cec5SDimitry Andric 16460b57cec5SDimitry Andric void Thread::SettingsTerminate() {} 16470b57cec5SDimitry Andric 16485f757f3fSDimitry Andric lldb::addr_t Thread::GetThreadPointer() { 16495f757f3fSDimitry Andric if (m_reg_context_sp) 16505f757f3fSDimitry Andric return m_reg_context_sp->GetThreadPointer(); 16515f757f3fSDimitry Andric return LLDB_INVALID_ADDRESS; 16525f757f3fSDimitry Andric } 16530b57cec5SDimitry Andric 16540b57cec5SDimitry Andric addr_t Thread::GetThreadLocalData(const ModuleSP module, 16550b57cec5SDimitry Andric lldb::addr_t tls_file_addr) { 16560b57cec5SDimitry Andric // The default implementation is to ask the dynamic loader for it. This can 16570b57cec5SDimitry Andric // be overridden for specific platforms. 16580b57cec5SDimitry Andric DynamicLoader *loader = GetProcess()->GetDynamicLoader(); 16590b57cec5SDimitry Andric if (loader) 16600b57cec5SDimitry Andric return loader->GetThreadLocalData(module, shared_from_this(), 16610b57cec5SDimitry Andric tls_file_addr); 16620b57cec5SDimitry Andric else 16630b57cec5SDimitry Andric return LLDB_INVALID_ADDRESS; 16640b57cec5SDimitry Andric } 16650b57cec5SDimitry Andric 16660b57cec5SDimitry Andric bool Thread::SafeToCallFunctions() { 16670b57cec5SDimitry Andric Process *process = GetProcess().get(); 16680b57cec5SDimitry Andric if (process) { 1669bdd1243dSDimitry Andric DynamicLoader *loader = GetProcess()->GetDynamicLoader(); 1670bdd1243dSDimitry Andric if (loader && loader->IsFullyInitialized() == false) 1671bdd1243dSDimitry Andric return false; 1672bdd1243dSDimitry Andric 16730b57cec5SDimitry Andric SystemRuntime *runtime = process->GetSystemRuntime(); 16740b57cec5SDimitry Andric if (runtime) { 16750b57cec5SDimitry Andric return runtime->SafeToCallFunctionsOnThisThread(shared_from_this()); 16760b57cec5SDimitry Andric } 16770b57cec5SDimitry Andric } 16780b57cec5SDimitry Andric return true; 16790b57cec5SDimitry Andric } 16800b57cec5SDimitry Andric 16810b57cec5SDimitry Andric lldb::StackFrameSP 16820b57cec5SDimitry Andric Thread::GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr) { 16830b57cec5SDimitry Andric return GetStackFrameList()->GetStackFrameSPForStackFramePtr(stack_frame_ptr); 16840b57cec5SDimitry Andric } 16850b57cec5SDimitry Andric 1686e8d8bef9SDimitry Andric std::string Thread::StopReasonAsString(lldb::StopReason reason) { 16870b57cec5SDimitry Andric switch (reason) { 16880b57cec5SDimitry Andric case eStopReasonInvalid: 16890b57cec5SDimitry Andric return "invalid"; 16900b57cec5SDimitry Andric case eStopReasonNone: 16910b57cec5SDimitry Andric return "none"; 16920b57cec5SDimitry Andric case eStopReasonTrace: 16930b57cec5SDimitry Andric return "trace"; 16940b57cec5SDimitry Andric case eStopReasonBreakpoint: 16950b57cec5SDimitry Andric return "breakpoint"; 16960b57cec5SDimitry Andric case eStopReasonWatchpoint: 16970b57cec5SDimitry Andric return "watchpoint"; 16980b57cec5SDimitry Andric case eStopReasonSignal: 16990b57cec5SDimitry Andric return "signal"; 17000b57cec5SDimitry Andric case eStopReasonException: 17010b57cec5SDimitry Andric return "exception"; 17020b57cec5SDimitry Andric case eStopReasonExec: 17030b57cec5SDimitry Andric return "exec"; 1704fe6060f1SDimitry Andric case eStopReasonFork: 1705fe6060f1SDimitry Andric return "fork"; 1706fe6060f1SDimitry Andric case eStopReasonVFork: 1707fe6060f1SDimitry Andric return "vfork"; 1708fe6060f1SDimitry Andric case eStopReasonVForkDone: 1709fe6060f1SDimitry Andric return "vfork done"; 17100b57cec5SDimitry Andric case eStopReasonPlanComplete: 17110b57cec5SDimitry Andric return "plan complete"; 17120b57cec5SDimitry Andric case eStopReasonThreadExiting: 17130b57cec5SDimitry Andric return "thread exiting"; 17140b57cec5SDimitry Andric case eStopReasonInstrumentation: 17150b57cec5SDimitry Andric return "instrumentation break"; 1716fe6060f1SDimitry Andric case eStopReasonProcessorTrace: 1717fe6060f1SDimitry Andric return "processor trace"; 17180b57cec5SDimitry Andric } 17190b57cec5SDimitry Andric 1720e8d8bef9SDimitry Andric return "StopReason = " + std::to_string(reason); 17210b57cec5SDimitry Andric } 17220b57cec5SDimitry Andric 1723e8d8bef9SDimitry Andric std::string Thread::RunModeAsString(lldb::RunMode mode) { 17240b57cec5SDimitry Andric switch (mode) { 17250b57cec5SDimitry Andric case eOnlyThisThread: 17260b57cec5SDimitry Andric return "only this thread"; 17270b57cec5SDimitry Andric case eAllThreads: 17280b57cec5SDimitry Andric return "all threads"; 17290b57cec5SDimitry Andric case eOnlyDuringStepping: 17300b57cec5SDimitry Andric return "only during stepping"; 17310b57cec5SDimitry Andric } 17320b57cec5SDimitry Andric 1733e8d8bef9SDimitry Andric return "RunMode = " + std::to_string(mode); 17340b57cec5SDimitry Andric } 17350b57cec5SDimitry Andric 17360b57cec5SDimitry Andric size_t Thread::GetStatus(Stream &strm, uint32_t start_frame, 17370b57cec5SDimitry Andric uint32_t num_frames, uint32_t num_frames_with_source, 17380b57cec5SDimitry Andric bool stop_format, bool only_stacks) { 17390b57cec5SDimitry Andric 17400b57cec5SDimitry Andric if (!only_stacks) { 17410b57cec5SDimitry Andric ExecutionContext exe_ctx(shared_from_this()); 17420b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr(); 17430b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 17440b57cec5SDimitry Andric strm.Indent(); 17450b57cec5SDimitry Andric bool is_selected = false; 17460b57cec5SDimitry Andric if (process) { 17470b57cec5SDimitry Andric if (process->GetThreadList().GetSelectedThread().get() == this) 17480b57cec5SDimitry Andric is_selected = true; 17490b57cec5SDimitry Andric } 17500b57cec5SDimitry Andric strm.Printf("%c ", is_selected ? '*' : ' '); 17510b57cec5SDimitry Andric if (target && target->GetDebugger().GetUseExternalEditor()) { 17520b57cec5SDimitry Andric StackFrameSP frame_sp = GetStackFrameAtIndex(start_frame); 17530b57cec5SDimitry Andric if (frame_sp) { 17540b57cec5SDimitry Andric SymbolContext frame_sc( 17550b57cec5SDimitry Andric frame_sp->GetSymbolContext(eSymbolContextLineEntry)); 1756*0fca6ea1SDimitry Andric if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.GetFile()) { 175706c3fb27SDimitry Andric if (llvm::Error e = Host::OpenFileInExternalEditor( 175806c3fb27SDimitry Andric target->GetDebugger().GetExternalEditor(), 1759*0fca6ea1SDimitry Andric frame_sc.line_entry.GetFile(), frame_sc.line_entry.line)) { 176006c3fb27SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e), 176106c3fb27SDimitry Andric "OpenFileInExternalEditor failed: {0}"); 176206c3fb27SDimitry Andric } 17630b57cec5SDimitry Andric } 17640b57cec5SDimitry Andric } 17650b57cec5SDimitry Andric } 17660b57cec5SDimitry Andric 17670b57cec5SDimitry Andric DumpUsingSettingsFormat(strm, start_frame, stop_format); 17680b57cec5SDimitry Andric } 17690b57cec5SDimitry Andric 17700b57cec5SDimitry Andric size_t num_frames_shown = 0; 17710b57cec5SDimitry Andric if (num_frames > 0) { 17720b57cec5SDimitry Andric strm.IndentMore(); 17730b57cec5SDimitry Andric 17740b57cec5SDimitry Andric const bool show_frame_info = true; 17750b57cec5SDimitry Andric const bool show_frame_unique = only_stacks; 17760b57cec5SDimitry Andric const char *selected_frame_marker = nullptr; 17770b57cec5SDimitry Andric if (num_frames == 1 || only_stacks || 17780b57cec5SDimitry Andric (GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID())) 17790b57cec5SDimitry Andric strm.IndentMore(); 17800b57cec5SDimitry Andric else 17810b57cec5SDimitry Andric selected_frame_marker = "* "; 17820b57cec5SDimitry Andric 17830b57cec5SDimitry Andric num_frames_shown = GetStackFrameList()->GetStatus( 17840b57cec5SDimitry Andric strm, start_frame, num_frames, show_frame_info, num_frames_with_source, 17850b57cec5SDimitry Andric show_frame_unique, selected_frame_marker); 17860b57cec5SDimitry Andric if (num_frames == 1) 17870b57cec5SDimitry Andric strm.IndentLess(); 17880b57cec5SDimitry Andric strm.IndentLess(); 17890b57cec5SDimitry Andric } 17900b57cec5SDimitry Andric return num_frames_shown; 17910b57cec5SDimitry Andric } 17920b57cec5SDimitry Andric 17930b57cec5SDimitry Andric bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level, 17940b57cec5SDimitry Andric bool print_json_thread, bool print_json_stopinfo) { 17950b57cec5SDimitry Andric const bool stop_format = false; 17960b57cec5SDimitry Andric DumpUsingSettingsFormat(strm, 0, stop_format); 17970b57cec5SDimitry Andric strm.Printf("\n"); 17980b57cec5SDimitry Andric 17990b57cec5SDimitry Andric StructuredData::ObjectSP thread_info = GetExtendedInfo(); 18000b57cec5SDimitry Andric 18010b57cec5SDimitry Andric if (print_json_thread || print_json_stopinfo) { 18020b57cec5SDimitry Andric if (thread_info && print_json_thread) { 18030b57cec5SDimitry Andric thread_info->Dump(strm); 18040b57cec5SDimitry Andric strm.Printf("\n"); 18050b57cec5SDimitry Andric } 18060b57cec5SDimitry Andric 18070b57cec5SDimitry Andric if (print_json_stopinfo && m_stop_info_sp) { 18080b57cec5SDimitry Andric StructuredData::ObjectSP stop_info = m_stop_info_sp->GetExtendedInfo(); 18090b57cec5SDimitry Andric if (stop_info) { 18100b57cec5SDimitry Andric stop_info->Dump(strm); 18110b57cec5SDimitry Andric strm.Printf("\n"); 18120b57cec5SDimitry Andric } 18130b57cec5SDimitry Andric } 18140b57cec5SDimitry Andric 18150b57cec5SDimitry Andric return true; 18160b57cec5SDimitry Andric } 18170b57cec5SDimitry Andric 18180b57cec5SDimitry Andric if (thread_info) { 18190b57cec5SDimitry Andric StructuredData::ObjectSP activity = 18200b57cec5SDimitry Andric thread_info->GetObjectForDotSeparatedPath("activity"); 18210b57cec5SDimitry Andric StructuredData::ObjectSP breadcrumb = 18220b57cec5SDimitry Andric thread_info->GetObjectForDotSeparatedPath("breadcrumb"); 18230b57cec5SDimitry Andric StructuredData::ObjectSP messages = 18240b57cec5SDimitry Andric thread_info->GetObjectForDotSeparatedPath("trace_messages"); 18250b57cec5SDimitry Andric 18260b57cec5SDimitry Andric bool printed_activity = false; 18270b57cec5SDimitry Andric if (activity && activity->GetType() == eStructuredDataTypeDictionary) { 18280b57cec5SDimitry Andric StructuredData::Dictionary *activity_dict = activity->GetAsDictionary(); 18290b57cec5SDimitry Andric StructuredData::ObjectSP id = activity_dict->GetValueForKey("id"); 18300b57cec5SDimitry Andric StructuredData::ObjectSP name = activity_dict->GetValueForKey("name"); 18310b57cec5SDimitry Andric if (name && name->GetType() == eStructuredDataTypeString && id && 18320b57cec5SDimitry Andric id->GetType() == eStructuredDataTypeInteger) { 18330b57cec5SDimitry Andric strm.Format(" Activity '{0}', {1:x}\n", 18340b57cec5SDimitry Andric name->GetAsString()->GetValue(), 183506c3fb27SDimitry Andric id->GetUnsignedIntegerValue()); 18360b57cec5SDimitry Andric } 18370b57cec5SDimitry Andric printed_activity = true; 18380b57cec5SDimitry Andric } 18390b57cec5SDimitry Andric bool printed_breadcrumb = false; 18400b57cec5SDimitry Andric if (breadcrumb && breadcrumb->GetType() == eStructuredDataTypeDictionary) { 18410b57cec5SDimitry Andric if (printed_activity) 18420b57cec5SDimitry Andric strm.Printf("\n"); 18430b57cec5SDimitry Andric StructuredData::Dictionary *breadcrumb_dict = 18440b57cec5SDimitry Andric breadcrumb->GetAsDictionary(); 18450b57cec5SDimitry Andric StructuredData::ObjectSP breadcrumb_text = 18460b57cec5SDimitry Andric breadcrumb_dict->GetValueForKey("name"); 18470b57cec5SDimitry Andric if (breadcrumb_text && 18480b57cec5SDimitry Andric breadcrumb_text->GetType() == eStructuredDataTypeString) { 18490b57cec5SDimitry Andric strm.Format(" Current Breadcrumb: {0}\n", 18500b57cec5SDimitry Andric breadcrumb_text->GetAsString()->GetValue()); 18510b57cec5SDimitry Andric } 18520b57cec5SDimitry Andric printed_breadcrumb = true; 18530b57cec5SDimitry Andric } 18540b57cec5SDimitry Andric if (messages && messages->GetType() == eStructuredDataTypeArray) { 18550b57cec5SDimitry Andric if (printed_breadcrumb) 18560b57cec5SDimitry Andric strm.Printf("\n"); 18570b57cec5SDimitry Andric StructuredData::Array *messages_array = messages->GetAsArray(); 18580b57cec5SDimitry Andric const size_t msg_count = messages_array->GetSize(); 18590b57cec5SDimitry Andric if (msg_count > 0) { 18600b57cec5SDimitry Andric strm.Printf(" %zu trace messages:\n", msg_count); 18610b57cec5SDimitry Andric for (size_t i = 0; i < msg_count; i++) { 18620b57cec5SDimitry Andric StructuredData::ObjectSP message = messages_array->GetItemAtIndex(i); 18630b57cec5SDimitry Andric if (message && message->GetType() == eStructuredDataTypeDictionary) { 18640b57cec5SDimitry Andric StructuredData::Dictionary *message_dict = 18650b57cec5SDimitry Andric message->GetAsDictionary(); 18660b57cec5SDimitry Andric StructuredData::ObjectSP message_text = 18670b57cec5SDimitry Andric message_dict->GetValueForKey("message"); 18680b57cec5SDimitry Andric if (message_text && 18690b57cec5SDimitry Andric message_text->GetType() == eStructuredDataTypeString) { 18700b57cec5SDimitry Andric strm.Format(" {0}\n", message_text->GetAsString()->GetValue()); 18710b57cec5SDimitry Andric } 18720b57cec5SDimitry Andric } 18730b57cec5SDimitry Andric } 18740b57cec5SDimitry Andric } 18750b57cec5SDimitry Andric } 18760b57cec5SDimitry Andric } 18770b57cec5SDimitry Andric 18780b57cec5SDimitry Andric return true; 18790b57cec5SDimitry Andric } 18800b57cec5SDimitry Andric 18810b57cec5SDimitry Andric size_t Thread::GetStackFrameStatus(Stream &strm, uint32_t first_frame, 18820b57cec5SDimitry Andric uint32_t num_frames, bool show_frame_info, 18830b57cec5SDimitry Andric uint32_t num_frames_with_source) { 18840b57cec5SDimitry Andric return GetStackFrameList()->GetStatus( 18850b57cec5SDimitry Andric strm, first_frame, num_frames, show_frame_info, num_frames_with_source); 18860b57cec5SDimitry Andric } 18870b57cec5SDimitry Andric 18885ffd83dbSDimitry Andric Unwind &Thread::GetUnwinder() { 18895ffd83dbSDimitry Andric if (!m_unwinder_up) 18905ffd83dbSDimitry Andric m_unwinder_up = std::make_unique<UnwindLLDB>(*this); 18915ffd83dbSDimitry Andric return *m_unwinder_up; 18920b57cec5SDimitry Andric } 18930b57cec5SDimitry Andric 18940b57cec5SDimitry Andric void Thread::Flush() { 18950b57cec5SDimitry Andric ClearStackFrames(); 18960b57cec5SDimitry Andric m_reg_context_sp.reset(); 18970b57cec5SDimitry Andric } 18980b57cec5SDimitry Andric 18990b57cec5SDimitry Andric bool Thread::IsStillAtLastBreakpointHit() { 19000b57cec5SDimitry Andric // If we are currently stopped at a breakpoint, always return that stopinfo 19010b57cec5SDimitry Andric // and don't reset it. This allows threads to maintain their breakpoint 19020b57cec5SDimitry Andric // stopinfo, such as when thread-stepping in multithreaded programs. 19030b57cec5SDimitry Andric if (m_stop_info_sp) { 19040b57cec5SDimitry Andric StopReason stop_reason = m_stop_info_sp->GetStopReason(); 19050b57cec5SDimitry Andric if (stop_reason == lldb::eStopReasonBreakpoint) { 19060b57cec5SDimitry Andric uint64_t value = m_stop_info_sp->GetValue(); 19070b57cec5SDimitry Andric lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext()); 19080b57cec5SDimitry Andric if (reg_ctx_sp) { 19090b57cec5SDimitry Andric lldb::addr_t pc = reg_ctx_sp->GetPC(); 19100b57cec5SDimitry Andric BreakpointSiteSP bp_site_sp = 19110b57cec5SDimitry Andric GetProcess()->GetBreakpointSiteList().FindByAddress(pc); 19120b57cec5SDimitry Andric if (bp_site_sp && static_cast<break_id_t>(value) == bp_site_sp->GetID()) 19130b57cec5SDimitry Andric return true; 19140b57cec5SDimitry Andric } 19150b57cec5SDimitry Andric } 19160b57cec5SDimitry Andric } 19170b57cec5SDimitry Andric return false; 19180b57cec5SDimitry Andric } 19190b57cec5SDimitry Andric 19200b57cec5SDimitry Andric Status Thread::StepIn(bool source_step, 19210b57cec5SDimitry Andric LazyBool step_in_avoids_code_without_debug_info, 19220b57cec5SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) 19230b57cec5SDimitry Andric 19240b57cec5SDimitry Andric { 19250b57cec5SDimitry Andric Status error; 19260b57cec5SDimitry Andric Process *process = GetProcess().get(); 19270b57cec5SDimitry Andric if (StateIsStoppedState(process->GetState(), true)) { 19280b57cec5SDimitry Andric StackFrameSP frame_sp = GetStackFrameAtIndex(0); 19290b57cec5SDimitry Andric ThreadPlanSP new_plan_sp; 19300b57cec5SDimitry Andric const lldb::RunMode run_mode = eOnlyThisThread; 19310b57cec5SDimitry Andric const bool abort_other_plans = false; 19320b57cec5SDimitry Andric 19330b57cec5SDimitry Andric if (source_step && frame_sp && frame_sp->HasDebugInformation()) { 19340b57cec5SDimitry Andric SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 19350b57cec5SDimitry Andric new_plan_sp = QueueThreadPlanForStepInRange( 19360b57cec5SDimitry Andric abort_other_plans, sc.line_entry, sc, nullptr, run_mode, error, 19370b57cec5SDimitry Andric step_in_avoids_code_without_debug_info, 19380b57cec5SDimitry Andric step_out_avoids_code_without_debug_info); 19390b57cec5SDimitry Andric } else { 19400b57cec5SDimitry Andric new_plan_sp = QueueThreadPlanForStepSingleInstruction( 19410b57cec5SDimitry Andric false, abort_other_plans, run_mode, error); 19420b57cec5SDimitry Andric } 19430b57cec5SDimitry Andric 1944349cc55cSDimitry Andric new_plan_sp->SetIsControllingPlan(true); 19450b57cec5SDimitry Andric new_plan_sp->SetOkayToDiscard(false); 19460b57cec5SDimitry Andric 19470b57cec5SDimitry Andric // Why do we need to set the current thread by ID here??? 19480b57cec5SDimitry Andric process->GetThreadList().SetSelectedThreadByID(GetID()); 19490b57cec5SDimitry Andric error = process->Resume(); 19500b57cec5SDimitry Andric } else { 19510b57cec5SDimitry Andric error.SetErrorString("process not stopped"); 19520b57cec5SDimitry Andric } 19530b57cec5SDimitry Andric return error; 19540b57cec5SDimitry Andric } 19550b57cec5SDimitry Andric 19560b57cec5SDimitry Andric Status Thread::StepOver(bool source_step, 19570b57cec5SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) { 19580b57cec5SDimitry Andric Status error; 19590b57cec5SDimitry Andric Process *process = GetProcess().get(); 19600b57cec5SDimitry Andric if (StateIsStoppedState(process->GetState(), true)) { 19610b57cec5SDimitry Andric StackFrameSP frame_sp = GetStackFrameAtIndex(0); 19620b57cec5SDimitry Andric ThreadPlanSP new_plan_sp; 19630b57cec5SDimitry Andric 19640b57cec5SDimitry Andric const lldb::RunMode run_mode = eOnlyThisThread; 19650b57cec5SDimitry Andric const bool abort_other_plans = false; 19660b57cec5SDimitry Andric 19670b57cec5SDimitry Andric if (source_step && frame_sp && frame_sp->HasDebugInformation()) { 19680b57cec5SDimitry Andric SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 19690b57cec5SDimitry Andric new_plan_sp = QueueThreadPlanForStepOverRange( 19700b57cec5SDimitry Andric abort_other_plans, sc.line_entry, sc, run_mode, error, 19710b57cec5SDimitry Andric step_out_avoids_code_without_debug_info); 19720b57cec5SDimitry Andric } else { 19730b57cec5SDimitry Andric new_plan_sp = QueueThreadPlanForStepSingleInstruction( 19740b57cec5SDimitry Andric true, abort_other_plans, run_mode, error); 19750b57cec5SDimitry Andric } 19760b57cec5SDimitry Andric 1977349cc55cSDimitry Andric new_plan_sp->SetIsControllingPlan(true); 19780b57cec5SDimitry Andric new_plan_sp->SetOkayToDiscard(false); 19790b57cec5SDimitry Andric 19800b57cec5SDimitry Andric // Why do we need to set the current thread by ID here??? 19810b57cec5SDimitry Andric process->GetThreadList().SetSelectedThreadByID(GetID()); 19820b57cec5SDimitry Andric error = process->Resume(); 19830b57cec5SDimitry Andric } else { 19840b57cec5SDimitry Andric error.SetErrorString("process not stopped"); 19850b57cec5SDimitry Andric } 19860b57cec5SDimitry Andric return error; 19870b57cec5SDimitry Andric } 19880b57cec5SDimitry Andric 198981ad6265SDimitry Andric Status Thread::StepOut(uint32_t frame_idx) { 19900b57cec5SDimitry Andric Status error; 19910b57cec5SDimitry Andric Process *process = GetProcess().get(); 19920b57cec5SDimitry Andric if (StateIsStoppedState(process->GetState(), true)) { 19930b57cec5SDimitry Andric const bool first_instruction = false; 19940b57cec5SDimitry Andric const bool stop_other_threads = false; 19950b57cec5SDimitry Andric const bool abort_other_plans = false; 19960b57cec5SDimitry Andric 19970b57cec5SDimitry Andric ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut( 19980b57cec5SDimitry Andric abort_other_plans, nullptr, first_instruction, stop_other_threads, 199981ad6265SDimitry Andric eVoteYes, eVoteNoOpinion, frame_idx, error)); 20000b57cec5SDimitry Andric 2001349cc55cSDimitry Andric new_plan_sp->SetIsControllingPlan(true); 20020b57cec5SDimitry Andric new_plan_sp->SetOkayToDiscard(false); 20030b57cec5SDimitry Andric 20040b57cec5SDimitry Andric // Why do we need to set the current thread by ID here??? 20050b57cec5SDimitry Andric process->GetThreadList().SetSelectedThreadByID(GetID()); 20060b57cec5SDimitry Andric error = process->Resume(); 20070b57cec5SDimitry Andric } else { 20080b57cec5SDimitry Andric error.SetErrorString("process not stopped"); 20090b57cec5SDimitry Andric } 20100b57cec5SDimitry Andric return error; 20110b57cec5SDimitry Andric } 20120b57cec5SDimitry Andric 20130b57cec5SDimitry Andric ValueObjectSP Thread::GetCurrentException() { 20140b57cec5SDimitry Andric if (auto frame_sp = GetStackFrameAtIndex(0)) 20150b57cec5SDimitry Andric if (auto recognized_frame = frame_sp->GetRecognizedFrame()) 20160b57cec5SDimitry Andric if (auto e = recognized_frame->GetExceptionObject()) 20170b57cec5SDimitry Andric return e; 20180b57cec5SDimitry Andric 20190b57cec5SDimitry Andric // NOTE: Even though this behavior is generalized, only ObjC is actually 20200b57cec5SDimitry Andric // supported at the moment. 20210b57cec5SDimitry Andric for (LanguageRuntime *runtime : GetProcess()->GetLanguageRuntimes()) { 20220b57cec5SDimitry Andric if (auto e = runtime->GetExceptionObjectForThread(shared_from_this())) 20230b57cec5SDimitry Andric return e; 20240b57cec5SDimitry Andric } 20250b57cec5SDimitry Andric 20260b57cec5SDimitry Andric return ValueObjectSP(); 20270b57cec5SDimitry Andric } 20280b57cec5SDimitry Andric 20290b57cec5SDimitry Andric ThreadSP Thread::GetCurrentExceptionBacktrace() { 20300b57cec5SDimitry Andric ValueObjectSP exception = GetCurrentException(); 20310b57cec5SDimitry Andric if (!exception) 20320b57cec5SDimitry Andric return ThreadSP(); 20330b57cec5SDimitry Andric 20340b57cec5SDimitry Andric // NOTE: Even though this behavior is generalized, only ObjC is actually 20350b57cec5SDimitry Andric // supported at the moment. 20360b57cec5SDimitry Andric for (LanguageRuntime *runtime : GetProcess()->GetLanguageRuntimes()) { 20370b57cec5SDimitry Andric if (auto bt = runtime->GetBacktraceThreadFromException(exception)) 20380b57cec5SDimitry Andric return bt; 20390b57cec5SDimitry Andric } 20400b57cec5SDimitry Andric 20410b57cec5SDimitry Andric return ThreadSP(); 20420b57cec5SDimitry Andric } 20431fd87a68SDimitry Andric 20441fd87a68SDimitry Andric lldb::ValueObjectSP Thread::GetSiginfoValue() { 20451fd87a68SDimitry Andric ProcessSP process_sp = GetProcess(); 20461fd87a68SDimitry Andric assert(process_sp); 20471fd87a68SDimitry Andric Target &target = process_sp->GetTarget(); 20481fd87a68SDimitry Andric PlatformSP platform_sp = target.GetPlatform(); 20491fd87a68SDimitry Andric assert(platform_sp); 20501fd87a68SDimitry Andric ArchSpec arch = target.GetArchitecture(); 20511fd87a68SDimitry Andric 20521fd87a68SDimitry Andric CompilerType type = platform_sp->GetSiginfoType(arch.GetTriple()); 20531fd87a68SDimitry Andric if (!type.IsValid()) 20541fd87a68SDimitry Andric return ValueObjectConstResult::Create(&target, Status("no siginfo_t for the platform")); 20551fd87a68SDimitry Andric 2056bdd1243dSDimitry Andric std::optional<uint64_t> type_size = type.GetByteSize(nullptr); 20571fd87a68SDimitry Andric assert(type_size); 2058fcaf7f86SDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> data = 2059bdd1243dSDimitry Andric GetSiginfo(*type_size); 20601fd87a68SDimitry Andric if (!data) 20611fd87a68SDimitry Andric return ValueObjectConstResult::Create(&target, Status(data.takeError())); 20621fd87a68SDimitry Andric 20631fd87a68SDimitry Andric DataExtractor data_extractor{data.get()->getBufferStart(), data.get()->getBufferSize(), 20641fd87a68SDimitry Andric process_sp->GetByteOrder(), arch.GetAddressByteSize()}; 20651fd87a68SDimitry Andric return ValueObjectConstResult::Create(&target, type, ConstString("__lldb_siginfo"), data_extractor); 20661fd87a68SDimitry Andric } 2067