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"
160b57cec5SDimitry Andric #include "lldb/Host/Host.h"
170b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueFileSpecList.h"
180b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueProperties.h"
190b57cec5SDimitry Andric #include "lldb/Interpreter/Property.h"
200b57cec5SDimitry Andric #include "lldb/Symbol/Function.h"
210b57cec5SDimitry Andric #include "lldb/Target/ABI.h"
220b57cec5SDimitry Andric #include "lldb/Target/DynamicLoader.h"
230b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
240b57cec5SDimitry Andric #include "lldb/Target/LanguageRuntime.h"
250b57cec5SDimitry Andric #include "lldb/Target/Process.h"
260b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h"
270b57cec5SDimitry Andric #include "lldb/Target/StackFrameRecognizer.h"
280b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h"
290b57cec5SDimitry Andric #include "lldb/Target/SystemRuntime.h"
300b57cec5SDimitry Andric #include "lldb/Target/Target.h"
310b57cec5SDimitry Andric #include "lldb/Target/ThreadPlan.h"
320b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanBase.h"
330b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanCallFunction.h"
340b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanPython.h"
350b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanRunToAddress.h"
365ffd83dbSDimitry Andric #include "lldb/Target/ThreadPlanStack.h"
370b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepInRange.h"
380b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepInstruction.h"
390b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepOut.h"
400b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
410b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepOverRange.h"
420b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepThrough.h"
430b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepUntil.h"
440b57cec5SDimitry Andric #include "lldb/Target/ThreadSpec.h"
455ffd83dbSDimitry Andric #include "lldb/Target/UnwindLLDB.h"
460b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
470b57cec5SDimitry Andric #include "lldb/Utility/RegularExpression.h"
480b57cec5SDimitry Andric #include "lldb/Utility/State.h"
490b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
500b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
510b57cec5SDimitry Andric #include "lldb/lldb-enumerations.h"
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric #include <memory>
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric using namespace lldb;
560b57cec5SDimitry Andric using namespace lldb_private;
570b57cec5SDimitry Andric
GetGlobalProperties()580b57cec5SDimitry Andric const ThreadPropertiesSP &Thread::GetGlobalProperties() {
590b57cec5SDimitry Andric // NOTE: intentional leak so we don't crash if global destructor chain gets
600b57cec5SDimitry Andric // called as other threads still use the result of this function
610b57cec5SDimitry Andric static ThreadPropertiesSP *g_settings_sp_ptr =
620b57cec5SDimitry Andric new ThreadPropertiesSP(new ThreadProperties(true));
630b57cec5SDimitry Andric return *g_settings_sp_ptr;
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric
669dba64beSDimitry Andric #define LLDB_PROPERTIES_thread
679dba64beSDimitry Andric #include "TargetProperties.inc"
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric enum {
709dba64beSDimitry Andric #define LLDB_PROPERTIES_thread
719dba64beSDimitry Andric #include "TargetPropertiesEnum.inc"
720b57cec5SDimitry Andric };
730b57cec5SDimitry Andric
74*5f7ddb14SDimitry Andric class ThreadOptionValueProperties
75*5f7ddb14SDimitry Andric : public Cloneable<ThreadOptionValueProperties, OptionValueProperties> {
760b57cec5SDimitry Andric public:
ThreadOptionValueProperties(ConstString name)77*5f7ddb14SDimitry Andric ThreadOptionValueProperties(ConstString name) : Cloneable(name) {}
780b57cec5SDimitry Andric
GetPropertyAtIndex(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const790b57cec5SDimitry Andric const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx,
800b57cec5SDimitry Andric bool will_modify,
810b57cec5SDimitry Andric uint32_t idx) const override {
820b57cec5SDimitry Andric // When getting the value for a key from the thread options, we will always
830b57cec5SDimitry Andric // try and grab the setting from the current thread if there is one. Else
840b57cec5SDimitry Andric // we just use the one from this instance.
850b57cec5SDimitry Andric if (exe_ctx) {
860b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
870b57cec5SDimitry Andric if (thread) {
880b57cec5SDimitry Andric ThreadOptionValueProperties *instance_properties =
890b57cec5SDimitry Andric static_cast<ThreadOptionValueProperties *>(
900b57cec5SDimitry Andric thread->GetValueProperties().get());
910b57cec5SDimitry Andric if (this != instance_properties)
920b57cec5SDimitry Andric return instance_properties->ProtectedGetPropertyAtIndex(idx);
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric return ProtectedGetPropertyAtIndex(idx);
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric };
980b57cec5SDimitry Andric
ThreadProperties(bool is_global)990b57cec5SDimitry Andric ThreadProperties::ThreadProperties(bool is_global) : Properties() {
1000b57cec5SDimitry Andric if (is_global) {
1010b57cec5SDimitry Andric m_collection_sp =
1020b57cec5SDimitry Andric std::make_shared<ThreadOptionValueProperties>(ConstString("thread"));
1039dba64beSDimitry Andric m_collection_sp->Initialize(g_thread_properties);
1040b57cec5SDimitry Andric } else
105*5f7ddb14SDimitry Andric m_collection_sp =
106*5f7ddb14SDimitry Andric OptionValueProperties::CreateLocalCopy(*Thread::GetGlobalProperties());
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric
1090b57cec5SDimitry Andric ThreadProperties::~ThreadProperties() = default;
1100b57cec5SDimitry Andric
GetSymbolsToAvoidRegexp()1110b57cec5SDimitry Andric const RegularExpression *ThreadProperties::GetSymbolsToAvoidRegexp() {
1120b57cec5SDimitry Andric const uint32_t idx = ePropertyStepAvoidRegex;
1130b57cec5SDimitry Andric return m_collection_sp->GetPropertyAtIndexAsOptionValueRegex(nullptr, idx);
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric
GetLibrariesToAvoid() const1160b57cec5SDimitry Andric FileSpecList ThreadProperties::GetLibrariesToAvoid() const {
1170b57cec5SDimitry Andric const uint32_t idx = ePropertyStepAvoidLibraries;
1180b57cec5SDimitry Andric const OptionValueFileSpecList *option_value =
1190b57cec5SDimitry Andric m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr,
1200b57cec5SDimitry Andric false, idx);
1210b57cec5SDimitry Andric assert(option_value);
1220b57cec5SDimitry Andric return option_value->GetCurrentValue();
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric
GetTraceEnabledState() const1250b57cec5SDimitry Andric bool ThreadProperties::GetTraceEnabledState() const {
1260b57cec5SDimitry Andric const uint32_t idx = ePropertyEnableThreadTrace;
1270b57cec5SDimitry Andric return m_collection_sp->GetPropertyAtIndexAsBoolean(
1289dba64beSDimitry Andric nullptr, idx, g_thread_properties[idx].default_uint_value != 0);
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric
GetStepInAvoidsNoDebug() const1310b57cec5SDimitry Andric bool ThreadProperties::GetStepInAvoidsNoDebug() const {
1320b57cec5SDimitry Andric const uint32_t idx = ePropertyStepInAvoidsNoDebug;
1330b57cec5SDimitry Andric return m_collection_sp->GetPropertyAtIndexAsBoolean(
1349dba64beSDimitry Andric nullptr, idx, g_thread_properties[idx].default_uint_value != 0);
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric
GetStepOutAvoidsNoDebug() const1370b57cec5SDimitry Andric bool ThreadProperties::GetStepOutAvoidsNoDebug() const {
1380b57cec5SDimitry Andric const uint32_t idx = ePropertyStepOutAvoidsNoDebug;
1390b57cec5SDimitry Andric return m_collection_sp->GetPropertyAtIndexAsBoolean(
1409dba64beSDimitry Andric nullptr, idx, g_thread_properties[idx].default_uint_value != 0);
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric
GetMaxBacktraceDepth() const1430b57cec5SDimitry Andric uint64_t ThreadProperties::GetMaxBacktraceDepth() const {
1440b57cec5SDimitry Andric const uint32_t idx = ePropertyMaxBacktraceDepth;
1450b57cec5SDimitry Andric return m_collection_sp->GetPropertyAtIndexAsUInt64(
1469dba64beSDimitry Andric nullptr, idx, g_thread_properties[idx].default_uint_value != 0);
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric
1490b57cec5SDimitry Andric // Thread Event Data
1500b57cec5SDimitry Andric
GetFlavorString()1510b57cec5SDimitry Andric ConstString Thread::ThreadEventData::GetFlavorString() {
1520b57cec5SDimitry Andric static ConstString g_flavor("Thread::ThreadEventData");
1530b57cec5SDimitry Andric return g_flavor;
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric
ThreadEventData(const lldb::ThreadSP thread_sp)1560b57cec5SDimitry Andric Thread::ThreadEventData::ThreadEventData(const lldb::ThreadSP thread_sp)
1570b57cec5SDimitry Andric : m_thread_sp(thread_sp), m_stack_id() {}
1580b57cec5SDimitry Andric
ThreadEventData(const lldb::ThreadSP thread_sp,const StackID & stack_id)1590b57cec5SDimitry Andric Thread::ThreadEventData::ThreadEventData(const lldb::ThreadSP thread_sp,
1600b57cec5SDimitry Andric const StackID &stack_id)
1610b57cec5SDimitry Andric : m_thread_sp(thread_sp), m_stack_id(stack_id) {}
1620b57cec5SDimitry Andric
ThreadEventData()1630b57cec5SDimitry Andric Thread::ThreadEventData::ThreadEventData() : m_thread_sp(), m_stack_id() {}
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric Thread::ThreadEventData::~ThreadEventData() = default;
1660b57cec5SDimitry Andric
Dump(Stream * s) const1670b57cec5SDimitry Andric void Thread::ThreadEventData::Dump(Stream *s) const {}
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric const Thread::ThreadEventData *
GetEventDataFromEvent(const Event * event_ptr)1700b57cec5SDimitry Andric Thread::ThreadEventData::GetEventDataFromEvent(const Event *event_ptr) {
1710b57cec5SDimitry Andric if (event_ptr) {
1720b57cec5SDimitry Andric const EventData *event_data = event_ptr->GetData();
1730b57cec5SDimitry Andric if (event_data &&
1740b57cec5SDimitry Andric event_data->GetFlavor() == ThreadEventData::GetFlavorString())
1750b57cec5SDimitry Andric return static_cast<const ThreadEventData *>(event_ptr->GetData());
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric return nullptr;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric
GetThreadFromEvent(const Event * event_ptr)1800b57cec5SDimitry Andric ThreadSP Thread::ThreadEventData::GetThreadFromEvent(const Event *event_ptr) {
1810b57cec5SDimitry Andric ThreadSP thread_sp;
1820b57cec5SDimitry Andric const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr);
1830b57cec5SDimitry Andric if (event_data)
1840b57cec5SDimitry Andric thread_sp = event_data->GetThread();
1850b57cec5SDimitry Andric return thread_sp;
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric
GetStackIDFromEvent(const Event * event_ptr)1880b57cec5SDimitry Andric StackID Thread::ThreadEventData::GetStackIDFromEvent(const Event *event_ptr) {
1890b57cec5SDimitry Andric StackID stack_id;
1900b57cec5SDimitry Andric const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr);
1910b57cec5SDimitry Andric if (event_data)
1920b57cec5SDimitry Andric stack_id = event_data->GetStackID();
1930b57cec5SDimitry Andric return stack_id;
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric
1960b57cec5SDimitry Andric StackFrameSP
GetStackFrameFromEvent(const Event * event_ptr)1970b57cec5SDimitry Andric Thread::ThreadEventData::GetStackFrameFromEvent(const Event *event_ptr) {
1980b57cec5SDimitry Andric const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr);
1990b57cec5SDimitry Andric StackFrameSP frame_sp;
2000b57cec5SDimitry Andric if (event_data) {
2010b57cec5SDimitry Andric ThreadSP thread_sp = event_data->GetThread();
2020b57cec5SDimitry Andric if (thread_sp) {
2030b57cec5SDimitry Andric frame_sp = thread_sp->GetStackFrameList()->GetFrameWithStackID(
2040b57cec5SDimitry Andric event_data->GetStackID());
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric return frame_sp;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric
2100b57cec5SDimitry Andric // Thread class
2110b57cec5SDimitry Andric
GetStaticBroadcasterClass()2120b57cec5SDimitry Andric ConstString &Thread::GetStaticBroadcasterClass() {
2130b57cec5SDimitry Andric static ConstString class_name("lldb.thread");
2140b57cec5SDimitry Andric return class_name;
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric
Thread(Process & process,lldb::tid_t tid,bool use_invalid_index_id)2170b57cec5SDimitry Andric Thread::Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id)
2180b57cec5SDimitry Andric : ThreadProperties(false), UserID(tid),
2190b57cec5SDimitry Andric Broadcaster(process.GetTarget().GetDebugger().GetBroadcasterManager(),
2200b57cec5SDimitry Andric Thread::GetStaticBroadcasterClass().AsCString()),
2210b57cec5SDimitry Andric m_process_wp(process.shared_from_this()), m_stop_info_sp(),
2220b57cec5SDimitry Andric m_stop_info_stop_id(0), m_stop_info_override_stop_id(0),
2230b57cec5SDimitry Andric m_index_id(use_invalid_index_id ? LLDB_INVALID_INDEX32
2240b57cec5SDimitry Andric : process.GetNextThreadIndexID(tid)),
2250b57cec5SDimitry Andric m_reg_context_sp(), m_state(eStateUnloaded), m_state_mutex(),
2265ffd83dbSDimitry Andric m_frame_mutex(), m_curr_frames_sp(), m_prev_frames_sp(),
2270b57cec5SDimitry Andric m_resume_signal(LLDB_INVALID_SIGNAL_NUMBER),
2280b57cec5SDimitry Andric m_resume_state(eStateRunning), m_temporary_resume_state(eStateRunning),
2290b57cec5SDimitry Andric m_unwinder_up(), m_destroy_called(false),
2300b57cec5SDimitry Andric m_override_should_notify(eLazyBoolCalculate),
2310b57cec5SDimitry Andric m_extended_info_fetched(false), m_extended_info() {
2320b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
2339dba64beSDimitry Andric LLDB_LOGF(log, "%p Thread::Thread(tid = 0x%4.4" PRIx64 ")",
2340b57cec5SDimitry Andric static_cast<void *>(this), GetID());
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric CheckInWithManager();
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric
~Thread()2390b57cec5SDimitry Andric Thread::~Thread() {
2400b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
2419dba64beSDimitry Andric LLDB_LOGF(log, "%p Thread::~Thread(tid = 0x%4.4" PRIx64 ")",
2420b57cec5SDimitry Andric static_cast<void *>(this), GetID());
2430b57cec5SDimitry Andric /// If you hit this assert, it means your derived class forgot to call
2440b57cec5SDimitry Andric /// DoDestroy in its destructor.
2450b57cec5SDimitry Andric assert(m_destroy_called);
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric
DestroyThread()2480b57cec5SDimitry Andric void Thread::DestroyThread() {
2490b57cec5SDimitry Andric m_destroy_called = true;
2500b57cec5SDimitry Andric m_stop_info_sp.reset();
2510b57cec5SDimitry Andric m_reg_context_sp.reset();
2520b57cec5SDimitry Andric m_unwinder_up.reset();
2530b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
2540b57cec5SDimitry Andric m_curr_frames_sp.reset();
2550b57cec5SDimitry Andric m_prev_frames_sp.reset();
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric
BroadcastSelectedFrameChange(StackID & new_frame_id)2580b57cec5SDimitry Andric void Thread::BroadcastSelectedFrameChange(StackID &new_frame_id) {
2590b57cec5SDimitry Andric if (EventTypeHasListeners(eBroadcastBitSelectedFrameChanged))
2600b57cec5SDimitry Andric BroadcastEvent(eBroadcastBitSelectedFrameChanged,
2610b57cec5SDimitry Andric new ThreadEventData(this->shared_from_this(), new_frame_id));
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric
GetSelectedFrame()2640b57cec5SDimitry Andric lldb::StackFrameSP Thread::GetSelectedFrame() {
2650b57cec5SDimitry Andric StackFrameListSP stack_frame_list_sp(GetStackFrameList());
2660b57cec5SDimitry Andric StackFrameSP frame_sp = stack_frame_list_sp->GetFrameAtIndex(
2670b57cec5SDimitry Andric stack_frame_list_sp->GetSelectedFrameIndex());
2685ffd83dbSDimitry Andric FrameSelectedCallback(frame_sp.get());
2690b57cec5SDimitry Andric return frame_sp;
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric
SetSelectedFrame(lldb_private::StackFrame * frame,bool broadcast)2720b57cec5SDimitry Andric uint32_t Thread::SetSelectedFrame(lldb_private::StackFrame *frame,
2730b57cec5SDimitry Andric bool broadcast) {
2740b57cec5SDimitry Andric uint32_t ret_value = GetStackFrameList()->SetSelectedFrame(frame);
2750b57cec5SDimitry Andric if (broadcast)
2760b57cec5SDimitry Andric BroadcastSelectedFrameChange(frame->GetStackID());
2775ffd83dbSDimitry Andric FrameSelectedCallback(frame);
2780b57cec5SDimitry Andric return ret_value;
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric
SetSelectedFrameByIndex(uint32_t frame_idx,bool broadcast)2810b57cec5SDimitry Andric bool Thread::SetSelectedFrameByIndex(uint32_t frame_idx, bool broadcast) {
2820b57cec5SDimitry Andric StackFrameSP frame_sp(GetStackFrameList()->GetFrameAtIndex(frame_idx));
2830b57cec5SDimitry Andric if (frame_sp) {
2840b57cec5SDimitry Andric GetStackFrameList()->SetSelectedFrame(frame_sp.get());
2850b57cec5SDimitry Andric if (broadcast)
2860b57cec5SDimitry Andric BroadcastSelectedFrameChange(frame_sp->GetStackID());
2875ffd83dbSDimitry Andric FrameSelectedCallback(frame_sp.get());
2880b57cec5SDimitry Andric return true;
2890b57cec5SDimitry Andric } else
2900b57cec5SDimitry Andric return false;
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric
SetSelectedFrameByIndexNoisily(uint32_t frame_idx,Stream & output_stream)2930b57cec5SDimitry Andric bool Thread::SetSelectedFrameByIndexNoisily(uint32_t frame_idx,
2940b57cec5SDimitry Andric Stream &output_stream) {
2950b57cec5SDimitry Andric const bool broadcast = true;
2960b57cec5SDimitry Andric bool success = SetSelectedFrameByIndex(frame_idx, broadcast);
2970b57cec5SDimitry Andric if (success) {
2980b57cec5SDimitry Andric StackFrameSP frame_sp = GetSelectedFrame();
2990b57cec5SDimitry Andric if (frame_sp) {
3000b57cec5SDimitry Andric bool already_shown = false;
3010b57cec5SDimitry Andric SymbolContext frame_sc(
3020b57cec5SDimitry Andric frame_sp->GetSymbolContext(eSymbolContextLineEntry));
3030b57cec5SDimitry Andric if (GetProcess()->GetTarget().GetDebugger().GetUseExternalEditor() &&
3040b57cec5SDimitry Andric frame_sc.line_entry.file && frame_sc.line_entry.line != 0) {
3050b57cec5SDimitry Andric already_shown = Host::OpenFileInExternalEditor(
3060b57cec5SDimitry Andric frame_sc.line_entry.file, frame_sc.line_entry.line);
3070b57cec5SDimitry Andric }
3080b57cec5SDimitry Andric
3090b57cec5SDimitry Andric bool show_frame_info = true;
3100b57cec5SDimitry Andric bool show_source = !already_shown;
3115ffd83dbSDimitry Andric FrameSelectedCallback(frame_sp.get());
3120b57cec5SDimitry Andric return frame_sp->GetStatus(output_stream, show_frame_info, show_source);
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric return false;
3150b57cec5SDimitry Andric } else
3160b57cec5SDimitry Andric return false;
3170b57cec5SDimitry Andric }
3180b57cec5SDimitry Andric
FrameSelectedCallback(StackFrame * frame)3195ffd83dbSDimitry Andric void Thread::FrameSelectedCallback(StackFrame *frame) {
3205ffd83dbSDimitry Andric if (!frame)
3215ffd83dbSDimitry Andric return;
3225ffd83dbSDimitry Andric
3235ffd83dbSDimitry Andric if (frame->HasDebugInformation() &&
3245ffd83dbSDimitry Andric (GetProcess()->GetWarningsOptimization() ||
3255ffd83dbSDimitry Andric GetProcess()->GetWarningsUnsupportedLanguage())) {
3260b57cec5SDimitry Andric SymbolContext sc =
3270b57cec5SDimitry Andric frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextModule);
3280b57cec5SDimitry Andric GetProcess()->PrintWarningOptimization(sc);
3295ffd83dbSDimitry Andric GetProcess()->PrintWarningUnsupportedLanguage(sc);
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric
GetStopInfo()3330b57cec5SDimitry Andric lldb::StopInfoSP Thread::GetStopInfo() {
3340b57cec5SDimitry Andric if (m_destroy_called)
3350b57cec5SDimitry Andric return m_stop_info_sp;
3360b57cec5SDimitry Andric
3370b57cec5SDimitry Andric ThreadPlanSP completed_plan_sp(GetCompletedPlan());
3380b57cec5SDimitry Andric ProcessSP process_sp(GetProcess());
3390b57cec5SDimitry Andric const uint32_t stop_id = process_sp ? process_sp->GetStopID() : UINT32_MAX;
3400b57cec5SDimitry Andric
3410b57cec5SDimitry Andric // Here we select the stop info according to priorirty: - m_stop_info_sp (if
3420b57cec5SDimitry Andric // not trace) - preset value - completed plan stop info - new value with plan
3430b57cec5SDimitry Andric // from completed plan stack - m_stop_info_sp (trace stop reason is OK now) -
3440b57cec5SDimitry Andric // ask GetPrivateStopInfo to set stop info
3450b57cec5SDimitry Andric
3460b57cec5SDimitry Andric bool have_valid_stop_info = m_stop_info_sp &&
3470b57cec5SDimitry Andric m_stop_info_sp ->IsValid() &&
3480b57cec5SDimitry Andric m_stop_info_stop_id == stop_id;
3490b57cec5SDimitry Andric bool have_valid_completed_plan = completed_plan_sp && completed_plan_sp->PlanSucceeded();
3500b57cec5SDimitry Andric bool plan_failed = completed_plan_sp && !completed_plan_sp->PlanSucceeded();
3510b57cec5SDimitry Andric bool plan_overrides_trace =
3520b57cec5SDimitry Andric have_valid_stop_info && have_valid_completed_plan
3530b57cec5SDimitry Andric && (m_stop_info_sp->GetStopReason() == eStopReasonTrace);
3540b57cec5SDimitry Andric
3550b57cec5SDimitry Andric if (have_valid_stop_info && !plan_overrides_trace && !plan_failed) {
3560b57cec5SDimitry Andric return m_stop_info_sp;
3570b57cec5SDimitry Andric } else if (completed_plan_sp) {
3580b57cec5SDimitry Andric return StopInfo::CreateStopReasonWithPlan(
3590b57cec5SDimitry Andric completed_plan_sp, GetReturnValueObject(), GetExpressionVariable());
3600b57cec5SDimitry Andric } else {
3610b57cec5SDimitry Andric GetPrivateStopInfo();
3620b57cec5SDimitry Andric return m_stop_info_sp;
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric
CalculatePublicStopInfo()3669dba64beSDimitry Andric void Thread::CalculatePublicStopInfo() {
3679dba64beSDimitry Andric ResetStopInfo();
3689dba64beSDimitry Andric SetStopInfo(GetStopInfo());
3699dba64beSDimitry Andric }
3709dba64beSDimitry Andric
GetPrivateStopInfo()3710b57cec5SDimitry Andric lldb::StopInfoSP Thread::GetPrivateStopInfo() {
3720b57cec5SDimitry Andric if (m_destroy_called)
3730b57cec5SDimitry Andric return m_stop_info_sp;
3740b57cec5SDimitry Andric
3750b57cec5SDimitry Andric ProcessSP process_sp(GetProcess());
3760b57cec5SDimitry Andric if (process_sp) {
3770b57cec5SDimitry Andric const uint32_t process_stop_id = process_sp->GetStopID();
3780b57cec5SDimitry Andric if (m_stop_info_stop_id != process_stop_id) {
3790b57cec5SDimitry Andric if (m_stop_info_sp) {
3800b57cec5SDimitry Andric if (m_stop_info_sp->IsValid() || IsStillAtLastBreakpointHit() ||
3810b57cec5SDimitry Andric GetCurrentPlan()->IsVirtualStep())
3820b57cec5SDimitry Andric SetStopInfo(m_stop_info_sp);
3830b57cec5SDimitry Andric else
3840b57cec5SDimitry Andric m_stop_info_sp.reset();
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric
3870b57cec5SDimitry Andric if (!m_stop_info_sp) {
3880b57cec5SDimitry Andric if (!CalculateStopInfo())
3890b57cec5SDimitry Andric SetStopInfo(StopInfoSP());
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric }
3920b57cec5SDimitry Andric
3930b57cec5SDimitry Andric // The stop info can be manually set by calling Thread::SetStopInfo() prior
3940b57cec5SDimitry Andric // to this function ever getting called, so we can't rely on
3950b57cec5SDimitry Andric // "m_stop_info_stop_id != process_stop_id" as the condition for the if
3960b57cec5SDimitry Andric // statement below, we must also check the stop info to see if we need to
3970b57cec5SDimitry Andric // override it. See the header documentation in
3985ffd83dbSDimitry Andric // Architecture::OverrideStopInfo() for more information on the stop
3990b57cec5SDimitry Andric // info override callback.
4000b57cec5SDimitry Andric if (m_stop_info_override_stop_id != process_stop_id) {
4010b57cec5SDimitry Andric m_stop_info_override_stop_id = process_stop_id;
4020b57cec5SDimitry Andric if (m_stop_info_sp) {
4030b57cec5SDimitry Andric if (const Architecture *arch =
4040b57cec5SDimitry Andric process_sp->GetTarget().GetArchitecturePlugin())
4050b57cec5SDimitry Andric arch->OverrideStopInfo(*this);
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric }
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric return m_stop_info_sp;
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric
GetStopReason()4120b57cec5SDimitry Andric lldb::StopReason Thread::GetStopReason() {
4130b57cec5SDimitry Andric lldb::StopInfoSP stop_info_sp(GetStopInfo());
4140b57cec5SDimitry Andric if (stop_info_sp)
4150b57cec5SDimitry Andric return stop_info_sp->GetStopReason();
4160b57cec5SDimitry Andric return eStopReasonNone;
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric
StopInfoIsUpToDate() const4190b57cec5SDimitry Andric bool Thread::StopInfoIsUpToDate() const {
4200b57cec5SDimitry Andric ProcessSP process_sp(GetProcess());
4210b57cec5SDimitry Andric if (process_sp)
4220b57cec5SDimitry Andric return m_stop_info_stop_id == process_sp->GetStopID();
4230b57cec5SDimitry Andric else
4240b57cec5SDimitry Andric return true; // Process is no longer around so stop info is always up to
4250b57cec5SDimitry Andric // date...
4260b57cec5SDimitry Andric }
4270b57cec5SDimitry Andric
ResetStopInfo()4280b57cec5SDimitry Andric void Thread::ResetStopInfo() {
4290b57cec5SDimitry Andric if (m_stop_info_sp) {
4300b57cec5SDimitry Andric m_stop_info_sp.reset();
4310b57cec5SDimitry Andric }
4320b57cec5SDimitry Andric }
4330b57cec5SDimitry Andric
SetStopInfo(const lldb::StopInfoSP & stop_info_sp)4340b57cec5SDimitry Andric void Thread::SetStopInfo(const lldb::StopInfoSP &stop_info_sp) {
4350b57cec5SDimitry Andric m_stop_info_sp = stop_info_sp;
4360b57cec5SDimitry Andric if (m_stop_info_sp) {
4370b57cec5SDimitry Andric m_stop_info_sp->MakeStopInfoValid();
4380b57cec5SDimitry Andric // If we are overriding the ShouldReportStop, do that here:
4390b57cec5SDimitry Andric if (m_override_should_notify != eLazyBoolCalculate)
4400b57cec5SDimitry Andric m_stop_info_sp->OverrideShouldNotify(m_override_should_notify ==
4410b57cec5SDimitry Andric eLazyBoolYes);
4420b57cec5SDimitry Andric }
4430b57cec5SDimitry Andric
4440b57cec5SDimitry Andric ProcessSP process_sp(GetProcess());
4450b57cec5SDimitry Andric if (process_sp)
4460b57cec5SDimitry Andric m_stop_info_stop_id = process_sp->GetStopID();
4470b57cec5SDimitry Andric else
4480b57cec5SDimitry Andric m_stop_info_stop_id = UINT32_MAX;
4490b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
4509dba64beSDimitry Andric LLDB_LOGF(log, "%p: tid = 0x%" PRIx64 ": stop info = %s (stop_id = %u)",
4510b57cec5SDimitry Andric static_cast<void *>(this), GetID(),
4520b57cec5SDimitry Andric stop_info_sp ? stop_info_sp->GetDescription() : "<NULL>",
4530b57cec5SDimitry Andric m_stop_info_stop_id);
4540b57cec5SDimitry Andric }
4550b57cec5SDimitry Andric
SetShouldReportStop(Vote vote)4560b57cec5SDimitry Andric void Thread::SetShouldReportStop(Vote vote) {
4570b57cec5SDimitry Andric if (vote == eVoteNoOpinion)
4580b57cec5SDimitry Andric return;
4590b57cec5SDimitry Andric else {
4600b57cec5SDimitry Andric m_override_should_notify = (vote == eVoteYes ? eLazyBoolYes : eLazyBoolNo);
4610b57cec5SDimitry Andric if (m_stop_info_sp)
4620b57cec5SDimitry Andric m_stop_info_sp->OverrideShouldNotify(m_override_should_notify ==
4630b57cec5SDimitry Andric eLazyBoolYes);
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric
SetStopInfoToNothing()4670b57cec5SDimitry Andric void Thread::SetStopInfoToNothing() {
4680b57cec5SDimitry Andric // Note, we can't just NULL out the private reason, or the native thread
4690b57cec5SDimitry Andric // implementation will try to go calculate it again. For now, just set it to
4700b57cec5SDimitry Andric // a Unix Signal with an invalid signal number.
4710b57cec5SDimitry Andric SetStopInfo(
4720b57cec5SDimitry Andric StopInfo::CreateStopReasonWithSignal(*this, LLDB_INVALID_SIGNAL_NUMBER));
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric
ThreadStoppedForAReason(void)4750b57cec5SDimitry Andric bool Thread::ThreadStoppedForAReason(void) {
4760b57cec5SDimitry Andric return (bool)GetPrivateStopInfo();
4770b57cec5SDimitry Andric }
4780b57cec5SDimitry Andric
CheckpointThreadState(ThreadStateCheckpoint & saved_state)4790b57cec5SDimitry Andric bool Thread::CheckpointThreadState(ThreadStateCheckpoint &saved_state) {
4800b57cec5SDimitry Andric saved_state.register_backup_sp.reset();
4810b57cec5SDimitry Andric lldb::StackFrameSP frame_sp(GetStackFrameAtIndex(0));
4820b57cec5SDimitry Andric if (frame_sp) {
4830b57cec5SDimitry Andric lldb::RegisterCheckpointSP reg_checkpoint_sp(
4840b57cec5SDimitry Andric new RegisterCheckpoint(RegisterCheckpoint::Reason::eExpression));
4850b57cec5SDimitry Andric if (reg_checkpoint_sp) {
4860b57cec5SDimitry Andric lldb::RegisterContextSP reg_ctx_sp(frame_sp->GetRegisterContext());
4870b57cec5SDimitry Andric if (reg_ctx_sp && reg_ctx_sp->ReadAllRegisterValues(*reg_checkpoint_sp))
4880b57cec5SDimitry Andric saved_state.register_backup_sp = reg_checkpoint_sp;
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric }
4910b57cec5SDimitry Andric if (!saved_state.register_backup_sp)
4920b57cec5SDimitry Andric return false;
4930b57cec5SDimitry Andric
4940b57cec5SDimitry Andric saved_state.stop_info_sp = GetStopInfo();
4950b57cec5SDimitry Andric ProcessSP process_sp(GetProcess());
4960b57cec5SDimitry Andric if (process_sp)
4970b57cec5SDimitry Andric saved_state.orig_stop_id = process_sp->GetStopID();
4980b57cec5SDimitry Andric saved_state.current_inlined_depth = GetCurrentInlinedDepth();
4995ffd83dbSDimitry Andric saved_state.m_completed_plan_checkpoint =
5005ffd83dbSDimitry Andric GetPlans().CheckpointCompletedPlans();
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric return true;
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric
RestoreRegisterStateFromCheckpoint(ThreadStateCheckpoint & saved_state)5050b57cec5SDimitry Andric bool Thread::RestoreRegisterStateFromCheckpoint(
5060b57cec5SDimitry Andric ThreadStateCheckpoint &saved_state) {
5070b57cec5SDimitry Andric if (saved_state.register_backup_sp) {
5080b57cec5SDimitry Andric lldb::StackFrameSP frame_sp(GetStackFrameAtIndex(0));
5090b57cec5SDimitry Andric if (frame_sp) {
5100b57cec5SDimitry Andric lldb::RegisterContextSP reg_ctx_sp(frame_sp->GetRegisterContext());
5110b57cec5SDimitry Andric if (reg_ctx_sp) {
5120b57cec5SDimitry Andric bool ret =
5130b57cec5SDimitry Andric reg_ctx_sp->WriteAllRegisterValues(*saved_state.register_backup_sp);
5140b57cec5SDimitry Andric
5150b57cec5SDimitry Andric // Clear out all stack frames as our world just changed.
5160b57cec5SDimitry Andric ClearStackFrames();
5170b57cec5SDimitry Andric reg_ctx_sp->InvalidateIfNeeded(true);
5180b57cec5SDimitry Andric if (m_unwinder_up)
5190b57cec5SDimitry Andric m_unwinder_up->Clear();
5200b57cec5SDimitry Andric return ret;
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric return false;
5250b57cec5SDimitry Andric }
5260b57cec5SDimitry Andric
RestoreThreadStateFromCheckpoint(ThreadStateCheckpoint & saved_state)527*5f7ddb14SDimitry Andric void Thread::RestoreThreadStateFromCheckpoint(
5280b57cec5SDimitry Andric ThreadStateCheckpoint &saved_state) {
5290b57cec5SDimitry Andric if (saved_state.stop_info_sp)
5300b57cec5SDimitry Andric saved_state.stop_info_sp->MakeStopInfoValid();
5310b57cec5SDimitry Andric SetStopInfo(saved_state.stop_info_sp);
5320b57cec5SDimitry Andric GetStackFrameList()->SetCurrentInlinedDepth(
5330b57cec5SDimitry Andric saved_state.current_inlined_depth);
5345ffd83dbSDimitry Andric GetPlans().RestoreCompletedPlanCheckpoint(
5355ffd83dbSDimitry Andric saved_state.m_completed_plan_checkpoint);
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric
GetState() const5380b57cec5SDimitry Andric StateType Thread::GetState() const {
5390b57cec5SDimitry Andric // If any other threads access this we will need a mutex for it
5400b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_state_mutex);
5410b57cec5SDimitry Andric return m_state;
5420b57cec5SDimitry Andric }
5430b57cec5SDimitry Andric
SetState(StateType state)5440b57cec5SDimitry Andric void Thread::SetState(StateType state) {
5450b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_state_mutex);
5460b57cec5SDimitry Andric m_state = state;
5470b57cec5SDimitry Andric }
5480b57cec5SDimitry Andric
GetStopDescription()5495ffd83dbSDimitry Andric std::string Thread::GetStopDescription() {
5505ffd83dbSDimitry Andric StackFrameSP frame_sp = GetStackFrameAtIndex(0);
5515ffd83dbSDimitry Andric
5525ffd83dbSDimitry Andric if (!frame_sp)
5535ffd83dbSDimitry Andric return GetStopDescriptionRaw();
5545ffd83dbSDimitry Andric
5555ffd83dbSDimitry Andric auto recognized_frame_sp = frame_sp->GetRecognizedFrame();
5565ffd83dbSDimitry Andric
5575ffd83dbSDimitry Andric if (!recognized_frame_sp)
5585ffd83dbSDimitry Andric return GetStopDescriptionRaw();
5595ffd83dbSDimitry Andric
5605ffd83dbSDimitry Andric std::string recognized_stop_description =
5615ffd83dbSDimitry Andric recognized_frame_sp->GetStopDescription();
5625ffd83dbSDimitry Andric
5635ffd83dbSDimitry Andric if (!recognized_stop_description.empty())
5645ffd83dbSDimitry Andric return recognized_stop_description;
5655ffd83dbSDimitry Andric
5665ffd83dbSDimitry Andric return GetStopDescriptionRaw();
5675ffd83dbSDimitry Andric }
5685ffd83dbSDimitry Andric
GetStopDescriptionRaw()5695ffd83dbSDimitry Andric std::string Thread::GetStopDescriptionRaw() {
5705ffd83dbSDimitry Andric StopInfoSP stop_info_sp = GetStopInfo();
5715ffd83dbSDimitry Andric std::string raw_stop_description;
5725ffd83dbSDimitry Andric if (stop_info_sp && stop_info_sp->IsValid()) {
5735ffd83dbSDimitry Andric raw_stop_description = stop_info_sp->GetDescription();
5745ffd83dbSDimitry Andric assert((!raw_stop_description.empty() ||
5755ffd83dbSDimitry Andric stop_info_sp->GetStopReason() == eStopReasonNone) &&
5765ffd83dbSDimitry Andric "StopInfo returned an empty description.");
5775ffd83dbSDimitry Andric }
5785ffd83dbSDimitry Andric return raw_stop_description;
5795ffd83dbSDimitry Andric }
5805ffd83dbSDimitry Andric
SelectMostRelevantFrame()5815ffd83dbSDimitry Andric void Thread::SelectMostRelevantFrame() {
5825ffd83dbSDimitry Andric Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD);
5835ffd83dbSDimitry Andric
5845ffd83dbSDimitry Andric auto frames_list_sp = GetStackFrameList();
5855ffd83dbSDimitry Andric
5865ffd83dbSDimitry Andric // Only the top frame should be recognized.
5875ffd83dbSDimitry Andric auto frame_sp = frames_list_sp->GetFrameAtIndex(0);
5885ffd83dbSDimitry Andric
5895ffd83dbSDimitry Andric auto recognized_frame_sp = frame_sp->GetRecognizedFrame();
5905ffd83dbSDimitry Andric
5915ffd83dbSDimitry Andric if (!recognized_frame_sp) {
5925ffd83dbSDimitry Andric LLDB_LOG(log, "Frame #0 not recognized");
5935ffd83dbSDimitry Andric return;
5945ffd83dbSDimitry Andric }
5955ffd83dbSDimitry Andric
5965ffd83dbSDimitry Andric if (StackFrameSP most_relevant_frame_sp =
5975ffd83dbSDimitry Andric recognized_frame_sp->GetMostRelevantFrame()) {
5985ffd83dbSDimitry Andric LLDB_LOG(log, "Found most relevant frame at index {0}",
5995ffd83dbSDimitry Andric most_relevant_frame_sp->GetFrameIndex());
6005ffd83dbSDimitry Andric SetSelectedFrame(most_relevant_frame_sp.get());
6015ffd83dbSDimitry Andric } else {
6025ffd83dbSDimitry Andric LLDB_LOG(log, "No relevant frame!");
6035ffd83dbSDimitry Andric }
6045ffd83dbSDimitry Andric }
6055ffd83dbSDimitry Andric
WillStop()6060b57cec5SDimitry Andric void Thread::WillStop() {
6070b57cec5SDimitry Andric ThreadPlan *current_plan = GetCurrentPlan();
6080b57cec5SDimitry Andric
6095ffd83dbSDimitry Andric SelectMostRelevantFrame();
6105ffd83dbSDimitry Andric
6110b57cec5SDimitry Andric // FIXME: I may decide to disallow threads with no plans. In which
6120b57cec5SDimitry Andric // case this should go to an assert.
6130b57cec5SDimitry Andric
6140b57cec5SDimitry Andric if (!current_plan)
6150b57cec5SDimitry Andric return;
6160b57cec5SDimitry Andric
6170b57cec5SDimitry Andric current_plan->WillStop();
6180b57cec5SDimitry Andric }
6190b57cec5SDimitry Andric
SetupForResume()6200b57cec5SDimitry Andric void Thread::SetupForResume() {
6210b57cec5SDimitry Andric if (GetResumeState() != eStateSuspended) {
6220b57cec5SDimitry Andric // If we're at a breakpoint push the step-over breakpoint plan. Do this
6230b57cec5SDimitry Andric // before telling the current plan it will resume, since we might change
6240b57cec5SDimitry Andric // what the current plan is.
6250b57cec5SDimitry Andric
6260b57cec5SDimitry Andric lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());
6270b57cec5SDimitry Andric if (reg_ctx_sp) {
6280b57cec5SDimitry Andric const addr_t thread_pc = reg_ctx_sp->GetPC();
6290b57cec5SDimitry Andric BreakpointSiteSP bp_site_sp =
6300b57cec5SDimitry Andric GetProcess()->GetBreakpointSiteList().FindByAddress(thread_pc);
6310b57cec5SDimitry Andric if (bp_site_sp) {
6320b57cec5SDimitry Andric // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the
6330b57cec5SDimitry Andric // target may not require anything special to step over a breakpoint.
6340b57cec5SDimitry Andric
6350b57cec5SDimitry Andric ThreadPlan *cur_plan = GetCurrentPlan();
6360b57cec5SDimitry Andric
6370b57cec5SDimitry Andric bool push_step_over_bp_plan = false;
6380b57cec5SDimitry Andric if (cur_plan->GetKind() == ThreadPlan::eKindStepOverBreakpoint) {
6390b57cec5SDimitry Andric ThreadPlanStepOverBreakpoint *bp_plan =
6400b57cec5SDimitry Andric (ThreadPlanStepOverBreakpoint *)cur_plan;
6410b57cec5SDimitry Andric if (bp_plan->GetBreakpointLoadAddress() != thread_pc)
6420b57cec5SDimitry Andric push_step_over_bp_plan = true;
6430b57cec5SDimitry Andric } else
6440b57cec5SDimitry Andric push_step_over_bp_plan = true;
6450b57cec5SDimitry Andric
6460b57cec5SDimitry Andric if (push_step_over_bp_plan) {
6470b57cec5SDimitry Andric ThreadPlanSP step_bp_plan_sp(new ThreadPlanStepOverBreakpoint(*this));
6480b57cec5SDimitry Andric if (step_bp_plan_sp) {
6490b57cec5SDimitry Andric step_bp_plan_sp->SetPrivate(true);
6500b57cec5SDimitry Andric
6510b57cec5SDimitry Andric if (GetCurrentPlan()->RunState() != eStateStepping) {
6520b57cec5SDimitry Andric ThreadPlanStepOverBreakpoint *step_bp_plan =
6530b57cec5SDimitry Andric static_cast<ThreadPlanStepOverBreakpoint *>(
6540b57cec5SDimitry Andric step_bp_plan_sp.get());
6550b57cec5SDimitry Andric step_bp_plan->SetAutoContinue(true);
6560b57cec5SDimitry Andric }
6570b57cec5SDimitry Andric QueueThreadPlan(step_bp_plan_sp, false);
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric }
6600b57cec5SDimitry Andric }
6610b57cec5SDimitry Andric }
6620b57cec5SDimitry Andric }
6630b57cec5SDimitry Andric }
6640b57cec5SDimitry Andric
ShouldResume(StateType resume_state)6650b57cec5SDimitry Andric bool Thread::ShouldResume(StateType resume_state) {
6660b57cec5SDimitry Andric // At this point clear the completed plan stack.
6675ffd83dbSDimitry Andric GetPlans().WillResume();
6680b57cec5SDimitry Andric m_override_should_notify = eLazyBoolCalculate;
6690b57cec5SDimitry Andric
6700b57cec5SDimitry Andric StateType prev_resume_state = GetTemporaryResumeState();
6710b57cec5SDimitry Andric
6720b57cec5SDimitry Andric SetTemporaryResumeState(resume_state);
6730b57cec5SDimitry Andric
6740b57cec5SDimitry Andric lldb::ThreadSP backing_thread_sp(GetBackingThread());
6750b57cec5SDimitry Andric if (backing_thread_sp)
6760b57cec5SDimitry Andric backing_thread_sp->SetTemporaryResumeState(resume_state);
6770b57cec5SDimitry Andric
6780b57cec5SDimitry Andric // Make sure m_stop_info_sp is valid. Don't do this for threads we suspended
6790b57cec5SDimitry Andric // in the previous run.
6800b57cec5SDimitry Andric if (prev_resume_state != eStateSuspended)
6810b57cec5SDimitry Andric GetPrivateStopInfo();
6820b57cec5SDimitry Andric
6830b57cec5SDimitry Andric // This is a little dubious, but we are trying to limit how often we actually
6840b57cec5SDimitry Andric // fetch stop info from the target, 'cause that slows down single stepping.
6850b57cec5SDimitry Andric // So assume that if we got to the point where we're about to resume, and we
6860b57cec5SDimitry Andric // haven't yet had to fetch the stop reason, then it doesn't need to know
6870b57cec5SDimitry Andric // about the fact that we are resuming...
6880b57cec5SDimitry Andric const uint32_t process_stop_id = GetProcess()->GetStopID();
6890b57cec5SDimitry Andric if (m_stop_info_stop_id == process_stop_id &&
6900b57cec5SDimitry Andric (m_stop_info_sp && m_stop_info_sp->IsValid())) {
6910b57cec5SDimitry Andric StopInfo *stop_info = GetPrivateStopInfo().get();
6920b57cec5SDimitry Andric if (stop_info)
6930b57cec5SDimitry Andric stop_info->WillResume(resume_state);
6940b57cec5SDimitry Andric }
6950b57cec5SDimitry Andric
6960b57cec5SDimitry Andric // Tell all the plans that we are about to resume in case they need to clear
6970b57cec5SDimitry Andric // any state. We distinguish between the plan on the top of the stack and the
6980b57cec5SDimitry Andric // lower plans in case a plan needs to do any special business before it
6990b57cec5SDimitry Andric // runs.
7000b57cec5SDimitry Andric
7010b57cec5SDimitry Andric bool need_to_resume = false;
7020b57cec5SDimitry Andric ThreadPlan *plan_ptr = GetCurrentPlan();
7030b57cec5SDimitry Andric if (plan_ptr) {
7040b57cec5SDimitry Andric need_to_resume = plan_ptr->WillResume(resume_state, true);
7050b57cec5SDimitry Andric
7060b57cec5SDimitry Andric while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr) {
7070b57cec5SDimitry Andric plan_ptr->WillResume(resume_state, false);
7080b57cec5SDimitry Andric }
7090b57cec5SDimitry Andric
7100b57cec5SDimitry Andric // If the WillResume for the plan says we are faking a resume, then it will
7110b57cec5SDimitry Andric // have set an appropriate stop info. In that case, don't reset it here.
7120b57cec5SDimitry Andric
7130b57cec5SDimitry Andric if (need_to_resume && resume_state != eStateSuspended) {
7140b57cec5SDimitry Andric m_stop_info_sp.reset();
7150b57cec5SDimitry Andric }
7160b57cec5SDimitry Andric }
7170b57cec5SDimitry Andric
7180b57cec5SDimitry Andric if (need_to_resume) {
7190b57cec5SDimitry Andric ClearStackFrames();
7200b57cec5SDimitry Andric // Let Thread subclasses do any special work they need to prior to resuming
7210b57cec5SDimitry Andric WillResume(resume_state);
7220b57cec5SDimitry Andric }
7230b57cec5SDimitry Andric
7240b57cec5SDimitry Andric return need_to_resume;
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric
DidResume()7270b57cec5SDimitry Andric void Thread::DidResume() { SetResumeSignal(LLDB_INVALID_SIGNAL_NUMBER); }
7280b57cec5SDimitry Andric
DidStop()7290b57cec5SDimitry Andric void Thread::DidStop() { SetState(eStateStopped); }
7300b57cec5SDimitry Andric
ShouldStop(Event * event_ptr)7310b57cec5SDimitry Andric bool Thread::ShouldStop(Event *event_ptr) {
7320b57cec5SDimitry Andric ThreadPlan *current_plan = GetCurrentPlan();
7330b57cec5SDimitry Andric
7340b57cec5SDimitry Andric bool should_stop = true;
7350b57cec5SDimitry Andric
7360b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
7370b57cec5SDimitry Andric
7380b57cec5SDimitry Andric if (GetResumeState() == eStateSuspended) {
7399dba64beSDimitry Andric LLDB_LOGF(log,
7409dba64beSDimitry Andric "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
7410b57cec5SDimitry Andric ", should_stop = 0 (ignore since thread was suspended)",
7420b57cec5SDimitry Andric __FUNCTION__, GetID(), GetProtocolID());
7430b57cec5SDimitry Andric return false;
7440b57cec5SDimitry Andric }
7450b57cec5SDimitry Andric
7460b57cec5SDimitry Andric if (GetTemporaryResumeState() == eStateSuspended) {
7479dba64beSDimitry Andric LLDB_LOGF(log,
7489dba64beSDimitry Andric "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
7490b57cec5SDimitry Andric ", should_stop = 0 (ignore since thread was suspended)",
7500b57cec5SDimitry Andric __FUNCTION__, GetID(), GetProtocolID());
7510b57cec5SDimitry Andric return false;
7520b57cec5SDimitry Andric }
7530b57cec5SDimitry Andric
7540b57cec5SDimitry Andric // Based on the current thread plan and process stop info, check if this
7550b57cec5SDimitry Andric // thread caused the process to stop. NOTE: this must take place before the
7560b57cec5SDimitry Andric // plan is moved from the current plan stack to the completed plan stack.
7570b57cec5SDimitry Andric if (!ThreadStoppedForAReason()) {
7589dba64beSDimitry Andric LLDB_LOGF(log,
7599dba64beSDimitry Andric "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
7600b57cec5SDimitry Andric ", pc = 0x%16.16" PRIx64
7610b57cec5SDimitry Andric ", should_stop = 0 (ignore since no stop reason)",
7620b57cec5SDimitry Andric __FUNCTION__, GetID(), GetProtocolID(),
7630b57cec5SDimitry Andric GetRegisterContext() ? GetRegisterContext()->GetPC()
7640b57cec5SDimitry Andric : LLDB_INVALID_ADDRESS);
7650b57cec5SDimitry Andric return false;
7660b57cec5SDimitry Andric }
7670b57cec5SDimitry Andric
7680b57cec5SDimitry Andric if (log) {
7699dba64beSDimitry Andric LLDB_LOGF(log,
7709dba64beSDimitry Andric "Thread::%s(%p) for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
7710b57cec5SDimitry Andric ", pc = 0x%16.16" PRIx64,
7729dba64beSDimitry Andric __FUNCTION__, static_cast<void *>(this), GetID(), GetProtocolID(),
7730b57cec5SDimitry Andric GetRegisterContext() ? GetRegisterContext()->GetPC()
7740b57cec5SDimitry Andric : LLDB_INVALID_ADDRESS);
7759dba64beSDimitry Andric LLDB_LOGF(log, "^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^");
7760b57cec5SDimitry Andric StreamString s;
7770b57cec5SDimitry Andric s.IndentMore();
7785ffd83dbSDimitry Andric GetProcess()->DumpThreadPlansForTID(
7795ffd83dbSDimitry Andric s, GetID(), eDescriptionLevelVerbose, true /* internal */,
7805ffd83dbSDimitry Andric false /* condense_trivial */, true /* skip_unreported */);
7819dba64beSDimitry Andric LLDB_LOGF(log, "Plan stack initial state:\n%s", s.GetData());
7820b57cec5SDimitry Andric }
7830b57cec5SDimitry Andric
7840b57cec5SDimitry Andric // The top most plan always gets to do the trace log...
7850b57cec5SDimitry Andric current_plan->DoTraceLog();
7860b57cec5SDimitry Andric
7870b57cec5SDimitry Andric // First query the stop info's ShouldStopSynchronous. This handles
7880b57cec5SDimitry Andric // "synchronous" stop reasons, for example the breakpoint command on internal
7890b57cec5SDimitry Andric // breakpoints. If a synchronous stop reason says we should not stop, then
7900b57cec5SDimitry Andric // we don't have to do any more work on this stop.
7910b57cec5SDimitry Andric StopInfoSP private_stop_info(GetPrivateStopInfo());
7920b57cec5SDimitry Andric if (private_stop_info &&
7930b57cec5SDimitry Andric !private_stop_info->ShouldStopSynchronous(event_ptr)) {
7949dba64beSDimitry Andric LLDB_LOGF(log, "StopInfo::ShouldStop async callback says we should not "
7950b57cec5SDimitry Andric "stop, returning ShouldStop of false.");
7960b57cec5SDimitry Andric return false;
7970b57cec5SDimitry Andric }
7980b57cec5SDimitry Andric
7990b57cec5SDimitry Andric // If we've already been restarted, don't query the plans since the state
8000b57cec5SDimitry Andric // they would examine is not current.
8010b57cec5SDimitry Andric if (Process::ProcessEventData::GetRestartedFromEvent(event_ptr))
8020b57cec5SDimitry Andric return false;
8030b57cec5SDimitry Andric
8040b57cec5SDimitry Andric // Before the plans see the state of the world, calculate the current inlined
8050b57cec5SDimitry Andric // depth.
8060b57cec5SDimitry Andric GetStackFrameList()->CalculateCurrentInlinedDepth();
8070b57cec5SDimitry Andric
8080b57cec5SDimitry Andric // If the base plan doesn't understand why we stopped, then we have to find a
8090b57cec5SDimitry Andric // plan that does. If that plan is still working, then we don't need to do
8100b57cec5SDimitry Andric // any more work. If the plan that explains the stop is done, then we should
8110b57cec5SDimitry Andric // pop all the plans below it, and pop it, and then let the plans above it
8120b57cec5SDimitry Andric // decide whether they still need to do more work.
8130b57cec5SDimitry Andric
8140b57cec5SDimitry Andric bool done_processing_current_plan = false;
8150b57cec5SDimitry Andric
8160b57cec5SDimitry Andric if (!current_plan->PlanExplainsStop(event_ptr)) {
8170b57cec5SDimitry Andric if (current_plan->TracerExplainsStop()) {
8180b57cec5SDimitry Andric done_processing_current_plan = true;
8190b57cec5SDimitry Andric should_stop = false;
8200b57cec5SDimitry Andric } else {
8210b57cec5SDimitry Andric // If the current plan doesn't explain the stop, then find one that does
8220b57cec5SDimitry Andric // and let it handle the situation.
8230b57cec5SDimitry Andric ThreadPlan *plan_ptr = current_plan;
8240b57cec5SDimitry Andric while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr) {
8250b57cec5SDimitry Andric if (plan_ptr->PlanExplainsStop(event_ptr)) {
826*5f7ddb14SDimitry Andric LLDB_LOGF(log, "Plan %s explains stop.", plan_ptr->GetName());
827*5f7ddb14SDimitry Andric
8280b57cec5SDimitry Andric should_stop = plan_ptr->ShouldStop(event_ptr);
8290b57cec5SDimitry Andric
8300b57cec5SDimitry Andric // plan_ptr explains the stop, next check whether plan_ptr is done,
8310b57cec5SDimitry Andric // if so, then we should take it and all the plans below it off the
8320b57cec5SDimitry Andric // stack.
8330b57cec5SDimitry Andric
8340b57cec5SDimitry Andric if (plan_ptr->MischiefManaged()) {
8350b57cec5SDimitry Andric // We're going to pop the plans up to and including the plan that
8360b57cec5SDimitry Andric // explains the stop.
8370b57cec5SDimitry Andric ThreadPlan *prev_plan_ptr = GetPreviousPlan(plan_ptr);
8380b57cec5SDimitry Andric
8390b57cec5SDimitry Andric do {
8400b57cec5SDimitry Andric if (should_stop)
8410b57cec5SDimitry Andric current_plan->WillStop();
8420b57cec5SDimitry Andric PopPlan();
8430b57cec5SDimitry Andric } while ((current_plan = GetCurrentPlan()) != prev_plan_ptr);
8440b57cec5SDimitry Andric // Now, if the responsible plan was not "Okay to discard" then
8450b57cec5SDimitry Andric // we're done, otherwise we forward this to the next plan in the
8460b57cec5SDimitry Andric // stack below.
8470b57cec5SDimitry Andric done_processing_current_plan =
8480b57cec5SDimitry Andric (plan_ptr->IsMasterPlan() && !plan_ptr->OkayToDiscard());
8490b57cec5SDimitry Andric } else
8500b57cec5SDimitry Andric done_processing_current_plan = true;
8510b57cec5SDimitry Andric
8520b57cec5SDimitry Andric break;
8530b57cec5SDimitry Andric }
8540b57cec5SDimitry Andric }
8550b57cec5SDimitry Andric }
8560b57cec5SDimitry Andric }
8570b57cec5SDimitry Andric
8580b57cec5SDimitry Andric if (!done_processing_current_plan) {
859*5f7ddb14SDimitry Andric bool override_stop = false;
8600b57cec5SDimitry Andric
8610b57cec5SDimitry Andric // We're starting from the base plan, so just let it decide;
8625ffd83dbSDimitry Andric if (current_plan->IsBasePlan()) {
8630b57cec5SDimitry Andric should_stop = current_plan->ShouldStop(event_ptr);
8649dba64beSDimitry Andric LLDB_LOGF(log, "Base plan says should stop: %i.", should_stop);
8650b57cec5SDimitry Andric } else {
8660b57cec5SDimitry Andric // Otherwise, don't let the base plan override what the other plans say
8670b57cec5SDimitry Andric // to do, since presumably if there were other plans they would know what
8680b57cec5SDimitry Andric // to do...
8690b57cec5SDimitry Andric while (true) {
8705ffd83dbSDimitry Andric if (current_plan->IsBasePlan())
8710b57cec5SDimitry Andric break;
8720b57cec5SDimitry Andric
8730b57cec5SDimitry Andric should_stop = current_plan->ShouldStop(event_ptr);
8749dba64beSDimitry Andric LLDB_LOGF(log, "Plan %s should stop: %d.", current_plan->GetName(),
8750b57cec5SDimitry Andric should_stop);
8760b57cec5SDimitry Andric if (current_plan->MischiefManaged()) {
8770b57cec5SDimitry Andric if (should_stop)
8780b57cec5SDimitry Andric current_plan->WillStop();
8790b57cec5SDimitry Andric
880*5f7ddb14SDimitry Andric if (current_plan->ShouldAutoContinue(event_ptr)) {
881*5f7ddb14SDimitry Andric override_stop = true;
882*5f7ddb14SDimitry Andric LLDB_LOGF(log, "Plan %s auto-continue: true.",
883*5f7ddb14SDimitry Andric current_plan->GetName());
884*5f7ddb14SDimitry Andric }
8850b57cec5SDimitry Andric
886*5f7ddb14SDimitry Andric // If a Master Plan wants to stop, we let it. Otherwise, see if the
887*5f7ddb14SDimitry Andric // plan's parent wants to stop.
888*5f7ddb14SDimitry Andric
889*5f7ddb14SDimitry Andric PopPlan();
8900b57cec5SDimitry Andric if (should_stop && current_plan->IsMasterPlan() &&
8910b57cec5SDimitry Andric !current_plan->OkayToDiscard()) {
8920b57cec5SDimitry Andric break;
893*5f7ddb14SDimitry Andric }
8940b57cec5SDimitry Andric
8950b57cec5SDimitry Andric current_plan = GetCurrentPlan();
8960b57cec5SDimitry Andric if (current_plan == nullptr) {
8970b57cec5SDimitry Andric break;
8980b57cec5SDimitry Andric }
8990b57cec5SDimitry Andric } else {
9000b57cec5SDimitry Andric break;
9010b57cec5SDimitry Andric }
9020b57cec5SDimitry Andric }
9030b57cec5SDimitry Andric }
9040b57cec5SDimitry Andric
905*5f7ddb14SDimitry Andric if (override_stop)
9060b57cec5SDimitry Andric should_stop = false;
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric
9090b57cec5SDimitry Andric // One other potential problem is that we set up a master plan, then stop in
9100b57cec5SDimitry Andric // before it is complete - for instance by hitting a breakpoint during a
9110b57cec5SDimitry Andric // step-over - then do some step/finish/etc operations that wind up past the
9120b57cec5SDimitry Andric // end point condition of the initial plan. We don't want to strand the
9130b57cec5SDimitry Andric // original plan on the stack, This code clears stale plans off the stack.
9140b57cec5SDimitry Andric
9150b57cec5SDimitry Andric if (should_stop) {
9160b57cec5SDimitry Andric ThreadPlan *plan_ptr = GetCurrentPlan();
9170b57cec5SDimitry Andric
9180b57cec5SDimitry Andric // Discard the stale plans and all plans below them in the stack, plus move
9190b57cec5SDimitry Andric // the completed plans to the completed plan stack
9205ffd83dbSDimitry Andric while (!plan_ptr->IsBasePlan()) {
9210b57cec5SDimitry Andric bool stale = plan_ptr->IsPlanStale();
9220b57cec5SDimitry Andric ThreadPlan *examined_plan = plan_ptr;
9230b57cec5SDimitry Andric plan_ptr = GetPreviousPlan(examined_plan);
9240b57cec5SDimitry Andric
9250b57cec5SDimitry Andric if (stale) {
9269dba64beSDimitry Andric LLDB_LOGF(
9279dba64beSDimitry Andric log,
9280b57cec5SDimitry Andric "Plan %s being discarded in cleanup, it says it is already done.",
9290b57cec5SDimitry Andric examined_plan->GetName());
9300b57cec5SDimitry Andric while (GetCurrentPlan() != examined_plan) {
9310b57cec5SDimitry Andric DiscardPlan();
9320b57cec5SDimitry Andric }
9330b57cec5SDimitry Andric if (examined_plan->IsPlanComplete()) {
9340b57cec5SDimitry Andric // plan is complete but does not explain the stop (example: step to a
9350b57cec5SDimitry Andric // line with breakpoint), let us move the plan to
9360b57cec5SDimitry Andric // completed_plan_stack anyway
9370b57cec5SDimitry Andric PopPlan();
9380b57cec5SDimitry Andric } else
9390b57cec5SDimitry Andric DiscardPlan();
9400b57cec5SDimitry Andric }
9410b57cec5SDimitry Andric }
9420b57cec5SDimitry Andric }
9430b57cec5SDimitry Andric
9440b57cec5SDimitry Andric if (log) {
9450b57cec5SDimitry Andric StreamString s;
9460b57cec5SDimitry Andric s.IndentMore();
9475ffd83dbSDimitry Andric GetProcess()->DumpThreadPlansForTID(
9485ffd83dbSDimitry Andric s, GetID(), eDescriptionLevelVerbose, true /* internal */,
9495ffd83dbSDimitry Andric false /* condense_trivial */, true /* skip_unreported */);
9509dba64beSDimitry Andric LLDB_LOGF(log, "Plan stack final state:\n%s", s.GetData());
9519dba64beSDimitry Andric LLDB_LOGF(log, "vvvvvvvv Thread::ShouldStop End (returning %i) vvvvvvvv",
9520b57cec5SDimitry Andric should_stop);
9530b57cec5SDimitry Andric }
9540b57cec5SDimitry Andric return should_stop;
9550b57cec5SDimitry Andric }
9560b57cec5SDimitry Andric
ShouldReportStop(Event * event_ptr)9570b57cec5SDimitry Andric Vote Thread::ShouldReportStop(Event *event_ptr) {
9580b57cec5SDimitry Andric StateType thread_state = GetResumeState();
9590b57cec5SDimitry Andric StateType temp_thread_state = GetTemporaryResumeState();
9600b57cec5SDimitry Andric
9610b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
9620b57cec5SDimitry Andric
9630b57cec5SDimitry Andric if (thread_state == eStateSuspended || thread_state == eStateInvalid) {
9649dba64beSDimitry Andric LLDB_LOGF(log,
9659dba64beSDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
9660b57cec5SDimitry Andric ": returning vote %i (state was suspended or invalid)",
9670b57cec5SDimitry Andric GetID(), eVoteNoOpinion);
9680b57cec5SDimitry Andric return eVoteNoOpinion;
9690b57cec5SDimitry Andric }
9700b57cec5SDimitry Andric
9710b57cec5SDimitry Andric if (temp_thread_state == eStateSuspended ||
9720b57cec5SDimitry Andric temp_thread_state == eStateInvalid) {
9739dba64beSDimitry Andric LLDB_LOGF(log,
9740b57cec5SDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
9750b57cec5SDimitry Andric ": returning vote %i (temporary state was suspended or invalid)",
9760b57cec5SDimitry Andric GetID(), eVoteNoOpinion);
9770b57cec5SDimitry Andric return eVoteNoOpinion;
9780b57cec5SDimitry Andric }
9790b57cec5SDimitry Andric
9800b57cec5SDimitry Andric if (!ThreadStoppedForAReason()) {
9819dba64beSDimitry Andric LLDB_LOGF(log,
9829dba64beSDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
9830b57cec5SDimitry Andric ": returning vote %i (thread didn't stop for a reason.)",
9840b57cec5SDimitry Andric GetID(), eVoteNoOpinion);
9850b57cec5SDimitry Andric return eVoteNoOpinion;
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric
9885ffd83dbSDimitry Andric if (GetPlans().AnyCompletedPlans()) {
9895ffd83dbSDimitry Andric // Pass skip_private = false to GetCompletedPlan, since we want to ask
9905ffd83dbSDimitry Andric // the last plan, regardless of whether it is private or not.
9919dba64beSDimitry Andric LLDB_LOGF(log,
9929dba64beSDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
9930b57cec5SDimitry Andric ": returning vote for complete stack's back plan",
9940b57cec5SDimitry Andric GetID());
9955ffd83dbSDimitry Andric return GetPlans().GetCompletedPlan(false)->ShouldReportStop(event_ptr);
9960b57cec5SDimitry Andric } else {
9970b57cec5SDimitry Andric Vote thread_vote = eVoteNoOpinion;
9980b57cec5SDimitry Andric ThreadPlan *plan_ptr = GetCurrentPlan();
9990b57cec5SDimitry Andric while (true) {
10000b57cec5SDimitry Andric if (plan_ptr->PlanExplainsStop(event_ptr)) {
10010b57cec5SDimitry Andric thread_vote = plan_ptr->ShouldReportStop(event_ptr);
10020b57cec5SDimitry Andric break;
10030b57cec5SDimitry Andric }
10045ffd83dbSDimitry Andric if (plan_ptr->IsBasePlan())
10050b57cec5SDimitry Andric break;
10060b57cec5SDimitry Andric else
10070b57cec5SDimitry Andric plan_ptr = GetPreviousPlan(plan_ptr);
10080b57cec5SDimitry Andric }
10099dba64beSDimitry Andric LLDB_LOGF(log,
10109dba64beSDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
10110b57cec5SDimitry Andric ": returning vote %i for current plan",
10120b57cec5SDimitry Andric GetID(), thread_vote);
10130b57cec5SDimitry Andric
10140b57cec5SDimitry Andric return thread_vote;
10150b57cec5SDimitry Andric }
10160b57cec5SDimitry Andric }
10170b57cec5SDimitry Andric
ShouldReportRun(Event * event_ptr)10180b57cec5SDimitry Andric Vote Thread::ShouldReportRun(Event *event_ptr) {
10190b57cec5SDimitry Andric StateType thread_state = GetResumeState();
10200b57cec5SDimitry Andric
10210b57cec5SDimitry Andric if (thread_state == eStateSuspended || thread_state == eStateInvalid) {
10220b57cec5SDimitry Andric return eVoteNoOpinion;
10230b57cec5SDimitry Andric }
10240b57cec5SDimitry Andric
10250b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
10265ffd83dbSDimitry Andric if (GetPlans().AnyCompletedPlans()) {
10275ffd83dbSDimitry Andric // Pass skip_private = false to GetCompletedPlan, since we want to ask
10285ffd83dbSDimitry Andric // the last plan, regardless of whether it is private or not.
10299dba64beSDimitry Andric LLDB_LOGF(log,
10309dba64beSDimitry Andric "Current Plan for thread %d(%p) (0x%4.4" PRIx64
10310b57cec5SDimitry Andric ", %s): %s being asked whether we should report run.",
10320b57cec5SDimitry Andric GetIndexID(), static_cast<void *>(this), GetID(),
10330b57cec5SDimitry Andric StateAsCString(GetTemporaryResumeState()),
10345ffd83dbSDimitry Andric GetCompletedPlan()->GetName());
10350b57cec5SDimitry Andric
10365ffd83dbSDimitry Andric return GetPlans().GetCompletedPlan(false)->ShouldReportRun(event_ptr);
10370b57cec5SDimitry Andric } else {
10389dba64beSDimitry Andric LLDB_LOGF(log,
10399dba64beSDimitry Andric "Current Plan for thread %d(%p) (0x%4.4" PRIx64
10400b57cec5SDimitry Andric ", %s): %s being asked whether we should report run.",
10410b57cec5SDimitry Andric GetIndexID(), static_cast<void *>(this), GetID(),
10420b57cec5SDimitry Andric StateAsCString(GetTemporaryResumeState()),
10430b57cec5SDimitry Andric GetCurrentPlan()->GetName());
10440b57cec5SDimitry Andric
10450b57cec5SDimitry Andric return GetCurrentPlan()->ShouldReportRun(event_ptr);
10460b57cec5SDimitry Andric }
10470b57cec5SDimitry Andric }
10480b57cec5SDimitry Andric
MatchesSpec(const ThreadSpec * spec)10490b57cec5SDimitry Andric bool Thread::MatchesSpec(const ThreadSpec *spec) {
10500b57cec5SDimitry Andric return (spec == nullptr) ? true : spec->ThreadPassesBasicTests(*this);
10510b57cec5SDimitry Andric }
10520b57cec5SDimitry Andric
GetPlans() const10535ffd83dbSDimitry Andric ThreadPlanStack &Thread::GetPlans() const {
10545ffd83dbSDimitry Andric ThreadPlanStack *plans = GetProcess()->FindThreadPlans(GetID());
10555ffd83dbSDimitry Andric if (plans)
10565ffd83dbSDimitry Andric return *plans;
10570b57cec5SDimitry Andric
10585ffd83dbSDimitry Andric // History threads don't have a thread plan, but they do ask get asked to
10595ffd83dbSDimitry Andric // describe themselves, which usually involves pulling out the stop reason.
10605ffd83dbSDimitry Andric // That in turn will check for a completed plan on the ThreadPlanStack.
10615ffd83dbSDimitry Andric // Instead of special-casing at that point, we return a Stack with a
10625ffd83dbSDimitry Andric // ThreadPlanNull as its base plan. That will give the right answers to the
10635ffd83dbSDimitry Andric // queries GetDescription makes, and only assert if you try to run the thread.
10645ffd83dbSDimitry Andric if (!m_null_plan_stack_up)
10655ffd83dbSDimitry Andric m_null_plan_stack_up = std::make_unique<ThreadPlanStack>(*this, true);
10665ffd83dbSDimitry Andric return *(m_null_plan_stack_up.get());
10675ffd83dbSDimitry Andric }
10685ffd83dbSDimitry Andric
PushPlan(ThreadPlanSP thread_plan_sp)10695ffd83dbSDimitry Andric void Thread::PushPlan(ThreadPlanSP thread_plan_sp) {
10705ffd83dbSDimitry Andric assert(thread_plan_sp && "Don't push an empty thread plan.");
10710b57cec5SDimitry Andric
10720b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
10730b57cec5SDimitry Andric if (log) {
10740b57cec5SDimitry Andric StreamString s;
10750b57cec5SDimitry Andric thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull);
10769dba64beSDimitry Andric LLDB_LOGF(log, "Thread::PushPlan(0x%p): \"%s\", tid = 0x%4.4" PRIx64 ".",
10770b57cec5SDimitry Andric static_cast<void *>(this), s.GetData(),
10780b57cec5SDimitry Andric thread_plan_sp->GetThread().GetID());
10790b57cec5SDimitry Andric }
10805ffd83dbSDimitry Andric
10815ffd83dbSDimitry Andric GetPlans().PushPlan(std::move(thread_plan_sp));
10820b57cec5SDimitry Andric }
10830b57cec5SDimitry Andric
PopPlan()10840b57cec5SDimitry Andric void Thread::PopPlan() {
10850b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
10865ffd83dbSDimitry Andric ThreadPlanSP popped_plan_sp = GetPlans().PopPlan();
10870b57cec5SDimitry Andric if (log) {
10889dba64beSDimitry Andric LLDB_LOGF(log, "Popping plan: \"%s\", tid = 0x%4.4" PRIx64 ".",
10895ffd83dbSDimitry Andric popped_plan_sp->GetName(), popped_plan_sp->GetThread().GetID());
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric }
10920b57cec5SDimitry Andric
DiscardPlan()10930b57cec5SDimitry Andric void Thread::DiscardPlan() {
10940b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
10955ffd83dbSDimitry Andric ThreadPlanSP discarded_plan_sp = GetPlans().PopPlan();
10965ffd83dbSDimitry Andric
10979dba64beSDimitry Andric LLDB_LOGF(log, "Discarding plan: \"%s\", tid = 0x%4.4" PRIx64 ".",
10985ffd83dbSDimitry Andric discarded_plan_sp->GetName(),
10995ffd83dbSDimitry Andric discarded_plan_sp->GetThread().GetID());
11000b57cec5SDimitry Andric }
11010b57cec5SDimitry Andric
AutoCompleteThreadPlans(CompletionRequest & request) const1102af732203SDimitry Andric void Thread::AutoCompleteThreadPlans(CompletionRequest &request) const {
1103af732203SDimitry Andric const ThreadPlanStack &plans = GetPlans();
1104af732203SDimitry Andric if (!plans.AnyPlans())
1105af732203SDimitry Andric return;
1106af732203SDimitry Andric
1107af732203SDimitry Andric // Iterate from the second plan (index: 1) to skip the base plan.
1108af732203SDimitry Andric ThreadPlanSP p;
1109af732203SDimitry Andric uint32_t i = 1;
1110af732203SDimitry Andric while ((p = plans.GetPlanByIndex(i, false))) {
1111af732203SDimitry Andric StreamString strm;
1112af732203SDimitry Andric p->GetDescription(&strm, eDescriptionLevelInitial);
1113af732203SDimitry Andric request.TryCompleteCurrentArg(std::to_string(i), strm.GetString());
1114af732203SDimitry Andric i++;
1115af732203SDimitry Andric }
1116af732203SDimitry Andric }
1117af732203SDimitry Andric
GetCurrentPlan() const11185ffd83dbSDimitry Andric ThreadPlan *Thread::GetCurrentPlan() const {
11195ffd83dbSDimitry Andric return GetPlans().GetCurrentPlan().get();
11200b57cec5SDimitry Andric }
11210b57cec5SDimitry Andric
GetCompletedPlan() const11225ffd83dbSDimitry Andric ThreadPlanSP Thread::GetCompletedPlan() const {
11235ffd83dbSDimitry Andric return GetPlans().GetCompletedPlan();
11240b57cec5SDimitry Andric }
11250b57cec5SDimitry Andric
GetReturnValueObject() const11265ffd83dbSDimitry Andric ValueObjectSP Thread::GetReturnValueObject() const {
11275ffd83dbSDimitry Andric return GetPlans().GetReturnValueObject();
11280b57cec5SDimitry Andric }
11290b57cec5SDimitry Andric
GetExpressionVariable() const11305ffd83dbSDimitry Andric ExpressionVariableSP Thread::GetExpressionVariable() const {
11315ffd83dbSDimitry Andric return GetPlans().GetExpressionVariable();
11320b57cec5SDimitry Andric }
11330b57cec5SDimitry Andric
IsThreadPlanDone(ThreadPlan * plan) const11345ffd83dbSDimitry Andric bool Thread::IsThreadPlanDone(ThreadPlan *plan) const {
11355ffd83dbSDimitry Andric return GetPlans().IsPlanDone(plan);
11360b57cec5SDimitry Andric }
11370b57cec5SDimitry Andric
WasThreadPlanDiscarded(ThreadPlan * plan) const11385ffd83dbSDimitry Andric bool Thread::WasThreadPlanDiscarded(ThreadPlan *plan) const {
11395ffd83dbSDimitry Andric return GetPlans().WasPlanDiscarded(plan);
11400b57cec5SDimitry Andric }
11410b57cec5SDimitry Andric
CompletedPlanOverridesBreakpoint() const11425ffd83dbSDimitry Andric bool Thread::CompletedPlanOverridesBreakpoint() const {
11435ffd83dbSDimitry Andric return GetPlans().AnyCompletedPlans();
11440b57cec5SDimitry Andric }
11450b57cec5SDimitry Andric
GetPreviousPlan(ThreadPlan * current_plan) const11465ffd83dbSDimitry Andric ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) const{
11475ffd83dbSDimitry Andric return GetPlans().GetPreviousPlan(current_plan);
11480b57cec5SDimitry Andric }
11490b57cec5SDimitry Andric
QueueThreadPlan(ThreadPlanSP & thread_plan_sp,bool abort_other_plans)11500b57cec5SDimitry Andric Status Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp,
11510b57cec5SDimitry Andric bool abort_other_plans) {
11520b57cec5SDimitry Andric Status status;
11530b57cec5SDimitry Andric StreamString s;
11540b57cec5SDimitry Andric if (!thread_plan_sp->ValidatePlan(&s)) {
11550b57cec5SDimitry Andric DiscardThreadPlansUpToPlan(thread_plan_sp);
11560b57cec5SDimitry Andric thread_plan_sp.reset();
11570b57cec5SDimitry Andric status.SetErrorString(s.GetString());
11580b57cec5SDimitry Andric return status;
11590b57cec5SDimitry Andric }
11600b57cec5SDimitry Andric
11610b57cec5SDimitry Andric if (abort_other_plans)
11620b57cec5SDimitry Andric DiscardThreadPlans(true);
11630b57cec5SDimitry Andric
11640b57cec5SDimitry Andric PushPlan(thread_plan_sp);
11650b57cec5SDimitry Andric
11660b57cec5SDimitry Andric // This seems a little funny, but I don't want to have to split up the
11670b57cec5SDimitry Andric // constructor and the DidPush in the scripted plan, that seems annoying.
11680b57cec5SDimitry Andric // That means the constructor has to be in DidPush. So I have to validate the
11690b57cec5SDimitry Andric // plan AFTER pushing it, and then take it off again...
11700b57cec5SDimitry Andric if (!thread_plan_sp->ValidatePlan(&s)) {
11710b57cec5SDimitry Andric DiscardThreadPlansUpToPlan(thread_plan_sp);
11720b57cec5SDimitry Andric thread_plan_sp.reset();
11730b57cec5SDimitry Andric status.SetErrorString(s.GetString());
11740b57cec5SDimitry Andric return status;
11750b57cec5SDimitry Andric }
11760b57cec5SDimitry Andric
11770b57cec5SDimitry Andric return status;
11780b57cec5SDimitry Andric }
11790b57cec5SDimitry Andric
DiscardUserThreadPlansUpToIndex(uint32_t plan_index)11805ffd83dbSDimitry Andric bool Thread::DiscardUserThreadPlansUpToIndex(uint32_t plan_index) {
11810b57cec5SDimitry Andric // Count the user thread plans from the back end to get the number of the one
11820b57cec5SDimitry Andric // we want to discard:
11830b57cec5SDimitry Andric
11845ffd83dbSDimitry Andric ThreadPlan *up_to_plan_ptr = GetPlans().GetPlanByIndex(plan_index).get();
11850b57cec5SDimitry Andric if (up_to_plan_ptr == nullptr)
11860b57cec5SDimitry Andric return false;
11870b57cec5SDimitry Andric
11880b57cec5SDimitry Andric DiscardThreadPlansUpToPlan(up_to_plan_ptr);
11890b57cec5SDimitry Andric return true;
11900b57cec5SDimitry Andric }
11910b57cec5SDimitry Andric
DiscardThreadPlansUpToPlan(lldb::ThreadPlanSP & up_to_plan_sp)11920b57cec5SDimitry Andric void Thread::DiscardThreadPlansUpToPlan(lldb::ThreadPlanSP &up_to_plan_sp) {
11930b57cec5SDimitry Andric DiscardThreadPlansUpToPlan(up_to_plan_sp.get());
11940b57cec5SDimitry Andric }
11950b57cec5SDimitry Andric
DiscardThreadPlansUpToPlan(ThreadPlan * up_to_plan_ptr)11960b57cec5SDimitry Andric void Thread::DiscardThreadPlansUpToPlan(ThreadPlan *up_to_plan_ptr) {
11970b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
11989dba64beSDimitry Andric LLDB_LOGF(log,
11999dba64beSDimitry Andric "Discarding thread plans for thread tid = 0x%4.4" PRIx64
12000b57cec5SDimitry Andric ", up to %p",
12010b57cec5SDimitry Andric GetID(), static_cast<void *>(up_to_plan_ptr));
12025ffd83dbSDimitry Andric GetPlans().DiscardPlansUpToPlan(up_to_plan_ptr);
12030b57cec5SDimitry Andric }
12040b57cec5SDimitry Andric
DiscardThreadPlans(bool force)12050b57cec5SDimitry Andric void Thread::DiscardThreadPlans(bool force) {
12060b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
12070b57cec5SDimitry Andric if (log) {
12089dba64beSDimitry Andric LLDB_LOGF(log,
12099dba64beSDimitry Andric "Discarding thread plans for thread (tid = 0x%4.4" PRIx64
12100b57cec5SDimitry Andric ", force %d)",
12110b57cec5SDimitry Andric GetID(), force);
12120b57cec5SDimitry Andric }
12130b57cec5SDimitry Andric
12140b57cec5SDimitry Andric if (force) {
12155ffd83dbSDimitry Andric GetPlans().DiscardAllPlans();
12160b57cec5SDimitry Andric return;
12170b57cec5SDimitry Andric }
12185ffd83dbSDimitry Andric GetPlans().DiscardConsultingMasterPlans();
12190b57cec5SDimitry Andric }
12200b57cec5SDimitry Andric
UnwindInnermostExpression()12210b57cec5SDimitry Andric Status Thread::UnwindInnermostExpression() {
12220b57cec5SDimitry Andric Status error;
12235ffd83dbSDimitry Andric ThreadPlan *innermost_expr_plan = GetPlans().GetInnermostExpression();
12245ffd83dbSDimitry Andric if (!innermost_expr_plan) {
12255ffd83dbSDimitry Andric error.SetErrorString("No expressions currently active on this thread");
12260b57cec5SDimitry Andric return error;
12270b57cec5SDimitry Andric }
12285ffd83dbSDimitry Andric DiscardThreadPlansUpToPlan(innermost_expr_plan);
12290b57cec5SDimitry Andric return error;
12300b57cec5SDimitry Andric }
12310b57cec5SDimitry Andric
QueueBasePlan(bool abort_other_plans)1232*5f7ddb14SDimitry Andric ThreadPlanSP Thread::QueueBasePlan(bool abort_other_plans) {
12330b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanBase(*this));
12340b57cec5SDimitry Andric QueueThreadPlan(thread_plan_sp, abort_other_plans);
12350b57cec5SDimitry Andric return thread_plan_sp;
12360b57cec5SDimitry Andric }
12370b57cec5SDimitry Andric
QueueThreadPlanForStepSingleInstruction(bool step_over,bool abort_other_plans,bool stop_other_threads,Status & status)12380b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction(
12390b57cec5SDimitry Andric bool step_over, bool abort_other_plans, bool stop_other_threads,
12400b57cec5SDimitry Andric Status &status) {
12410b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepInstruction(
12420b57cec5SDimitry Andric *this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
12430b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
12440b57cec5SDimitry Andric return thread_plan_sp;
12450b57cec5SDimitry Andric }
12460b57cec5SDimitry Andric
QueueThreadPlanForStepOverRange(bool abort_other_plans,const AddressRange & range,const SymbolContext & addr_context,lldb::RunMode stop_other_threads,Status & status,LazyBool step_out_avoids_code_withoug_debug_info)12470b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
12480b57cec5SDimitry Andric bool abort_other_plans, const AddressRange &range,
12490b57cec5SDimitry Andric const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
12500b57cec5SDimitry Andric Status &status, LazyBool step_out_avoids_code_withoug_debug_info) {
12510b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp;
12520b57cec5SDimitry Andric thread_plan_sp = std::make_shared<ThreadPlanStepOverRange>(
12530b57cec5SDimitry Andric *this, range, addr_context, stop_other_threads,
12540b57cec5SDimitry Andric step_out_avoids_code_withoug_debug_info);
12550b57cec5SDimitry Andric
12560b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
12570b57cec5SDimitry Andric return thread_plan_sp;
12580b57cec5SDimitry Andric }
12590b57cec5SDimitry Andric
12600b57cec5SDimitry Andric // Call the QueueThreadPlanForStepOverRange method which takes an address
12610b57cec5SDimitry Andric // range.
QueueThreadPlanForStepOverRange(bool abort_other_plans,const LineEntry & line_entry,const SymbolContext & addr_context,lldb::RunMode stop_other_threads,Status & status,LazyBool step_out_avoids_code_withoug_debug_info)12620b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
12630b57cec5SDimitry Andric bool abort_other_plans, const LineEntry &line_entry,
12640b57cec5SDimitry Andric const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
12650b57cec5SDimitry Andric Status &status, LazyBool step_out_avoids_code_withoug_debug_info) {
12660b57cec5SDimitry Andric const bool include_inlined_functions = true;
12670b57cec5SDimitry Andric auto address_range =
12680b57cec5SDimitry Andric line_entry.GetSameLineContiguousAddressRange(include_inlined_functions);
12690b57cec5SDimitry Andric return QueueThreadPlanForStepOverRange(
12700b57cec5SDimitry Andric abort_other_plans, address_range, addr_context, stop_other_threads,
12710b57cec5SDimitry Andric status, step_out_avoids_code_withoug_debug_info);
12720b57cec5SDimitry Andric }
12730b57cec5SDimitry Andric
QueueThreadPlanForStepInRange(bool abort_other_plans,const AddressRange & range,const SymbolContext & addr_context,const char * step_in_target,lldb::RunMode stop_other_threads,Status & status,LazyBool step_in_avoids_code_without_debug_info,LazyBool step_out_avoids_code_without_debug_info)12740b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
12750b57cec5SDimitry Andric bool abort_other_plans, const AddressRange &range,
12760b57cec5SDimitry Andric const SymbolContext &addr_context, const char *step_in_target,
12770b57cec5SDimitry Andric lldb::RunMode stop_other_threads, Status &status,
12780b57cec5SDimitry Andric LazyBool step_in_avoids_code_without_debug_info,
12790b57cec5SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) {
1280*5f7ddb14SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepInRange(
1281*5f7ddb14SDimitry Andric *this, range, addr_context, step_in_target, stop_other_threads,
12820b57cec5SDimitry Andric step_in_avoids_code_without_debug_info,
12830b57cec5SDimitry Andric step_out_avoids_code_without_debug_info));
12840b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
12850b57cec5SDimitry Andric return thread_plan_sp;
12860b57cec5SDimitry Andric }
12870b57cec5SDimitry Andric
12880b57cec5SDimitry Andric // Call the QueueThreadPlanForStepInRange method which takes an address range.
QueueThreadPlanForStepInRange(bool abort_other_plans,const LineEntry & line_entry,const SymbolContext & addr_context,const char * step_in_target,lldb::RunMode stop_other_threads,Status & status,LazyBool step_in_avoids_code_without_debug_info,LazyBool step_out_avoids_code_without_debug_info)12890b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
12900b57cec5SDimitry Andric bool abort_other_plans, const LineEntry &line_entry,
12910b57cec5SDimitry Andric const SymbolContext &addr_context, const char *step_in_target,
12920b57cec5SDimitry Andric lldb::RunMode stop_other_threads, Status &status,
12930b57cec5SDimitry Andric LazyBool step_in_avoids_code_without_debug_info,
12940b57cec5SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) {
12950b57cec5SDimitry Andric const bool include_inlined_functions = false;
12960b57cec5SDimitry Andric return QueueThreadPlanForStepInRange(
12970b57cec5SDimitry Andric abort_other_plans,
12980b57cec5SDimitry Andric line_entry.GetSameLineContiguousAddressRange(include_inlined_functions),
12990b57cec5SDimitry Andric addr_context, step_in_target, stop_other_threads, status,
13000b57cec5SDimitry Andric step_in_avoids_code_without_debug_info,
13010b57cec5SDimitry Andric step_out_avoids_code_without_debug_info);
13020b57cec5SDimitry Andric }
13030b57cec5SDimitry Andric
QueueThreadPlanForStepOut(bool abort_other_plans,SymbolContext * addr_context,bool first_insn,bool stop_other_threads,Vote report_stop_vote,Vote report_run_vote,uint32_t frame_idx,Status & status,LazyBool step_out_avoids_code_without_debug_info)13040b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepOut(
13050b57cec5SDimitry Andric bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
1306*5f7ddb14SDimitry Andric bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote,
1307*5f7ddb14SDimitry Andric uint32_t frame_idx, Status &status,
1308*5f7ddb14SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) {
13090b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
1310*5f7ddb14SDimitry Andric *this, addr_context, first_insn, stop_other_threads, report_stop_vote,
1311*5f7ddb14SDimitry Andric report_run_vote, frame_idx, step_out_avoids_code_without_debug_info));
13120b57cec5SDimitry Andric
13130b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
13140b57cec5SDimitry Andric return thread_plan_sp;
13150b57cec5SDimitry Andric }
13160b57cec5SDimitry Andric
QueueThreadPlanForStepOutNoShouldStop(bool abort_other_plans,SymbolContext * addr_context,bool first_insn,bool stop_other_threads,Vote report_stop_vote,Vote report_run_vote,uint32_t frame_idx,Status & status,bool continue_to_next_branch)13170b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepOutNoShouldStop(
13180b57cec5SDimitry Andric bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
1319*5f7ddb14SDimitry Andric bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote,
1320*5f7ddb14SDimitry Andric uint32_t frame_idx, Status &status, bool continue_to_next_branch) {
13210b57cec5SDimitry Andric const bool calculate_return_value =
13220b57cec5SDimitry Andric false; // No need to calculate the return value here.
13230b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
1324*5f7ddb14SDimitry Andric *this, addr_context, first_insn, stop_other_threads, report_stop_vote,
1325*5f7ddb14SDimitry Andric report_run_vote, frame_idx, eLazyBoolNo, continue_to_next_branch,
1326*5f7ddb14SDimitry Andric calculate_return_value));
13270b57cec5SDimitry Andric
13280b57cec5SDimitry Andric ThreadPlanStepOut *new_plan =
13290b57cec5SDimitry Andric static_cast<ThreadPlanStepOut *>(thread_plan_sp.get());
13300b57cec5SDimitry Andric new_plan->ClearShouldStopHereCallbacks();
13310b57cec5SDimitry Andric
13320b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
13330b57cec5SDimitry Andric return thread_plan_sp;
13340b57cec5SDimitry Andric }
13350b57cec5SDimitry Andric
QueueThreadPlanForStepThrough(StackID & return_stack_id,bool abort_other_plans,bool stop_other_threads,Status & status)13360b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepThrough(StackID &return_stack_id,
13370b57cec5SDimitry Andric bool abort_other_plans,
13380b57cec5SDimitry Andric bool stop_other_threads,
13390b57cec5SDimitry Andric Status &status) {
13400b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp(
13410b57cec5SDimitry Andric new ThreadPlanStepThrough(*this, return_stack_id, stop_other_threads));
13420b57cec5SDimitry Andric if (!thread_plan_sp || !thread_plan_sp->ValidatePlan(nullptr))
13430b57cec5SDimitry Andric return ThreadPlanSP();
13440b57cec5SDimitry Andric
13450b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
13460b57cec5SDimitry Andric return thread_plan_sp;
13470b57cec5SDimitry Andric }
13480b57cec5SDimitry Andric
QueueThreadPlanForRunToAddress(bool abort_other_plans,Address & target_addr,bool stop_other_threads,Status & status)13490b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForRunToAddress(bool abort_other_plans,
13500b57cec5SDimitry Andric Address &target_addr,
13510b57cec5SDimitry Andric bool stop_other_threads,
13520b57cec5SDimitry Andric Status &status) {
13530b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp(
13540b57cec5SDimitry Andric new ThreadPlanRunToAddress(*this, target_addr, stop_other_threads));
13550b57cec5SDimitry Andric
13560b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
13570b57cec5SDimitry Andric return thread_plan_sp;
13580b57cec5SDimitry Andric }
13590b57cec5SDimitry Andric
QueueThreadPlanForStepUntil(bool abort_other_plans,lldb::addr_t * address_list,size_t num_addresses,bool stop_other_threads,uint32_t frame_idx,Status & status)13600b57cec5SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepUntil(
13610b57cec5SDimitry Andric bool abort_other_plans, lldb::addr_t *address_list, size_t num_addresses,
13620b57cec5SDimitry Andric bool stop_other_threads, uint32_t frame_idx, Status &status) {
13630b57cec5SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepUntil(
13640b57cec5SDimitry Andric *this, address_list, num_addresses, stop_other_threads, frame_idx));
13650b57cec5SDimitry Andric
13660b57cec5SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
13670b57cec5SDimitry Andric return thread_plan_sp;
13680b57cec5SDimitry Andric }
13690b57cec5SDimitry Andric
QueueThreadPlanForStepScripted(bool abort_other_plans,const char * class_name,StructuredData::ObjectSP extra_args_sp,bool stop_other_threads,Status & status)13700b57cec5SDimitry Andric lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
13719dba64beSDimitry Andric bool abort_other_plans, const char *class_name,
13729dba64beSDimitry Andric StructuredData::ObjectSP extra_args_sp, bool stop_other_threads,
13730b57cec5SDimitry Andric Status &status) {
13749dba64beSDimitry Andric
13759dba64beSDimitry Andric StructuredDataImpl *extra_args_impl = nullptr;
13769dba64beSDimitry Andric if (extra_args_sp) {
13779dba64beSDimitry Andric extra_args_impl = new StructuredDataImpl();
13789dba64beSDimitry Andric extra_args_impl->SetObjectSP(extra_args_sp);
13799dba64beSDimitry Andric }
13809dba64beSDimitry Andric
13819dba64beSDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name,
13829dba64beSDimitry Andric extra_args_impl));
1383af732203SDimitry 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
GetIndexID() const13880b57cec5SDimitry Andric uint32_t Thread::GetIndexID() const { return m_index_id; }
13890b57cec5SDimitry Andric
CalculateTarget()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
CalculateProcess()13980b57cec5SDimitry Andric ProcessSP Thread::CalculateProcess() { return GetProcess(); }
13990b57cec5SDimitry Andric
CalculateThread()14000b57cec5SDimitry Andric ThreadSP Thread::CalculateThread() { return shared_from_this(); }
14010b57cec5SDimitry Andric
CalculateStackFrame()14020b57cec5SDimitry Andric StackFrameSP Thread::CalculateStackFrame() { return StackFrameSP(); }
14030b57cec5SDimitry Andric
CalculateExecutionContext(ExecutionContext & exe_ctx)14040b57cec5SDimitry Andric void Thread::CalculateExecutionContext(ExecutionContext &exe_ctx) {
14050b57cec5SDimitry Andric exe_ctx.SetContext(shared_from_this());
14060b57cec5SDimitry Andric }
14070b57cec5SDimitry Andric
GetStackFrameList()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
ClearStackFrames()14180b57cec5SDimitry Andric void Thread::ClearStackFrames() {
14190b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
14200b57cec5SDimitry Andric
14215ffd83dbSDimitry Andric GetUnwinder().Clear();
14220b57cec5SDimitry Andric
14230b57cec5SDimitry Andric // Only store away the old "reference" StackFrameList if we got all its
14240b57cec5SDimitry Andric // frames:
14250b57cec5SDimitry Andric // FIXME: At some point we can try to splice in the frames we have fetched
14260b57cec5SDimitry Andric // into
14270b57cec5SDimitry Andric // the new frame as we make it, but let's not try that now.
14280b57cec5SDimitry Andric if (m_curr_frames_sp && m_curr_frames_sp->GetAllFramesFetched())
14290b57cec5SDimitry Andric m_prev_frames_sp.swap(m_curr_frames_sp);
14300b57cec5SDimitry Andric m_curr_frames_sp.reset();
14310b57cec5SDimitry Andric
14320b57cec5SDimitry Andric m_extended_info.reset();
14330b57cec5SDimitry Andric m_extended_info_fetched = false;
14340b57cec5SDimitry Andric }
14350b57cec5SDimitry Andric
GetFrameWithConcreteFrameIndex(uint32_t unwind_idx)14360b57cec5SDimitry Andric lldb::StackFrameSP Thread::GetFrameWithConcreteFrameIndex(uint32_t unwind_idx) {
14370b57cec5SDimitry Andric return GetStackFrameList()->GetFrameWithConcreteFrameIndex(unwind_idx);
14380b57cec5SDimitry Andric }
14390b57cec5SDimitry Andric
ReturnFromFrameWithIndex(uint32_t frame_idx,lldb::ValueObjectSP return_value_sp,bool broadcast)14400b57cec5SDimitry Andric Status Thread::ReturnFromFrameWithIndex(uint32_t frame_idx,
14410b57cec5SDimitry Andric lldb::ValueObjectSP return_value_sp,
14420b57cec5SDimitry Andric bool broadcast) {
14430b57cec5SDimitry Andric StackFrameSP frame_sp = GetStackFrameAtIndex(frame_idx);
14440b57cec5SDimitry Andric Status return_error;
14450b57cec5SDimitry Andric
14460b57cec5SDimitry Andric if (!frame_sp) {
14470b57cec5SDimitry Andric return_error.SetErrorStringWithFormat(
14480b57cec5SDimitry Andric "Could not find frame with index %d in thread 0x%" PRIx64 ".",
14490b57cec5SDimitry Andric frame_idx, GetID());
14500b57cec5SDimitry Andric }
14510b57cec5SDimitry Andric
14520b57cec5SDimitry Andric return ReturnFromFrame(frame_sp, return_value_sp, broadcast);
14530b57cec5SDimitry Andric }
14540b57cec5SDimitry Andric
ReturnFromFrame(lldb::StackFrameSP frame_sp,lldb::ValueObjectSP return_value_sp,bool broadcast)14550b57cec5SDimitry Andric Status Thread::ReturnFromFrame(lldb::StackFrameSP frame_sp,
14560b57cec5SDimitry Andric lldb::ValueObjectSP return_value_sp,
14570b57cec5SDimitry Andric bool broadcast) {
14580b57cec5SDimitry Andric Status return_error;
14590b57cec5SDimitry Andric
14600b57cec5SDimitry Andric if (!frame_sp) {
14610b57cec5SDimitry Andric return_error.SetErrorString("Can't return to a null frame.");
14620b57cec5SDimitry Andric return return_error;
14630b57cec5SDimitry Andric }
14640b57cec5SDimitry Andric
14650b57cec5SDimitry Andric Thread *thread = frame_sp->GetThread().get();
14660b57cec5SDimitry Andric uint32_t older_frame_idx = frame_sp->GetFrameIndex() + 1;
14670b57cec5SDimitry Andric StackFrameSP older_frame_sp = thread->GetStackFrameAtIndex(older_frame_idx);
14680b57cec5SDimitry Andric if (!older_frame_sp) {
14690b57cec5SDimitry Andric return_error.SetErrorString("No older frame to return to.");
14700b57cec5SDimitry Andric return return_error;
14710b57cec5SDimitry Andric }
14720b57cec5SDimitry Andric
14730b57cec5SDimitry Andric if (return_value_sp) {
14740b57cec5SDimitry Andric lldb::ABISP abi = thread->GetProcess()->GetABI();
14750b57cec5SDimitry Andric if (!abi) {
14760b57cec5SDimitry Andric return_error.SetErrorString("Could not find ABI to set return value.");
14770b57cec5SDimitry Andric return return_error;
14780b57cec5SDimitry Andric }
14790b57cec5SDimitry Andric SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextFunction);
14800b57cec5SDimitry Andric
14810b57cec5SDimitry Andric // FIXME: ValueObject::Cast doesn't currently work correctly, at least not
14820b57cec5SDimitry Andric // for scalars.
14830b57cec5SDimitry Andric // Turn that back on when that works.
14840b57cec5SDimitry Andric if (/* DISABLES CODE */ (false) && sc.function != nullptr) {
14850b57cec5SDimitry Andric Type *function_type = sc.function->GetType();
14860b57cec5SDimitry Andric if (function_type) {
14870b57cec5SDimitry Andric CompilerType return_type =
14880b57cec5SDimitry Andric sc.function->GetCompilerType().GetFunctionReturnType();
14890b57cec5SDimitry Andric if (return_type) {
14900b57cec5SDimitry Andric StreamString s;
14910b57cec5SDimitry Andric return_type.DumpTypeDescription(&s);
14920b57cec5SDimitry Andric ValueObjectSP cast_value_sp = return_value_sp->Cast(return_type);
14930b57cec5SDimitry Andric if (cast_value_sp) {
14940b57cec5SDimitry Andric cast_value_sp->SetFormat(eFormatHex);
14950b57cec5SDimitry Andric return_value_sp = cast_value_sp;
14960b57cec5SDimitry Andric }
14970b57cec5SDimitry Andric }
14980b57cec5SDimitry Andric }
14990b57cec5SDimitry Andric }
15000b57cec5SDimitry Andric
15010b57cec5SDimitry Andric return_error = abi->SetReturnValueObject(older_frame_sp, return_value_sp);
15020b57cec5SDimitry Andric if (!return_error.Success())
15030b57cec5SDimitry Andric return return_error;
15040b57cec5SDimitry Andric }
15050b57cec5SDimitry Andric
15060b57cec5SDimitry Andric // Now write the return registers for the chosen frame: Note, we can't use
15070b57cec5SDimitry Andric // ReadAllRegisterValues->WriteAllRegisterValues, since the read & write cook
15080b57cec5SDimitry Andric // their data
15090b57cec5SDimitry Andric
15100b57cec5SDimitry Andric StackFrameSP youngest_frame_sp = thread->GetStackFrameAtIndex(0);
15110b57cec5SDimitry Andric if (youngest_frame_sp) {
15120b57cec5SDimitry Andric lldb::RegisterContextSP reg_ctx_sp(youngest_frame_sp->GetRegisterContext());
15130b57cec5SDimitry Andric if (reg_ctx_sp) {
15140b57cec5SDimitry Andric bool copy_success = reg_ctx_sp->CopyFromRegisterContext(
15150b57cec5SDimitry Andric older_frame_sp->GetRegisterContext());
15160b57cec5SDimitry Andric if (copy_success) {
15170b57cec5SDimitry Andric thread->DiscardThreadPlans(true);
15180b57cec5SDimitry Andric thread->ClearStackFrames();
15190b57cec5SDimitry Andric if (broadcast && EventTypeHasListeners(eBroadcastBitStackChanged))
15200b57cec5SDimitry Andric BroadcastEvent(eBroadcastBitStackChanged,
15210b57cec5SDimitry Andric new ThreadEventData(this->shared_from_this()));
15220b57cec5SDimitry Andric } else {
15230b57cec5SDimitry Andric return_error.SetErrorString("Could not reset register values.");
15240b57cec5SDimitry Andric }
15250b57cec5SDimitry Andric } else {
15260b57cec5SDimitry Andric return_error.SetErrorString("Frame has no register context.");
15270b57cec5SDimitry Andric }
15280b57cec5SDimitry Andric } else {
15290b57cec5SDimitry Andric return_error.SetErrorString("Returned past top frame.");
15300b57cec5SDimitry Andric }
15310b57cec5SDimitry Andric return return_error;
15320b57cec5SDimitry Andric }
15330b57cec5SDimitry Andric
DumpAddressList(Stream & s,const std::vector<Address> & list,ExecutionContextScope * exe_scope)15340b57cec5SDimitry Andric static void DumpAddressList(Stream &s, const std::vector<Address> &list,
15350b57cec5SDimitry Andric ExecutionContextScope *exe_scope) {
15360b57cec5SDimitry Andric for (size_t n = 0; n < list.size(); n++) {
15370b57cec5SDimitry Andric s << "\t";
15380b57cec5SDimitry Andric list[n].Dump(&s, exe_scope, Address::DumpStyleResolvedDescription,
15390b57cec5SDimitry Andric Address::DumpStyleSectionNameOffset);
15400b57cec5SDimitry Andric s << "\n";
15410b57cec5SDimitry Andric }
15420b57cec5SDimitry Andric }
15430b57cec5SDimitry Andric
JumpToLine(const FileSpec & file,uint32_t line,bool can_leave_function,std::string * warnings)15440b57cec5SDimitry Andric Status Thread::JumpToLine(const FileSpec &file, uint32_t line,
15450b57cec5SDimitry Andric bool can_leave_function, std::string *warnings) {
15460b57cec5SDimitry Andric ExecutionContext exe_ctx(GetStackFrameAtIndex(0));
15470b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr();
15480b57cec5SDimitry Andric TargetSP target_sp = exe_ctx.GetTargetSP();
15490b57cec5SDimitry Andric RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
15500b57cec5SDimitry Andric StackFrame *frame = exe_ctx.GetFramePtr();
15510b57cec5SDimitry Andric const SymbolContext &sc = frame->GetSymbolContext(eSymbolContextFunction);
15520b57cec5SDimitry Andric
15530b57cec5SDimitry Andric // Find candidate locations.
15540b57cec5SDimitry Andric std::vector<Address> candidates, within_function, outside_function;
15550b57cec5SDimitry Andric target->GetImages().FindAddressesForLine(target_sp, file, line, sc.function,
15560b57cec5SDimitry Andric within_function, outside_function);
15570b57cec5SDimitry Andric
15580b57cec5SDimitry Andric // If possible, we try and stay within the current function. Within a
15590b57cec5SDimitry Andric // function, we accept multiple locations (optimized code may do this,
15600b57cec5SDimitry Andric // there's no solution here so we do the best we can). However if we're
15610b57cec5SDimitry Andric // trying to leave the function, we don't know how to pick the right
15620b57cec5SDimitry Andric // location, so if there's more than one then we bail.
15630b57cec5SDimitry Andric if (!within_function.empty())
15640b57cec5SDimitry Andric candidates = within_function;
15650b57cec5SDimitry Andric else if (outside_function.size() == 1 && can_leave_function)
15660b57cec5SDimitry Andric candidates = outside_function;
15670b57cec5SDimitry Andric
15680b57cec5SDimitry Andric // Check if we got anything.
15690b57cec5SDimitry Andric if (candidates.empty()) {
15700b57cec5SDimitry Andric if (outside_function.empty()) {
15710b57cec5SDimitry Andric return Status("Cannot locate an address for %s:%i.",
15720b57cec5SDimitry Andric file.GetFilename().AsCString(), line);
15730b57cec5SDimitry Andric } else if (outside_function.size() == 1) {
15740b57cec5SDimitry Andric return Status("%s:%i is outside the current function.",
15750b57cec5SDimitry Andric file.GetFilename().AsCString(), line);
15760b57cec5SDimitry Andric } else {
15770b57cec5SDimitry Andric StreamString sstr;
15780b57cec5SDimitry Andric DumpAddressList(sstr, outside_function, target);
15790b57cec5SDimitry Andric return Status("%s:%i has multiple candidate locations:\n%s",
15800b57cec5SDimitry Andric file.GetFilename().AsCString(), line, sstr.GetData());
15810b57cec5SDimitry Andric }
15820b57cec5SDimitry Andric }
15830b57cec5SDimitry Andric
15840b57cec5SDimitry Andric // Accept the first location, warn about any others.
15850b57cec5SDimitry Andric Address dest = candidates[0];
15860b57cec5SDimitry Andric if (warnings && candidates.size() > 1) {
15870b57cec5SDimitry Andric StreamString sstr;
15880b57cec5SDimitry Andric sstr.Printf("%s:%i appears multiple times in this function, selecting the "
15890b57cec5SDimitry Andric "first location:\n",
15900b57cec5SDimitry Andric file.GetFilename().AsCString(), line);
15910b57cec5SDimitry Andric DumpAddressList(sstr, candidates, target);
15925ffd83dbSDimitry Andric *warnings = std::string(sstr.GetString());
15930b57cec5SDimitry Andric }
15940b57cec5SDimitry Andric
15950b57cec5SDimitry Andric if (!reg_ctx->SetPC(dest))
15960b57cec5SDimitry Andric return Status("Cannot change PC to target address.");
15970b57cec5SDimitry Andric
15980b57cec5SDimitry Andric return Status();
15990b57cec5SDimitry Andric }
16000b57cec5SDimitry Andric
DumpUsingSettingsFormat(Stream & strm,uint32_t frame_idx,bool stop_format)16010b57cec5SDimitry Andric void Thread::DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx,
16020b57cec5SDimitry Andric bool stop_format) {
16030b57cec5SDimitry Andric ExecutionContext exe_ctx(shared_from_this());
16040b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr();
16050b57cec5SDimitry Andric if (process == nullptr)
16060b57cec5SDimitry Andric return;
16070b57cec5SDimitry Andric
16080b57cec5SDimitry Andric StackFrameSP frame_sp;
16090b57cec5SDimitry Andric SymbolContext frame_sc;
16100b57cec5SDimitry Andric if (frame_idx != LLDB_INVALID_FRAME_ID) {
16110b57cec5SDimitry Andric frame_sp = GetStackFrameAtIndex(frame_idx);
16120b57cec5SDimitry Andric if (frame_sp) {
16130b57cec5SDimitry Andric exe_ctx.SetFrameSP(frame_sp);
16140b57cec5SDimitry Andric frame_sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
16150b57cec5SDimitry Andric }
16160b57cec5SDimitry Andric }
16170b57cec5SDimitry Andric
16180b57cec5SDimitry Andric const FormatEntity::Entry *thread_format;
16190b57cec5SDimitry Andric if (stop_format)
16200b57cec5SDimitry Andric thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadStopFormat();
16210b57cec5SDimitry Andric else
16220b57cec5SDimitry Andric thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat();
16230b57cec5SDimitry Andric
16240b57cec5SDimitry Andric assert(thread_format);
16250b57cec5SDimitry Andric
16260b57cec5SDimitry Andric FormatEntity::Format(*thread_format, strm, frame_sp ? &frame_sc : nullptr,
16270b57cec5SDimitry Andric &exe_ctx, nullptr, nullptr, false, false);
16280b57cec5SDimitry Andric }
16290b57cec5SDimitry Andric
SettingsInitialize()16300b57cec5SDimitry Andric void Thread::SettingsInitialize() {}
16310b57cec5SDimitry Andric
SettingsTerminate()16320b57cec5SDimitry Andric void Thread::SettingsTerminate() {}
16330b57cec5SDimitry Andric
GetThreadPointer()16340b57cec5SDimitry Andric lldb::addr_t Thread::GetThreadPointer() { return LLDB_INVALID_ADDRESS; }
16350b57cec5SDimitry Andric
GetThreadLocalData(const ModuleSP module,lldb::addr_t tls_file_addr)16360b57cec5SDimitry Andric addr_t Thread::GetThreadLocalData(const ModuleSP module,
16370b57cec5SDimitry Andric lldb::addr_t tls_file_addr) {
16380b57cec5SDimitry Andric // The default implementation is to ask the dynamic loader for it. This can
16390b57cec5SDimitry Andric // be overridden for specific platforms.
16400b57cec5SDimitry Andric DynamicLoader *loader = GetProcess()->GetDynamicLoader();
16410b57cec5SDimitry Andric if (loader)
16420b57cec5SDimitry Andric return loader->GetThreadLocalData(module, shared_from_this(),
16430b57cec5SDimitry Andric tls_file_addr);
16440b57cec5SDimitry Andric else
16450b57cec5SDimitry Andric return LLDB_INVALID_ADDRESS;
16460b57cec5SDimitry Andric }
16470b57cec5SDimitry Andric
SafeToCallFunctions()16480b57cec5SDimitry Andric bool Thread::SafeToCallFunctions() {
16490b57cec5SDimitry Andric Process *process = GetProcess().get();
16500b57cec5SDimitry Andric if (process) {
16510b57cec5SDimitry Andric SystemRuntime *runtime = process->GetSystemRuntime();
16520b57cec5SDimitry Andric if (runtime) {
16530b57cec5SDimitry Andric return runtime->SafeToCallFunctionsOnThisThread(shared_from_this());
16540b57cec5SDimitry Andric }
16550b57cec5SDimitry Andric }
16560b57cec5SDimitry Andric return true;
16570b57cec5SDimitry Andric }
16580b57cec5SDimitry Andric
16590b57cec5SDimitry Andric lldb::StackFrameSP
GetStackFrameSPForStackFramePtr(StackFrame * stack_frame_ptr)16600b57cec5SDimitry Andric Thread::GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr) {
16610b57cec5SDimitry Andric return GetStackFrameList()->GetStackFrameSPForStackFramePtr(stack_frame_ptr);
16620b57cec5SDimitry Andric }
16630b57cec5SDimitry Andric
StopReasonAsString(lldb::StopReason reason)1664af732203SDimitry Andric std::string Thread::StopReasonAsString(lldb::StopReason reason) {
16650b57cec5SDimitry Andric switch (reason) {
16660b57cec5SDimitry Andric case eStopReasonInvalid:
16670b57cec5SDimitry Andric return "invalid";
16680b57cec5SDimitry Andric case eStopReasonNone:
16690b57cec5SDimitry Andric return "none";
16700b57cec5SDimitry Andric case eStopReasonTrace:
16710b57cec5SDimitry Andric return "trace";
16720b57cec5SDimitry Andric case eStopReasonBreakpoint:
16730b57cec5SDimitry Andric return "breakpoint";
16740b57cec5SDimitry Andric case eStopReasonWatchpoint:
16750b57cec5SDimitry Andric return "watchpoint";
16760b57cec5SDimitry Andric case eStopReasonSignal:
16770b57cec5SDimitry Andric return "signal";
16780b57cec5SDimitry Andric case eStopReasonException:
16790b57cec5SDimitry Andric return "exception";
16800b57cec5SDimitry Andric case eStopReasonExec:
16810b57cec5SDimitry Andric return "exec";
1682*5f7ddb14SDimitry Andric case eStopReasonFork:
1683*5f7ddb14SDimitry Andric return "fork";
1684*5f7ddb14SDimitry Andric case eStopReasonVFork:
1685*5f7ddb14SDimitry Andric return "vfork";
1686*5f7ddb14SDimitry Andric case eStopReasonVForkDone:
1687*5f7ddb14SDimitry Andric return "vfork done";
16880b57cec5SDimitry Andric case eStopReasonPlanComplete:
16890b57cec5SDimitry Andric return "plan complete";
16900b57cec5SDimitry Andric case eStopReasonThreadExiting:
16910b57cec5SDimitry Andric return "thread exiting";
16920b57cec5SDimitry Andric case eStopReasonInstrumentation:
16930b57cec5SDimitry Andric return "instrumentation break";
1694*5f7ddb14SDimitry Andric case eStopReasonProcessorTrace:
1695*5f7ddb14SDimitry Andric return "processor trace";
16960b57cec5SDimitry Andric }
16970b57cec5SDimitry Andric
1698af732203SDimitry Andric return "StopReason = " + std::to_string(reason);
16990b57cec5SDimitry Andric }
17000b57cec5SDimitry Andric
RunModeAsString(lldb::RunMode mode)1701af732203SDimitry Andric std::string Thread::RunModeAsString(lldb::RunMode mode) {
17020b57cec5SDimitry Andric switch (mode) {
17030b57cec5SDimitry Andric case eOnlyThisThread:
17040b57cec5SDimitry Andric return "only this thread";
17050b57cec5SDimitry Andric case eAllThreads:
17060b57cec5SDimitry Andric return "all threads";
17070b57cec5SDimitry Andric case eOnlyDuringStepping:
17080b57cec5SDimitry Andric return "only during stepping";
17090b57cec5SDimitry Andric }
17100b57cec5SDimitry Andric
1711af732203SDimitry Andric return "RunMode = " + std::to_string(mode);
17120b57cec5SDimitry Andric }
17130b57cec5SDimitry Andric
GetStatus(Stream & strm,uint32_t start_frame,uint32_t num_frames,uint32_t num_frames_with_source,bool stop_format,bool only_stacks)17140b57cec5SDimitry Andric size_t Thread::GetStatus(Stream &strm, uint32_t start_frame,
17150b57cec5SDimitry Andric uint32_t num_frames, uint32_t num_frames_with_source,
17160b57cec5SDimitry Andric bool stop_format, bool only_stacks) {
17170b57cec5SDimitry Andric
17180b57cec5SDimitry Andric if (!only_stacks) {
17190b57cec5SDimitry Andric ExecutionContext exe_ctx(shared_from_this());
17200b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr();
17210b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr();
17220b57cec5SDimitry Andric strm.Indent();
17230b57cec5SDimitry Andric bool is_selected = false;
17240b57cec5SDimitry Andric if (process) {
17250b57cec5SDimitry Andric if (process->GetThreadList().GetSelectedThread().get() == this)
17260b57cec5SDimitry Andric is_selected = true;
17270b57cec5SDimitry Andric }
17280b57cec5SDimitry Andric strm.Printf("%c ", is_selected ? '*' : ' ');
17290b57cec5SDimitry Andric if (target && target->GetDebugger().GetUseExternalEditor()) {
17300b57cec5SDimitry Andric StackFrameSP frame_sp = GetStackFrameAtIndex(start_frame);
17310b57cec5SDimitry Andric if (frame_sp) {
17320b57cec5SDimitry Andric SymbolContext frame_sc(
17330b57cec5SDimitry Andric frame_sp->GetSymbolContext(eSymbolContextLineEntry));
17340b57cec5SDimitry Andric if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.file) {
17350b57cec5SDimitry Andric Host::OpenFileInExternalEditor(frame_sc.line_entry.file,
17360b57cec5SDimitry Andric frame_sc.line_entry.line);
17370b57cec5SDimitry Andric }
17380b57cec5SDimitry Andric }
17390b57cec5SDimitry Andric }
17400b57cec5SDimitry Andric
17410b57cec5SDimitry Andric DumpUsingSettingsFormat(strm, start_frame, stop_format);
17420b57cec5SDimitry Andric }
17430b57cec5SDimitry Andric
17440b57cec5SDimitry Andric size_t num_frames_shown = 0;
17450b57cec5SDimitry Andric if (num_frames > 0) {
17460b57cec5SDimitry Andric strm.IndentMore();
17470b57cec5SDimitry Andric
17480b57cec5SDimitry Andric const bool show_frame_info = true;
17490b57cec5SDimitry Andric const bool show_frame_unique = only_stacks;
17500b57cec5SDimitry Andric const char *selected_frame_marker = nullptr;
17510b57cec5SDimitry Andric if (num_frames == 1 || only_stacks ||
17520b57cec5SDimitry Andric (GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID()))
17530b57cec5SDimitry Andric strm.IndentMore();
17540b57cec5SDimitry Andric else
17550b57cec5SDimitry Andric selected_frame_marker = "* ";
17560b57cec5SDimitry Andric
17570b57cec5SDimitry Andric num_frames_shown = GetStackFrameList()->GetStatus(
17580b57cec5SDimitry Andric strm, start_frame, num_frames, show_frame_info, num_frames_with_source,
17590b57cec5SDimitry Andric show_frame_unique, selected_frame_marker);
17600b57cec5SDimitry Andric if (num_frames == 1)
17610b57cec5SDimitry Andric strm.IndentLess();
17620b57cec5SDimitry Andric strm.IndentLess();
17630b57cec5SDimitry Andric }
17640b57cec5SDimitry Andric return num_frames_shown;
17650b57cec5SDimitry Andric }
17660b57cec5SDimitry Andric
GetDescription(Stream & strm,lldb::DescriptionLevel level,bool print_json_thread,bool print_json_stopinfo)17670b57cec5SDimitry Andric bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level,
17680b57cec5SDimitry Andric bool print_json_thread, bool print_json_stopinfo) {
17690b57cec5SDimitry Andric const bool stop_format = false;
17700b57cec5SDimitry Andric DumpUsingSettingsFormat(strm, 0, stop_format);
17710b57cec5SDimitry Andric strm.Printf("\n");
17720b57cec5SDimitry Andric
17730b57cec5SDimitry Andric StructuredData::ObjectSP thread_info = GetExtendedInfo();
17740b57cec5SDimitry Andric
17750b57cec5SDimitry Andric if (print_json_thread || print_json_stopinfo) {
17760b57cec5SDimitry Andric if (thread_info && print_json_thread) {
17770b57cec5SDimitry Andric thread_info->Dump(strm);
17780b57cec5SDimitry Andric strm.Printf("\n");
17790b57cec5SDimitry Andric }
17800b57cec5SDimitry Andric
17810b57cec5SDimitry Andric if (print_json_stopinfo && m_stop_info_sp) {
17820b57cec5SDimitry Andric StructuredData::ObjectSP stop_info = m_stop_info_sp->GetExtendedInfo();
17830b57cec5SDimitry Andric if (stop_info) {
17840b57cec5SDimitry Andric stop_info->Dump(strm);
17850b57cec5SDimitry Andric strm.Printf("\n");
17860b57cec5SDimitry Andric }
17870b57cec5SDimitry Andric }
17880b57cec5SDimitry Andric
17890b57cec5SDimitry Andric return true;
17900b57cec5SDimitry Andric }
17910b57cec5SDimitry Andric
17920b57cec5SDimitry Andric if (thread_info) {
17930b57cec5SDimitry Andric StructuredData::ObjectSP activity =
17940b57cec5SDimitry Andric thread_info->GetObjectForDotSeparatedPath("activity");
17950b57cec5SDimitry Andric StructuredData::ObjectSP breadcrumb =
17960b57cec5SDimitry Andric thread_info->GetObjectForDotSeparatedPath("breadcrumb");
17970b57cec5SDimitry Andric StructuredData::ObjectSP messages =
17980b57cec5SDimitry Andric thread_info->GetObjectForDotSeparatedPath("trace_messages");
17990b57cec5SDimitry Andric
18000b57cec5SDimitry Andric bool printed_activity = false;
18010b57cec5SDimitry Andric if (activity && activity->GetType() == eStructuredDataTypeDictionary) {
18020b57cec5SDimitry Andric StructuredData::Dictionary *activity_dict = activity->GetAsDictionary();
18030b57cec5SDimitry Andric StructuredData::ObjectSP id = activity_dict->GetValueForKey("id");
18040b57cec5SDimitry Andric StructuredData::ObjectSP name = activity_dict->GetValueForKey("name");
18050b57cec5SDimitry Andric if (name && name->GetType() == eStructuredDataTypeString && id &&
18060b57cec5SDimitry Andric id->GetType() == eStructuredDataTypeInteger) {
18070b57cec5SDimitry Andric strm.Format(" Activity '{0}', {1:x}\n",
18080b57cec5SDimitry Andric name->GetAsString()->GetValue(),
18090b57cec5SDimitry Andric id->GetAsInteger()->GetValue());
18100b57cec5SDimitry Andric }
18110b57cec5SDimitry Andric printed_activity = true;
18120b57cec5SDimitry Andric }
18130b57cec5SDimitry Andric bool printed_breadcrumb = false;
18140b57cec5SDimitry Andric if (breadcrumb && breadcrumb->GetType() == eStructuredDataTypeDictionary) {
18150b57cec5SDimitry Andric if (printed_activity)
18160b57cec5SDimitry Andric strm.Printf("\n");
18170b57cec5SDimitry Andric StructuredData::Dictionary *breadcrumb_dict =
18180b57cec5SDimitry Andric breadcrumb->GetAsDictionary();
18190b57cec5SDimitry Andric StructuredData::ObjectSP breadcrumb_text =
18200b57cec5SDimitry Andric breadcrumb_dict->GetValueForKey("name");
18210b57cec5SDimitry Andric if (breadcrumb_text &&
18220b57cec5SDimitry Andric breadcrumb_text->GetType() == eStructuredDataTypeString) {
18230b57cec5SDimitry Andric strm.Format(" Current Breadcrumb: {0}\n",
18240b57cec5SDimitry Andric breadcrumb_text->GetAsString()->GetValue());
18250b57cec5SDimitry Andric }
18260b57cec5SDimitry Andric printed_breadcrumb = true;
18270b57cec5SDimitry Andric }
18280b57cec5SDimitry Andric if (messages && messages->GetType() == eStructuredDataTypeArray) {
18290b57cec5SDimitry Andric if (printed_breadcrumb)
18300b57cec5SDimitry Andric strm.Printf("\n");
18310b57cec5SDimitry Andric StructuredData::Array *messages_array = messages->GetAsArray();
18320b57cec5SDimitry Andric const size_t msg_count = messages_array->GetSize();
18330b57cec5SDimitry Andric if (msg_count > 0) {
18340b57cec5SDimitry Andric strm.Printf(" %zu trace messages:\n", msg_count);
18350b57cec5SDimitry Andric for (size_t i = 0; i < msg_count; i++) {
18360b57cec5SDimitry Andric StructuredData::ObjectSP message = messages_array->GetItemAtIndex(i);
18370b57cec5SDimitry Andric if (message && message->GetType() == eStructuredDataTypeDictionary) {
18380b57cec5SDimitry Andric StructuredData::Dictionary *message_dict =
18390b57cec5SDimitry Andric message->GetAsDictionary();
18400b57cec5SDimitry Andric StructuredData::ObjectSP message_text =
18410b57cec5SDimitry Andric message_dict->GetValueForKey("message");
18420b57cec5SDimitry Andric if (message_text &&
18430b57cec5SDimitry Andric message_text->GetType() == eStructuredDataTypeString) {
18440b57cec5SDimitry Andric strm.Format(" {0}\n", message_text->GetAsString()->GetValue());
18450b57cec5SDimitry Andric }
18460b57cec5SDimitry Andric }
18470b57cec5SDimitry Andric }
18480b57cec5SDimitry Andric }
18490b57cec5SDimitry Andric }
18500b57cec5SDimitry Andric }
18510b57cec5SDimitry Andric
18520b57cec5SDimitry Andric return true;
18530b57cec5SDimitry Andric }
18540b57cec5SDimitry Andric
GetStackFrameStatus(Stream & strm,uint32_t first_frame,uint32_t num_frames,bool show_frame_info,uint32_t num_frames_with_source)18550b57cec5SDimitry Andric size_t Thread::GetStackFrameStatus(Stream &strm, uint32_t first_frame,
18560b57cec5SDimitry Andric uint32_t num_frames, bool show_frame_info,
18570b57cec5SDimitry Andric uint32_t num_frames_with_source) {
18580b57cec5SDimitry Andric return GetStackFrameList()->GetStatus(
18590b57cec5SDimitry Andric strm, first_frame, num_frames, show_frame_info, num_frames_with_source);
18600b57cec5SDimitry Andric }
18610b57cec5SDimitry Andric
GetUnwinder()18625ffd83dbSDimitry Andric Unwind &Thread::GetUnwinder() {
18635ffd83dbSDimitry Andric if (!m_unwinder_up)
18645ffd83dbSDimitry Andric m_unwinder_up = std::make_unique<UnwindLLDB>(*this);
18655ffd83dbSDimitry Andric return *m_unwinder_up;
18660b57cec5SDimitry Andric }
18670b57cec5SDimitry Andric
Flush()18680b57cec5SDimitry Andric void Thread::Flush() {
18690b57cec5SDimitry Andric ClearStackFrames();
18700b57cec5SDimitry Andric m_reg_context_sp.reset();
18710b57cec5SDimitry Andric }
18720b57cec5SDimitry Andric
IsStillAtLastBreakpointHit()18730b57cec5SDimitry Andric bool Thread::IsStillAtLastBreakpointHit() {
18740b57cec5SDimitry Andric // If we are currently stopped at a breakpoint, always return that stopinfo
18750b57cec5SDimitry Andric // and don't reset it. This allows threads to maintain their breakpoint
18760b57cec5SDimitry Andric // stopinfo, such as when thread-stepping in multithreaded programs.
18770b57cec5SDimitry Andric if (m_stop_info_sp) {
18780b57cec5SDimitry Andric StopReason stop_reason = m_stop_info_sp->GetStopReason();
18790b57cec5SDimitry Andric if (stop_reason == lldb::eStopReasonBreakpoint) {
18800b57cec5SDimitry Andric uint64_t value = m_stop_info_sp->GetValue();
18810b57cec5SDimitry Andric lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());
18820b57cec5SDimitry Andric if (reg_ctx_sp) {
18830b57cec5SDimitry Andric lldb::addr_t pc = reg_ctx_sp->GetPC();
18840b57cec5SDimitry Andric BreakpointSiteSP bp_site_sp =
18850b57cec5SDimitry Andric GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
18860b57cec5SDimitry Andric if (bp_site_sp && static_cast<break_id_t>(value) == bp_site_sp->GetID())
18870b57cec5SDimitry Andric return true;
18880b57cec5SDimitry Andric }
18890b57cec5SDimitry Andric }
18900b57cec5SDimitry Andric }
18910b57cec5SDimitry Andric return false;
18920b57cec5SDimitry Andric }
18930b57cec5SDimitry Andric
StepIn(bool source_step,LazyBool step_in_avoids_code_without_debug_info,LazyBool step_out_avoids_code_without_debug_info)18940b57cec5SDimitry Andric Status Thread::StepIn(bool source_step,
18950b57cec5SDimitry Andric LazyBool step_in_avoids_code_without_debug_info,
18960b57cec5SDimitry Andric LazyBool step_out_avoids_code_without_debug_info)
18970b57cec5SDimitry Andric
18980b57cec5SDimitry Andric {
18990b57cec5SDimitry Andric Status error;
19000b57cec5SDimitry Andric Process *process = GetProcess().get();
19010b57cec5SDimitry Andric if (StateIsStoppedState(process->GetState(), true)) {
19020b57cec5SDimitry Andric StackFrameSP frame_sp = GetStackFrameAtIndex(0);
19030b57cec5SDimitry Andric ThreadPlanSP new_plan_sp;
19040b57cec5SDimitry Andric const lldb::RunMode run_mode = eOnlyThisThread;
19050b57cec5SDimitry Andric const bool abort_other_plans = false;
19060b57cec5SDimitry Andric
19070b57cec5SDimitry Andric if (source_step && frame_sp && frame_sp->HasDebugInformation()) {
19080b57cec5SDimitry Andric SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
19090b57cec5SDimitry Andric new_plan_sp = QueueThreadPlanForStepInRange(
19100b57cec5SDimitry Andric abort_other_plans, sc.line_entry, sc, nullptr, run_mode, error,
19110b57cec5SDimitry Andric step_in_avoids_code_without_debug_info,
19120b57cec5SDimitry Andric step_out_avoids_code_without_debug_info);
19130b57cec5SDimitry Andric } else {
19140b57cec5SDimitry Andric new_plan_sp = QueueThreadPlanForStepSingleInstruction(
19150b57cec5SDimitry Andric false, abort_other_plans, run_mode, error);
19160b57cec5SDimitry Andric }
19170b57cec5SDimitry Andric
19180b57cec5SDimitry Andric new_plan_sp->SetIsMasterPlan(true);
19190b57cec5SDimitry Andric new_plan_sp->SetOkayToDiscard(false);
19200b57cec5SDimitry Andric
19210b57cec5SDimitry Andric // Why do we need to set the current thread by ID here???
19220b57cec5SDimitry Andric process->GetThreadList().SetSelectedThreadByID(GetID());
19230b57cec5SDimitry Andric error = process->Resume();
19240b57cec5SDimitry Andric } else {
19250b57cec5SDimitry Andric error.SetErrorString("process not stopped");
19260b57cec5SDimitry Andric }
19270b57cec5SDimitry Andric return error;
19280b57cec5SDimitry Andric }
19290b57cec5SDimitry Andric
StepOver(bool source_step,LazyBool step_out_avoids_code_without_debug_info)19300b57cec5SDimitry Andric Status Thread::StepOver(bool source_step,
19310b57cec5SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) {
19320b57cec5SDimitry Andric Status error;
19330b57cec5SDimitry Andric Process *process = GetProcess().get();
19340b57cec5SDimitry Andric if (StateIsStoppedState(process->GetState(), true)) {
19350b57cec5SDimitry Andric StackFrameSP frame_sp = GetStackFrameAtIndex(0);
19360b57cec5SDimitry Andric ThreadPlanSP new_plan_sp;
19370b57cec5SDimitry Andric
19380b57cec5SDimitry Andric const lldb::RunMode run_mode = eOnlyThisThread;
19390b57cec5SDimitry Andric const bool abort_other_plans = false;
19400b57cec5SDimitry Andric
19410b57cec5SDimitry Andric if (source_step && frame_sp && frame_sp->HasDebugInformation()) {
19420b57cec5SDimitry Andric SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
19430b57cec5SDimitry Andric new_plan_sp = QueueThreadPlanForStepOverRange(
19440b57cec5SDimitry Andric abort_other_plans, sc.line_entry, sc, run_mode, error,
19450b57cec5SDimitry Andric step_out_avoids_code_without_debug_info);
19460b57cec5SDimitry Andric } else {
19470b57cec5SDimitry Andric new_plan_sp = QueueThreadPlanForStepSingleInstruction(
19480b57cec5SDimitry Andric true, abort_other_plans, run_mode, error);
19490b57cec5SDimitry Andric }
19500b57cec5SDimitry Andric
19510b57cec5SDimitry Andric new_plan_sp->SetIsMasterPlan(true);
19520b57cec5SDimitry Andric new_plan_sp->SetOkayToDiscard(false);
19530b57cec5SDimitry Andric
19540b57cec5SDimitry Andric // Why do we need to set the current thread by ID here???
19550b57cec5SDimitry Andric process->GetThreadList().SetSelectedThreadByID(GetID());
19560b57cec5SDimitry Andric error = process->Resume();
19570b57cec5SDimitry Andric } else {
19580b57cec5SDimitry Andric error.SetErrorString("process not stopped");
19590b57cec5SDimitry Andric }
19600b57cec5SDimitry Andric return error;
19610b57cec5SDimitry Andric }
19620b57cec5SDimitry Andric
StepOut()19630b57cec5SDimitry Andric Status Thread::StepOut() {
19640b57cec5SDimitry Andric Status error;
19650b57cec5SDimitry Andric Process *process = GetProcess().get();
19660b57cec5SDimitry Andric if (StateIsStoppedState(process->GetState(), true)) {
19670b57cec5SDimitry Andric const bool first_instruction = false;
19680b57cec5SDimitry Andric const bool stop_other_threads = false;
19690b57cec5SDimitry Andric const bool abort_other_plans = false;
19700b57cec5SDimitry Andric
19710b57cec5SDimitry Andric ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut(
19720b57cec5SDimitry Andric abort_other_plans, nullptr, first_instruction, stop_other_threads,
19730b57cec5SDimitry Andric eVoteYes, eVoteNoOpinion, 0, error));
19740b57cec5SDimitry Andric
19750b57cec5SDimitry Andric new_plan_sp->SetIsMasterPlan(true);
19760b57cec5SDimitry Andric new_plan_sp->SetOkayToDiscard(false);
19770b57cec5SDimitry Andric
19780b57cec5SDimitry Andric // Why do we need to set the current thread by ID here???
19790b57cec5SDimitry Andric process->GetThreadList().SetSelectedThreadByID(GetID());
19800b57cec5SDimitry Andric error = process->Resume();
19810b57cec5SDimitry Andric } else {
19820b57cec5SDimitry Andric error.SetErrorString("process not stopped");
19830b57cec5SDimitry Andric }
19840b57cec5SDimitry Andric return error;
19850b57cec5SDimitry Andric }
19860b57cec5SDimitry Andric
GetCurrentException()19870b57cec5SDimitry Andric ValueObjectSP Thread::GetCurrentException() {
19880b57cec5SDimitry Andric if (auto frame_sp = GetStackFrameAtIndex(0))
19890b57cec5SDimitry Andric if (auto recognized_frame = frame_sp->GetRecognizedFrame())
19900b57cec5SDimitry Andric if (auto e = recognized_frame->GetExceptionObject())
19910b57cec5SDimitry Andric return e;
19920b57cec5SDimitry Andric
19930b57cec5SDimitry Andric // NOTE: Even though this behavior is generalized, only ObjC is actually
19940b57cec5SDimitry Andric // supported at the moment.
19950b57cec5SDimitry Andric for (LanguageRuntime *runtime : GetProcess()->GetLanguageRuntimes()) {
19960b57cec5SDimitry Andric if (auto e = runtime->GetExceptionObjectForThread(shared_from_this()))
19970b57cec5SDimitry Andric return e;
19980b57cec5SDimitry Andric }
19990b57cec5SDimitry Andric
20000b57cec5SDimitry Andric return ValueObjectSP();
20010b57cec5SDimitry Andric }
20020b57cec5SDimitry Andric
GetCurrentExceptionBacktrace()20030b57cec5SDimitry Andric ThreadSP Thread::GetCurrentExceptionBacktrace() {
20040b57cec5SDimitry Andric ValueObjectSP exception = GetCurrentException();
20050b57cec5SDimitry Andric if (!exception)
20060b57cec5SDimitry Andric return ThreadSP();
20070b57cec5SDimitry Andric
20080b57cec5SDimitry Andric // NOTE: Even though this behavior is generalized, only ObjC is actually
20090b57cec5SDimitry Andric // supported at the moment.
20100b57cec5SDimitry Andric for (LanguageRuntime *runtime : GetProcess()->GetLanguageRuntimes()) {
20110b57cec5SDimitry Andric if (auto bt = runtime->GetBacktraceThreadFromException(exception))
20120b57cec5SDimitry Andric return bt;
20130b57cec5SDimitry Andric }
20140b57cec5SDimitry Andric
20150b57cec5SDimitry Andric return ThreadSP();
20160b57cec5SDimitry Andric }
2017