1cfca06d7SDimitry Andric //===-- Thread.cpp --------------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
914f1b3e8SDimitry Andric #include "lldb/Target/Thread.h"
10f034231aSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
11f034231aSEd Maste #include "lldb/Core/Debugger.h"
1212bd4897SEd Maste #include "lldb/Core/FormatEntity.h"
13e81d9d49SDimitry Andric #include "lldb/Core/Module.h"
14ead24645SDimitry Andric #include "lldb/Core/StructuredDataImpl.h"
15e81d9d49SDimitry Andric #include "lldb/Core/ValueObject.h"
16ecbca9f5SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h"
17f034231aSEd Maste #include "lldb/Host/Host.h"
18866dcdacSEd Maste #include "lldb/Interpreter/OptionValueFileSpecList.h"
195e95aa85SEd Maste #include "lldb/Interpreter/OptionValueProperties.h"
205e95aa85SEd Maste #include "lldb/Interpreter/Property.h"
21f034231aSEd Maste #include "lldb/Symbol/Function.h"
225e95aa85SEd Maste #include "lldb/Target/ABI.h"
23f034231aSEd Maste #include "lldb/Target/DynamicLoader.h"
24f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
255f29bb8aSDimitry Andric #include "lldb/Target/LanguageRuntime.h"
26f034231aSEd Maste #include "lldb/Target/Process.h"
27f034231aSEd Maste #include "lldb/Target/RegisterContext.h"
2894994d37SDimitry Andric #include "lldb/Target/StackFrameRecognizer.h"
29f034231aSEd Maste #include "lldb/Target/StopInfo.h"
300cac4ca3SEd Maste #include "lldb/Target/SystemRuntime.h"
31f034231aSEd Maste #include "lldb/Target/Target.h"
32f034231aSEd Maste #include "lldb/Target/ThreadPlan.h"
33f034231aSEd Maste #include "lldb/Target/ThreadPlanBase.h"
3414f1b3e8SDimitry Andric #include "lldb/Target/ThreadPlanCallFunction.h"
35205afe67SEd Maste #include "lldb/Target/ThreadPlanPython.h"
3614f1b3e8SDimitry Andric #include "lldb/Target/ThreadPlanRunToAddress.h"
37cfca06d7SDimitry Andric #include "lldb/Target/ThreadPlanStack.h"
3814f1b3e8SDimitry Andric #include "lldb/Target/ThreadPlanStepInRange.h"
39f034231aSEd Maste #include "lldb/Target/ThreadPlanStepInstruction.h"
40f034231aSEd Maste #include "lldb/Target/ThreadPlanStepOut.h"
41f034231aSEd Maste #include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
42f034231aSEd Maste #include "lldb/Target/ThreadPlanStepOverRange.h"
4314f1b3e8SDimitry Andric #include "lldb/Target/ThreadPlanStepThrough.h"
44f034231aSEd Maste #include "lldb/Target/ThreadPlanStepUntil.h"
45f034231aSEd Maste #include "lldb/Target/ThreadSpec.h"
46cfca06d7SDimitry Andric #include "lldb/Target/UnwindLLDB.h"
47145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
4874a628f7SDimitry Andric #include "lldb/Utility/Log.h"
4974a628f7SDimitry Andric #include "lldb/Utility/RegularExpression.h"
5094994d37SDimitry Andric #include "lldb/Utility/State.h"
5174a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
5274a628f7SDimitry Andric #include "lldb/Utility/StreamString.h"
5361b440f5SDimitry Andric #include "lldb/lldb-enumerations.h"
54f034231aSEd Maste
555f29bb8aSDimitry Andric #include <memory>
56e3b55780SDimitry Andric #include <optional>
575f29bb8aSDimitry Andric
58f034231aSEd Maste using namespace lldb;
59f034231aSEd Maste using namespace lldb_private;
60f034231aSEd Maste
GetGlobalProperties()61c0981da4SDimitry Andric ThreadProperties &Thread::GetGlobalProperties() {
62f3fbd1c0SDimitry Andric // NOTE: intentional leak so we don't crash if global destructor chain gets
63f3fbd1c0SDimitry Andric // called as other threads still use the result of this function
64c0981da4SDimitry Andric static ThreadProperties *g_settings_ptr = new ThreadProperties(true);
65c0981da4SDimitry Andric return *g_settings_ptr;
66f034231aSEd Maste }
67f034231aSEd Maste
68ead24645SDimitry Andric #define LLDB_PROPERTIES_thread
69ead24645SDimitry Andric #include "TargetProperties.inc"
70f034231aSEd Maste
71f034231aSEd Maste enum {
72ead24645SDimitry Andric #define LLDB_PROPERTIES_thread
73ead24645SDimitry Andric #include "TargetPropertiesEnum.inc"
74f034231aSEd Maste };
75f034231aSEd Maste
76344a3780SDimitry Andric class ThreadOptionValueProperties
77344a3780SDimitry Andric : public Cloneable<ThreadOptionValueProperties, OptionValueProperties> {
78f034231aSEd Maste public:
ThreadOptionValueProperties(llvm::StringRef name)79b1c73532SDimitry Andric ThreadOptionValueProperties(llvm::StringRef name) : Cloneable(name) {}
80f034231aSEd Maste
817fa27ce4SDimitry Andric const Property *
GetPropertyAtIndex(size_t idx,const ExecutionContext * exe_ctx) const827fa27ce4SDimitry Andric GetPropertyAtIndex(size_t idx,
837fa27ce4SDimitry Andric const ExecutionContext *exe_ctx) const override {
840cac4ca3SEd Maste // When getting the value for a key from the thread options, we will always
85f73363f1SDimitry Andric // try and grab the setting from the current thread if there is one. Else
86f73363f1SDimitry Andric // we just use the one from this instance.
8714f1b3e8SDimitry Andric if (exe_ctx) {
88f034231aSEd Maste Thread *thread = exe_ctx->GetThreadPtr();
8914f1b3e8SDimitry Andric if (thread) {
9014f1b3e8SDimitry Andric ThreadOptionValueProperties *instance_properties =
9114f1b3e8SDimitry Andric static_cast<ThreadOptionValueProperties *>(
9214f1b3e8SDimitry Andric thread->GetValueProperties().get());
93f034231aSEd Maste if (this != instance_properties)
94f034231aSEd Maste return instance_properties->ProtectedGetPropertyAtIndex(idx);
95f034231aSEd Maste }
96f034231aSEd Maste }
97f034231aSEd Maste return ProtectedGetPropertyAtIndex(idx);
98f034231aSEd Maste }
99f034231aSEd Maste };
100f034231aSEd Maste
ThreadProperties(bool is_global)10114f1b3e8SDimitry Andric ThreadProperties::ThreadProperties(bool is_global) : Properties() {
10214f1b3e8SDimitry Andric if (is_global) {
103b1c73532SDimitry Andric m_collection_sp = std::make_shared<ThreadOptionValueProperties>("thread");
104ead24645SDimitry Andric m_collection_sp->Initialize(g_thread_properties);
10514f1b3e8SDimitry Andric } else
106344a3780SDimitry Andric m_collection_sp =
107c0981da4SDimitry Andric OptionValueProperties::CreateLocalCopy(Thread::GetGlobalProperties());
108f034231aSEd Maste }
109f034231aSEd Maste
110e81d9d49SDimitry Andric ThreadProperties::~ThreadProperties() = default;
111f034231aSEd Maste
GetSymbolsToAvoidRegexp()11214f1b3e8SDimitry Andric const RegularExpression *ThreadProperties::GetSymbolsToAvoidRegexp() {
113f034231aSEd Maste const uint32_t idx = ePropertyStepAvoidRegex;
1147fa27ce4SDimitry Andric return GetPropertyAtIndexAs<const RegularExpression *>(idx);
115f034231aSEd Maste }
116f034231aSEd Maste
GetLibrariesToAvoid() const1175f29bb8aSDimitry Andric FileSpecList ThreadProperties::GetLibrariesToAvoid() const {
118866dcdacSEd Maste const uint32_t idx = ePropertyStepAvoidLibraries;
1197fa27ce4SDimitry Andric return GetPropertyAtIndexAs<FileSpecList>(idx, {});
120866dcdacSEd Maste }
121866dcdacSEd Maste
GetTraceEnabledState() const12214f1b3e8SDimitry Andric bool ThreadProperties::GetTraceEnabledState() const {
123f034231aSEd Maste const uint32_t idx = ePropertyEnableThreadTrace;
1247fa27ce4SDimitry Andric return GetPropertyAtIndexAs<bool>(
1257fa27ce4SDimitry Andric idx, g_thread_properties[idx].default_uint_value != 0);
126f034231aSEd Maste }
127f034231aSEd Maste
GetStepInAvoidsNoDebug() const12814f1b3e8SDimitry Andric bool ThreadProperties::GetStepInAvoidsNoDebug() const {
1290cac4ca3SEd Maste const uint32_t idx = ePropertyStepInAvoidsNoDebug;
1307fa27ce4SDimitry Andric return GetPropertyAtIndexAs<bool>(
1317fa27ce4SDimitry Andric idx, g_thread_properties[idx].default_uint_value != 0);
1320cac4ca3SEd Maste }
1330cac4ca3SEd Maste
GetStepOutAvoidsNoDebug() const13414f1b3e8SDimitry Andric bool ThreadProperties::GetStepOutAvoidsNoDebug() const {
1350cac4ca3SEd Maste const uint32_t idx = ePropertyStepOutAvoidsNoDebug;
1367fa27ce4SDimitry Andric return GetPropertyAtIndexAs<bool>(
1377fa27ce4SDimitry Andric idx, g_thread_properties[idx].default_uint_value != 0);
1380cac4ca3SEd Maste }
1390cac4ca3SEd Maste
GetMaxBacktraceDepth() const14094994d37SDimitry Andric uint64_t ThreadProperties::GetMaxBacktraceDepth() const {
14194994d37SDimitry Andric const uint32_t idx = ePropertyMaxBacktraceDepth;
1427fa27ce4SDimitry Andric return GetPropertyAtIndexAs<uint64_t>(
1437fa27ce4SDimitry Andric idx, g_thread_properties[idx].default_uint_value);
14494994d37SDimitry Andric }
14594994d37SDimitry Andric
146f034231aSEd Maste // Thread Event Data
147f034231aSEd Maste
GetFlavorString()1487fa27ce4SDimitry Andric llvm::StringRef Thread::ThreadEventData::GetFlavorString() {
1497fa27ce4SDimitry Andric return "Thread::ThreadEventData";
150f034231aSEd Maste }
151f034231aSEd Maste
ThreadEventData(const lldb::ThreadSP thread_sp)15214f1b3e8SDimitry Andric Thread::ThreadEventData::ThreadEventData(const lldb::ThreadSP thread_sp)
15314f1b3e8SDimitry Andric : m_thread_sp(thread_sp), m_stack_id() {}
154f034231aSEd Maste
ThreadEventData(const lldb::ThreadSP thread_sp,const StackID & stack_id)15514f1b3e8SDimitry Andric Thread::ThreadEventData::ThreadEventData(const lldb::ThreadSP thread_sp,
15614f1b3e8SDimitry Andric const StackID &stack_id)
15714f1b3e8SDimitry Andric : m_thread_sp(thread_sp), m_stack_id(stack_id) {}
158f034231aSEd Maste
ThreadEventData()15914f1b3e8SDimitry Andric Thread::ThreadEventData::ThreadEventData() : m_thread_sp(), m_stack_id() {}
160f034231aSEd Maste
161e81d9d49SDimitry Andric Thread::ThreadEventData::~ThreadEventData() = default;
162f034231aSEd Maste
Dump(Stream * s) const16314f1b3e8SDimitry Andric void Thread::ThreadEventData::Dump(Stream *s) const {}
164f034231aSEd Maste
165f034231aSEd Maste const Thread::ThreadEventData *
GetEventDataFromEvent(const Event * event_ptr)16614f1b3e8SDimitry Andric Thread::ThreadEventData::GetEventDataFromEvent(const Event *event_ptr) {
16714f1b3e8SDimitry Andric if (event_ptr) {
168f034231aSEd Maste const EventData *event_data = event_ptr->GetData();
16914f1b3e8SDimitry Andric if (event_data &&
17014f1b3e8SDimitry Andric event_data->GetFlavor() == ThreadEventData::GetFlavorString())
171f034231aSEd Maste return static_cast<const ThreadEventData *>(event_ptr->GetData());
172f034231aSEd Maste }
173e81d9d49SDimitry Andric return nullptr;
174f034231aSEd Maste }
175f034231aSEd Maste
GetThreadFromEvent(const Event * event_ptr)17614f1b3e8SDimitry Andric ThreadSP Thread::ThreadEventData::GetThreadFromEvent(const Event *event_ptr) {
177f034231aSEd Maste ThreadSP thread_sp;
178f034231aSEd Maste const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr);
179f034231aSEd Maste if (event_data)
180f034231aSEd Maste thread_sp = event_data->GetThread();
181f034231aSEd Maste return thread_sp;
182f034231aSEd Maste }
183f034231aSEd Maste
GetStackIDFromEvent(const Event * event_ptr)18414f1b3e8SDimitry Andric StackID Thread::ThreadEventData::GetStackIDFromEvent(const Event *event_ptr) {
185f034231aSEd Maste StackID stack_id;
186f034231aSEd Maste const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr);
187f034231aSEd Maste if (event_data)
188f034231aSEd Maste stack_id = event_data->GetStackID();
189f034231aSEd Maste return stack_id;
190f034231aSEd Maste }
191f034231aSEd Maste
192f034231aSEd Maste StackFrameSP
GetStackFrameFromEvent(const Event * event_ptr)19314f1b3e8SDimitry Andric Thread::ThreadEventData::GetStackFrameFromEvent(const Event *event_ptr) {
194f034231aSEd Maste const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr);
195f034231aSEd Maste StackFrameSP frame_sp;
19614f1b3e8SDimitry Andric if (event_data) {
197f034231aSEd Maste ThreadSP thread_sp = event_data->GetThread();
19814f1b3e8SDimitry Andric if (thread_sp) {
19914f1b3e8SDimitry Andric frame_sp = thread_sp->GetStackFrameList()->GetFrameWithStackID(
20014f1b3e8SDimitry Andric event_data->GetStackID());
201f034231aSEd Maste }
202f034231aSEd Maste }
203f034231aSEd Maste return frame_sp;
204f034231aSEd Maste }
205f034231aSEd Maste
206f034231aSEd Maste // Thread class
207f034231aSEd Maste
GetStaticBroadcasterClass()208ac9a064cSDimitry Andric llvm::StringRef Thread::GetStaticBroadcasterClass() {
209ac9a064cSDimitry Andric static constexpr llvm::StringLiteral class_name("lldb.thread");
210f034231aSEd Maste return class_name;
211f034231aSEd Maste }
212f034231aSEd Maste
Thread(Process & process,lldb::tid_t tid,bool use_invalid_index_id)213f3fbd1c0SDimitry Andric Thread::Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id)
21414f1b3e8SDimitry Andric : ThreadProperties(false), UserID(tid),
215f3fbd1c0SDimitry Andric Broadcaster(process.GetTarget().GetDebugger().GetBroadcasterManager(),
216ac9a064cSDimitry Andric Thread::GetStaticBroadcasterClass().str()),
21714f1b3e8SDimitry Andric m_process_wp(process.shared_from_this()), m_stop_info_sp(),
21814f1b3e8SDimitry Andric m_stop_info_stop_id(0), m_stop_info_override_stop_id(0),
219e3b55780SDimitry Andric m_should_run_before_public_stop(false),
22014f1b3e8SDimitry Andric m_index_id(use_invalid_index_id ? LLDB_INVALID_INDEX32
22114f1b3e8SDimitry Andric : process.GetNextThreadIndexID(tid)),
22214f1b3e8SDimitry Andric m_reg_context_sp(), m_state(eStateUnloaded), m_state_mutex(),
223cfca06d7SDimitry Andric m_frame_mutex(), m_curr_frames_sp(), m_prev_frames_sp(),
224ac9a064cSDimitry Andric m_prev_framezero_pc(), m_resume_signal(LLDB_INVALID_SIGNAL_NUMBER),
22514f1b3e8SDimitry Andric m_resume_state(eStateRunning), m_temporary_resume_state(eStateRunning),
2265f29bb8aSDimitry Andric m_unwinder_up(), m_destroy_called(false),
2270cac4ca3SEd Maste m_override_should_notify(eLazyBoolCalculate),
22814f1b3e8SDimitry Andric m_extended_info_fetched(false), m_extended_info() {
229145449b1SDimitry Andric Log *log = GetLog(LLDBLog::Object);
230ead24645SDimitry Andric LLDB_LOGF(log, "%p Thread::Thread(tid = 0x%4.4" PRIx64 ")",
23114f1b3e8SDimitry Andric static_cast<void *>(this), GetID());
232f034231aSEd Maste
233f034231aSEd Maste CheckInWithManager();
234f034231aSEd Maste }
235f034231aSEd Maste
~Thread()23614f1b3e8SDimitry Andric Thread::~Thread() {
237145449b1SDimitry Andric Log *log = GetLog(LLDBLog::Object);
238ead24645SDimitry Andric LLDB_LOGF(log, "%p Thread::~Thread(tid = 0x%4.4" PRIx64 ")",
2390cac4ca3SEd Maste static_cast<void *>(this), GetID());
24014f1b3e8SDimitry Andric /// If you hit this assert, it means your derived class forgot to call
24114f1b3e8SDimitry Andric /// DoDestroy in its destructor.
242f034231aSEd Maste assert(m_destroy_called);
243f034231aSEd Maste }
244f034231aSEd Maste
DestroyThread()24514f1b3e8SDimitry Andric void Thread::DestroyThread() {
246f034231aSEd Maste m_destroy_called = true;
247f034231aSEd Maste m_stop_info_sp.reset();
248f034231aSEd Maste m_reg_context_sp.reset();
2495f29bb8aSDimitry Andric m_unwinder_up.reset();
250f3fbd1c0SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
251f034231aSEd Maste m_curr_frames_sp.reset();
252f034231aSEd Maste m_prev_frames_sp.reset();
253ac9a064cSDimitry Andric m_prev_framezero_pc.reset();
254f034231aSEd Maste }
255f034231aSEd Maste
BroadcastSelectedFrameChange(StackID & new_frame_id)25614f1b3e8SDimitry Andric void Thread::BroadcastSelectedFrameChange(StackID &new_frame_id) {
2574df029ccSDimitry Andric if (EventTypeHasListeners(eBroadcastBitSelectedFrameChanged)) {
2584df029ccSDimitry Andric auto data_sp =
2594df029ccSDimitry Andric std::make_shared<ThreadEventData>(shared_from_this(), new_frame_id);
2604df029ccSDimitry Andric BroadcastEvent(eBroadcastBitSelectedFrameChanged, data_sp);
2614df029ccSDimitry Andric }
262f034231aSEd Maste }
263f034231aSEd Maste
2647fa27ce4SDimitry Andric lldb::StackFrameSP
GetSelectedFrame(SelectMostRelevant select_most_relevant)2657fa27ce4SDimitry Andric Thread::GetSelectedFrame(SelectMostRelevant select_most_relevant) {
266e81d9d49SDimitry Andric StackFrameListSP stack_frame_list_sp(GetStackFrameList());
26714f1b3e8SDimitry Andric StackFrameSP frame_sp = stack_frame_list_sp->GetFrameAtIndex(
2687fa27ce4SDimitry Andric stack_frame_list_sp->GetSelectedFrameIndex(select_most_relevant));
269cfca06d7SDimitry Andric FrameSelectedCallback(frame_sp.get());
270e81d9d49SDimitry Andric return frame_sp;
271e81d9d49SDimitry Andric }
272e81d9d49SDimitry Andric
SetSelectedFrame(lldb_private::StackFrame * frame,bool broadcast)27314f1b3e8SDimitry Andric uint32_t Thread::SetSelectedFrame(lldb_private::StackFrame *frame,
27414f1b3e8SDimitry Andric bool broadcast) {
275f034231aSEd Maste uint32_t ret_value = GetStackFrameList()->SetSelectedFrame(frame);
276f034231aSEd Maste if (broadcast)
277f034231aSEd Maste BroadcastSelectedFrameChange(frame->GetStackID());
278cfca06d7SDimitry Andric FrameSelectedCallback(frame);
279f034231aSEd Maste return ret_value;
280f034231aSEd Maste }
281f034231aSEd Maste
SetSelectedFrameByIndex(uint32_t frame_idx,bool broadcast)28214f1b3e8SDimitry Andric bool Thread::SetSelectedFrameByIndex(uint32_t frame_idx, bool broadcast) {
283f034231aSEd Maste StackFrameSP frame_sp(GetStackFrameList()->GetFrameAtIndex(frame_idx));
28414f1b3e8SDimitry Andric if (frame_sp) {
285f034231aSEd Maste GetStackFrameList()->SetSelectedFrame(frame_sp.get());
286f034231aSEd Maste if (broadcast)
287f034231aSEd Maste BroadcastSelectedFrameChange(frame_sp->GetStackID());
288cfca06d7SDimitry Andric FrameSelectedCallback(frame_sp.get());
289f034231aSEd Maste return true;
29014f1b3e8SDimitry Andric } else
291f034231aSEd Maste return false;
292f034231aSEd Maste }
293f034231aSEd Maste
SetSelectedFrameByIndexNoisily(uint32_t frame_idx,Stream & output_stream)29414f1b3e8SDimitry Andric bool Thread::SetSelectedFrameByIndexNoisily(uint32_t frame_idx,
29514f1b3e8SDimitry Andric Stream &output_stream) {
296f034231aSEd Maste const bool broadcast = true;
297f034231aSEd Maste bool success = SetSelectedFrameByIndex(frame_idx, broadcast);
29814f1b3e8SDimitry Andric if (success) {
2997fa27ce4SDimitry Andric StackFrameSP frame_sp = GetSelectedFrame(DoNoSelectMostRelevantFrame);
30014f1b3e8SDimitry Andric if (frame_sp) {
301f034231aSEd Maste bool already_shown = false;
30214f1b3e8SDimitry Andric SymbolContext frame_sc(
30314f1b3e8SDimitry Andric frame_sp->GetSymbolContext(eSymbolContextLineEntry));
3047fa27ce4SDimitry Andric const Debugger &debugger = GetProcess()->GetTarget().GetDebugger();
305ac9a064cSDimitry Andric if (debugger.GetUseExternalEditor() && frame_sc.line_entry.GetFile() &&
3067fa27ce4SDimitry Andric frame_sc.line_entry.line != 0) {
3077fa27ce4SDimitry Andric if (llvm::Error e = Host::OpenFileInExternalEditor(
308ac9a064cSDimitry Andric debugger.GetExternalEditor(), frame_sc.line_entry.GetFile(),
3097fa27ce4SDimitry Andric frame_sc.line_entry.line)) {
3107fa27ce4SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e),
3117fa27ce4SDimitry Andric "OpenFileInExternalEditor failed: {0}");
3127fa27ce4SDimitry Andric } else {
3137fa27ce4SDimitry Andric already_shown = true;
3147fa27ce4SDimitry Andric }
315f034231aSEd Maste }
316f034231aSEd Maste
317f034231aSEd Maste bool show_frame_info = true;
318f034231aSEd Maste bool show_source = !already_shown;
319cfca06d7SDimitry Andric FrameSelectedCallback(frame_sp.get());
320f034231aSEd Maste return frame_sp->GetStatus(output_stream, show_frame_info, show_source);
321f034231aSEd Maste }
322f034231aSEd Maste return false;
32314f1b3e8SDimitry Andric } else
324f034231aSEd Maste return false;
325f034231aSEd Maste }
326f034231aSEd Maste
FrameSelectedCallback(StackFrame * frame)327cfca06d7SDimitry Andric void Thread::FrameSelectedCallback(StackFrame *frame) {
328cfca06d7SDimitry Andric if (!frame)
329cfca06d7SDimitry Andric return;
330cfca06d7SDimitry Andric
331cfca06d7SDimitry Andric if (frame->HasDebugInformation() &&
332cfca06d7SDimitry Andric (GetProcess()->GetWarningsOptimization() ||
333cfca06d7SDimitry Andric GetProcess()->GetWarningsUnsupportedLanguage())) {
33414f1b3e8SDimitry Andric SymbolContext sc =
33514f1b3e8SDimitry Andric frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextModule);
336e81d9d49SDimitry Andric GetProcess()->PrintWarningOptimization(sc);
337cfca06d7SDimitry Andric GetProcess()->PrintWarningUnsupportedLanguage(sc);
338e81d9d49SDimitry Andric }
339e81d9d49SDimitry Andric }
340f034231aSEd Maste
GetStopInfo()34114f1b3e8SDimitry Andric lldb::StopInfoSP Thread::GetStopInfo() {
342f034231aSEd Maste if (m_destroy_called)
343f034231aSEd Maste return m_stop_info_sp;
344f034231aSEd Maste
34574a628f7SDimitry Andric ThreadPlanSP completed_plan_sp(GetCompletedPlan());
346f034231aSEd Maste ProcessSP process_sp(GetProcess());
347f034231aSEd Maste const uint32_t stop_id = process_sp ? process_sp->GetStopID() : UINT32_MAX;
34874a628f7SDimitry Andric
349f73363f1SDimitry Andric // Here we select the stop info according to priorirty: - m_stop_info_sp (if
350f73363f1SDimitry Andric // not trace) - preset value - completed plan stop info - new value with plan
351f73363f1SDimitry Andric // from completed plan stack - m_stop_info_sp (trace stop reason is OK now) -
352f73363f1SDimitry Andric // ask GetPrivateStopInfo to set stop info
35374a628f7SDimitry Andric
35474a628f7SDimitry Andric bool have_valid_stop_info = m_stop_info_sp &&
35574a628f7SDimitry Andric m_stop_info_sp ->IsValid() &&
35674a628f7SDimitry Andric m_stop_info_stop_id == stop_id;
35774a628f7SDimitry Andric bool have_valid_completed_plan = completed_plan_sp && completed_plan_sp->PlanSucceeded();
35894994d37SDimitry Andric bool plan_failed = completed_plan_sp && !completed_plan_sp->PlanSucceeded();
35974a628f7SDimitry Andric bool plan_overrides_trace =
36074a628f7SDimitry Andric have_valid_stop_info && have_valid_completed_plan
36174a628f7SDimitry Andric && (m_stop_info_sp->GetStopReason() == eStopReasonTrace);
36274a628f7SDimitry Andric
36394994d37SDimitry Andric if (have_valid_stop_info && !plan_overrides_trace && !plan_failed) {
364f034231aSEd Maste return m_stop_info_sp;
36594994d37SDimitry Andric } else if (completed_plan_sp) {
36674a628f7SDimitry Andric return StopInfo::CreateStopReasonWithPlan(
36774a628f7SDimitry Andric completed_plan_sp, GetReturnValueObject(), GetExpressionVariable());
36814f1b3e8SDimitry Andric } else {
369f034231aSEd Maste GetPrivateStopInfo();
370f034231aSEd Maste return m_stop_info_sp;
371f034231aSEd Maste }
372f034231aSEd Maste }
373f034231aSEd Maste
CalculatePublicStopInfo()374ead24645SDimitry Andric void Thread::CalculatePublicStopInfo() {
375ead24645SDimitry Andric ResetStopInfo();
376ead24645SDimitry Andric SetStopInfo(GetStopInfo());
377ead24645SDimitry Andric }
378ead24645SDimitry Andric
GetPrivateStopInfo(bool calculate)379e3b55780SDimitry Andric lldb::StopInfoSP Thread::GetPrivateStopInfo(bool calculate) {
380e3b55780SDimitry Andric if (!calculate)
381e3b55780SDimitry Andric return m_stop_info_sp;
382e3b55780SDimitry Andric
383f034231aSEd Maste if (m_destroy_called)
384f034231aSEd Maste return m_stop_info_sp;
385f034231aSEd Maste
386f034231aSEd Maste ProcessSP process_sp(GetProcess());
38714f1b3e8SDimitry Andric if (process_sp) {
388f034231aSEd Maste const uint32_t process_stop_id = process_sp->GetStopID();
38914f1b3e8SDimitry Andric if (m_stop_info_stop_id != process_stop_id) {
390e3b55780SDimitry Andric // We preserve the old stop info for a variety of reasons:
391e3b55780SDimitry Andric // 1) Someone has already updated it by the time we get here
392e3b55780SDimitry Andric // 2) We didn't get to execute the breakpoint instruction we stopped at
393e3b55780SDimitry Andric // 3) This is a virtual step so we didn't actually run
394e3b55780SDimitry Andric // 4) If this thread wasn't allowed to run the last time round.
39514f1b3e8SDimitry Andric if (m_stop_info_sp) {
39614f1b3e8SDimitry Andric if (m_stop_info_sp->IsValid() || IsStillAtLastBreakpointHit() ||
397e3b55780SDimitry Andric GetCurrentPlan()->IsVirtualStep()
398e3b55780SDimitry Andric || GetTemporaryResumeState() == eStateSuspended)
399f034231aSEd Maste SetStopInfo(m_stop_info_sp);
400f034231aSEd Maste else
401f034231aSEd Maste m_stop_info_sp.reset();
402f034231aSEd Maste }
403f034231aSEd Maste
40414f1b3e8SDimitry Andric if (!m_stop_info_sp) {
405e81d9d49SDimitry Andric if (!CalculateStopInfo())
406f034231aSEd Maste SetStopInfo(StopInfoSP());
407f034231aSEd Maste }
408f034231aSEd Maste }
409205afe67SEd Maste
410f73363f1SDimitry Andric // The stop info can be manually set by calling Thread::SetStopInfo() prior
411f73363f1SDimitry Andric // to this function ever getting called, so we can't rely on
412f73363f1SDimitry Andric // "m_stop_info_stop_id != process_stop_id" as the condition for the if
413f73363f1SDimitry Andric // statement below, we must also check the stop info to see if we need to
414f73363f1SDimitry Andric // override it. See the header documentation in
415cfca06d7SDimitry Andric // Architecture::OverrideStopInfo() for more information on the stop
416f73363f1SDimitry Andric // info override callback.
41714f1b3e8SDimitry Andric if (m_stop_info_override_stop_id != process_stop_id) {
418205afe67SEd Maste m_stop_info_override_stop_id = process_stop_id;
41914f1b3e8SDimitry Andric if (m_stop_info_sp) {
420f73363f1SDimitry Andric if (const Architecture *arch =
421ef5d0b5eSDimitry Andric process_sp->GetTarget().GetArchitecturePlugin())
422ef5d0b5eSDimitry Andric arch->OverrideStopInfo(*this);
423205afe67SEd Maste }
424205afe67SEd Maste }
425f034231aSEd Maste }
426ac9a064cSDimitry Andric
427ac9a064cSDimitry Andric // If we were resuming the process and it was interrupted,
428ac9a064cSDimitry Andric // return no stop reason. This thread would like to resume.
429ac9a064cSDimitry Andric if (m_stop_info_sp && m_stop_info_sp->WasContinueInterrupted(*this))
430ac9a064cSDimitry Andric return {};
431ac9a064cSDimitry Andric
432f034231aSEd Maste return m_stop_info_sp;
433f034231aSEd Maste }
434f034231aSEd Maste
GetStopReason()43514f1b3e8SDimitry Andric lldb::StopReason Thread::GetStopReason() {
436f034231aSEd Maste lldb::StopInfoSP stop_info_sp(GetStopInfo());
437f034231aSEd Maste if (stop_info_sp)
438f034231aSEd Maste return stop_info_sp->GetStopReason();
439f034231aSEd Maste return eStopReasonNone;
440f034231aSEd Maste }
441f034231aSEd Maste
StopInfoIsUpToDate() const44214f1b3e8SDimitry Andric bool Thread::StopInfoIsUpToDate() const {
443e81d9d49SDimitry Andric ProcessSP process_sp(GetProcess());
444e81d9d49SDimitry Andric if (process_sp)
445e81d9d49SDimitry Andric return m_stop_info_stop_id == process_sp->GetStopID();
446e81d9d49SDimitry Andric else
44714f1b3e8SDimitry Andric return true; // Process is no longer around so stop info is always up to
44814f1b3e8SDimitry Andric // date...
449e81d9d49SDimitry Andric }
450f034231aSEd Maste
ResetStopInfo()45174a628f7SDimitry Andric void Thread::ResetStopInfo() {
45274a628f7SDimitry Andric if (m_stop_info_sp) {
45374a628f7SDimitry Andric m_stop_info_sp.reset();
45474a628f7SDimitry Andric }
45574a628f7SDimitry Andric }
45674a628f7SDimitry Andric
SetStopInfo(const lldb::StopInfoSP & stop_info_sp)45714f1b3e8SDimitry Andric void Thread::SetStopInfo(const lldb::StopInfoSP &stop_info_sp) {
458f034231aSEd Maste m_stop_info_sp = stop_info_sp;
45914f1b3e8SDimitry Andric if (m_stop_info_sp) {
460f034231aSEd Maste m_stop_info_sp->MakeStopInfoValid();
461f034231aSEd Maste // If we are overriding the ShouldReportStop, do that here:
462f034231aSEd Maste if (m_override_should_notify != eLazyBoolCalculate)
46314f1b3e8SDimitry Andric m_stop_info_sp->OverrideShouldNotify(m_override_should_notify ==
46414f1b3e8SDimitry Andric eLazyBoolYes);
465f034231aSEd Maste }
466f034231aSEd Maste
467f034231aSEd Maste ProcessSP process_sp(GetProcess());
468f034231aSEd Maste if (process_sp)
469f034231aSEd Maste m_stop_info_stop_id = process_sp->GetStopID();
470f034231aSEd Maste else
471f034231aSEd Maste m_stop_info_stop_id = UINT32_MAX;
472145449b1SDimitry Andric Log *log = GetLog(LLDBLog::Thread);
473ead24645SDimitry Andric LLDB_LOGF(log, "%p: tid = 0x%" PRIx64 ": stop info = %s (stop_id = %u)",
4740cac4ca3SEd Maste static_cast<void *>(this), GetID(),
4750cac4ca3SEd Maste stop_info_sp ? stop_info_sp->GetDescription() : "<NULL>",
4760cac4ca3SEd Maste m_stop_info_stop_id);
477f034231aSEd Maste }
478f034231aSEd Maste
SetShouldReportStop(Vote vote)47914f1b3e8SDimitry Andric void Thread::SetShouldReportStop(Vote vote) {
480f034231aSEd Maste if (vote == eVoteNoOpinion)
481f034231aSEd Maste return;
48214f1b3e8SDimitry Andric else {
483f034231aSEd Maste m_override_should_notify = (vote == eVoteYes ? eLazyBoolYes : eLazyBoolNo);
484f034231aSEd Maste if (m_stop_info_sp)
48514f1b3e8SDimitry Andric m_stop_info_sp->OverrideShouldNotify(m_override_should_notify ==
48614f1b3e8SDimitry Andric eLazyBoolYes);
487f034231aSEd Maste }
488f034231aSEd Maste }
489f034231aSEd Maste
SetStopInfoToNothing()49014f1b3e8SDimitry Andric void Thread::SetStopInfoToNothing() {
49114f1b3e8SDimitry Andric // Note, we can't just NULL out the private reason, or the native thread
492f73363f1SDimitry Andric // implementation will try to go calculate it again. For now, just set it to
493f73363f1SDimitry Andric // a Unix Signal with an invalid signal number.
49414f1b3e8SDimitry Andric SetStopInfo(
49514f1b3e8SDimitry Andric StopInfo::CreateStopReasonWithSignal(*this, LLDB_INVALID_SIGNAL_NUMBER));
496f034231aSEd Maste }
497f034231aSEd Maste
ThreadStoppedForAReason()4986f8fc217SDimitry Andric bool Thread::ThreadStoppedForAReason() { return (bool)GetPrivateStopInfo(); }
499f034231aSEd Maste
CheckpointThreadState(ThreadStateCheckpoint & saved_state)50014f1b3e8SDimitry Andric bool Thread::CheckpointThreadState(ThreadStateCheckpoint &saved_state) {
50186758c71SEd Maste saved_state.register_backup_sp.reset();
50286758c71SEd Maste lldb::StackFrameSP frame_sp(GetStackFrameAtIndex(0));
50314f1b3e8SDimitry Andric if (frame_sp) {
50414f1b3e8SDimitry Andric lldb::RegisterCheckpointSP reg_checkpoint_sp(
50514f1b3e8SDimitry Andric new RegisterCheckpoint(RegisterCheckpoint::Reason::eExpression));
50614f1b3e8SDimitry Andric if (reg_checkpoint_sp) {
50786758c71SEd Maste lldb::RegisterContextSP reg_ctx_sp(frame_sp->GetRegisterContext());
50886758c71SEd Maste if (reg_ctx_sp && reg_ctx_sp->ReadAllRegisterValues(*reg_checkpoint_sp))
50986758c71SEd Maste saved_state.register_backup_sp = reg_checkpoint_sp;
51086758c71SEd Maste }
51186758c71SEd Maste }
51286758c71SEd Maste if (!saved_state.register_backup_sp)
513f034231aSEd Maste return false;
514f034231aSEd Maste
515f034231aSEd Maste saved_state.stop_info_sp = GetStopInfo();
516f034231aSEd Maste ProcessSP process_sp(GetProcess());
517f034231aSEd Maste if (process_sp)
518f034231aSEd Maste saved_state.orig_stop_id = process_sp->GetStopID();
519f034231aSEd Maste saved_state.current_inlined_depth = GetCurrentInlinedDepth();
520cfca06d7SDimitry Andric saved_state.m_completed_plan_checkpoint =
521cfca06d7SDimitry Andric GetPlans().CheckpointCompletedPlans();
522f034231aSEd Maste
523f034231aSEd Maste return true;
524f034231aSEd Maste }
525f034231aSEd Maste
RestoreRegisterStateFromCheckpoint(ThreadStateCheckpoint & saved_state)52614f1b3e8SDimitry Andric bool Thread::RestoreRegisterStateFromCheckpoint(
52714f1b3e8SDimitry Andric ThreadStateCheckpoint &saved_state) {
52814f1b3e8SDimitry Andric if (saved_state.register_backup_sp) {
52986758c71SEd Maste lldb::StackFrameSP frame_sp(GetStackFrameAtIndex(0));
53014f1b3e8SDimitry Andric if (frame_sp) {
53186758c71SEd Maste lldb::RegisterContextSP reg_ctx_sp(frame_sp->GetRegisterContext());
53214f1b3e8SDimitry Andric if (reg_ctx_sp) {
53314f1b3e8SDimitry Andric bool ret =
53414f1b3e8SDimitry Andric reg_ctx_sp->WriteAllRegisterValues(*saved_state.register_backup_sp);
53586758c71SEd Maste
53686758c71SEd Maste // Clear out all stack frames as our world just changed.
53786758c71SEd Maste ClearStackFrames();
53886758c71SEd Maste reg_ctx_sp->InvalidateIfNeeded(true);
5395f29bb8aSDimitry Andric if (m_unwinder_up)
5405f29bb8aSDimitry Andric m_unwinder_up->Clear();
54186758c71SEd Maste return ret;
54286758c71SEd Maste }
54386758c71SEd Maste }
54486758c71SEd Maste }
54586758c71SEd Maste return false;
546f034231aSEd Maste }
547f034231aSEd Maste
RestoreThreadStateFromCheckpoint(ThreadStateCheckpoint & saved_state)548344a3780SDimitry Andric void Thread::RestoreThreadStateFromCheckpoint(
54914f1b3e8SDimitry Andric ThreadStateCheckpoint &saved_state) {
550f034231aSEd Maste if (saved_state.stop_info_sp)
551f034231aSEd Maste saved_state.stop_info_sp->MakeStopInfoValid();
552f034231aSEd Maste SetStopInfo(saved_state.stop_info_sp);
55314f1b3e8SDimitry Andric GetStackFrameList()->SetCurrentInlinedDepth(
55414f1b3e8SDimitry Andric saved_state.current_inlined_depth);
555cfca06d7SDimitry Andric GetPlans().RestoreCompletedPlanCheckpoint(
556cfca06d7SDimitry Andric saved_state.m_completed_plan_checkpoint);
557f034231aSEd Maste }
558f034231aSEd Maste
GetState() const55914f1b3e8SDimitry Andric StateType Thread::GetState() const {
560f034231aSEd Maste // If any other threads access this we will need a mutex for it
561f3fbd1c0SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_state_mutex);
562f034231aSEd Maste return m_state;
563f034231aSEd Maste }
564f034231aSEd Maste
SetState(StateType state)56514f1b3e8SDimitry Andric void Thread::SetState(StateType state) {
566f3fbd1c0SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_state_mutex);
567f034231aSEd Maste m_state = state;
568f034231aSEd Maste }
569f034231aSEd Maste
GetStopDescription()570cfca06d7SDimitry Andric std::string Thread::GetStopDescription() {
571cfca06d7SDimitry Andric StackFrameSP frame_sp = GetStackFrameAtIndex(0);
572cfca06d7SDimitry Andric
573cfca06d7SDimitry Andric if (!frame_sp)
574cfca06d7SDimitry Andric return GetStopDescriptionRaw();
575cfca06d7SDimitry Andric
576cfca06d7SDimitry Andric auto recognized_frame_sp = frame_sp->GetRecognizedFrame();
577cfca06d7SDimitry Andric
578cfca06d7SDimitry Andric if (!recognized_frame_sp)
579cfca06d7SDimitry Andric return GetStopDescriptionRaw();
580cfca06d7SDimitry Andric
581cfca06d7SDimitry Andric std::string recognized_stop_description =
582cfca06d7SDimitry Andric recognized_frame_sp->GetStopDescription();
583cfca06d7SDimitry Andric
584cfca06d7SDimitry Andric if (!recognized_stop_description.empty())
585cfca06d7SDimitry Andric return recognized_stop_description;
586cfca06d7SDimitry Andric
587cfca06d7SDimitry Andric return GetStopDescriptionRaw();
588cfca06d7SDimitry Andric }
589cfca06d7SDimitry Andric
GetStopDescriptionRaw()590cfca06d7SDimitry Andric std::string Thread::GetStopDescriptionRaw() {
591cfca06d7SDimitry Andric StopInfoSP stop_info_sp = GetStopInfo();
592cfca06d7SDimitry Andric std::string raw_stop_description;
593cfca06d7SDimitry Andric if (stop_info_sp && stop_info_sp->IsValid()) {
594cfca06d7SDimitry Andric raw_stop_description = stop_info_sp->GetDescription();
595cfca06d7SDimitry Andric assert((!raw_stop_description.empty() ||
596cfca06d7SDimitry Andric stop_info_sp->GetStopReason() == eStopReasonNone) &&
597cfca06d7SDimitry Andric "StopInfo returned an empty description.");
598cfca06d7SDimitry Andric }
599cfca06d7SDimitry Andric return raw_stop_description;
600cfca06d7SDimitry Andric }
601cfca06d7SDimitry Andric
WillStop()60214f1b3e8SDimitry Andric void Thread::WillStop() {
603f034231aSEd Maste ThreadPlan *current_plan = GetCurrentPlan();
604f034231aSEd Maste
605f034231aSEd Maste // FIXME: I may decide to disallow threads with no plans. In which
606f034231aSEd Maste // case this should go to an assert.
607f034231aSEd Maste
608f034231aSEd Maste if (!current_plan)
609f034231aSEd Maste return;
610f034231aSEd Maste
611f034231aSEd Maste current_plan->WillStop();
612f034231aSEd Maste }
613f034231aSEd Maste
SetupForResume()61414f1b3e8SDimitry Andric void Thread::SetupForResume() {
61514f1b3e8SDimitry Andric if (GetResumeState() != eStateSuspended) {
61614f1b3e8SDimitry Andric // If we're at a breakpoint push the step-over breakpoint plan. Do this
617f73363f1SDimitry Andric // before telling the current plan it will resume, since we might change
618f73363f1SDimitry Andric // what the current plan is.
619f034231aSEd Maste
620f034231aSEd Maste lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());
62114f1b3e8SDimitry Andric if (reg_ctx_sp) {
622205afe67SEd Maste const addr_t thread_pc = reg_ctx_sp->GetPC();
62314f1b3e8SDimitry Andric BreakpointSiteSP bp_site_sp =
62414f1b3e8SDimitry Andric GetProcess()->GetBreakpointSiteList().FindByAddress(thread_pc);
62514f1b3e8SDimitry Andric if (bp_site_sp) {
626f73363f1SDimitry Andric // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the
627f73363f1SDimitry Andric // target may not require anything special to step over a breakpoint.
628f034231aSEd Maste
629f034231aSEd Maste ThreadPlan *cur_plan = GetCurrentPlan();
630f034231aSEd Maste
631205afe67SEd Maste bool push_step_over_bp_plan = false;
63214f1b3e8SDimitry Andric if (cur_plan->GetKind() == ThreadPlan::eKindStepOverBreakpoint) {
63314f1b3e8SDimitry Andric ThreadPlanStepOverBreakpoint *bp_plan =
63414f1b3e8SDimitry Andric (ThreadPlanStepOverBreakpoint *)cur_plan;
635205afe67SEd Maste if (bp_plan->GetBreakpointLoadAddress() != thread_pc)
636205afe67SEd Maste push_step_over_bp_plan = true;
63714f1b3e8SDimitry Andric } else
638205afe67SEd Maste push_step_over_bp_plan = true;
639205afe67SEd Maste
64014f1b3e8SDimitry Andric if (push_step_over_bp_plan) {
641205afe67SEd Maste ThreadPlanSP step_bp_plan_sp(new ThreadPlanStepOverBreakpoint(*this));
64214f1b3e8SDimitry Andric if (step_bp_plan_sp) {
643205afe67SEd Maste step_bp_plan_sp->SetPrivate(true);
644f034231aSEd Maste
64514f1b3e8SDimitry Andric if (GetCurrentPlan()->RunState() != eStateStepping) {
64614f1b3e8SDimitry Andric ThreadPlanStepOverBreakpoint *step_bp_plan =
64714f1b3e8SDimitry Andric static_cast<ThreadPlanStepOverBreakpoint *>(
64814f1b3e8SDimitry Andric step_bp_plan_sp.get());
649f034231aSEd Maste step_bp_plan->SetAutoContinue(true);
650f034231aSEd Maste }
651f034231aSEd Maste QueueThreadPlan(step_bp_plan_sp, false);
652f034231aSEd Maste }
653f034231aSEd Maste }
654f034231aSEd Maste }
655f034231aSEd Maste }
656f034231aSEd Maste }
657f034231aSEd Maste }
658f034231aSEd Maste
ShouldResume(StateType resume_state)65914f1b3e8SDimitry Andric bool Thread::ShouldResume(StateType resume_state) {
660f034231aSEd Maste // At this point clear the completed plan stack.
661cfca06d7SDimitry Andric GetPlans().WillResume();
662f034231aSEd Maste m_override_should_notify = eLazyBoolCalculate;
663f034231aSEd Maste
664e81d9d49SDimitry Andric StateType prev_resume_state = GetTemporaryResumeState();
665e81d9d49SDimitry Andric
666e81d9d49SDimitry Andric SetTemporaryResumeState(resume_state);
667f034231aSEd Maste
668f034231aSEd Maste lldb::ThreadSP backing_thread_sp(GetBackingThread());
669f034231aSEd Maste if (backing_thread_sp)
670e81d9d49SDimitry Andric backing_thread_sp->SetTemporaryResumeState(resume_state);
671f034231aSEd Maste
67214f1b3e8SDimitry Andric // Make sure m_stop_info_sp is valid. Don't do this for threads we suspended
67314f1b3e8SDimitry Andric // in the previous run.
674e81d9d49SDimitry Andric if (prev_resume_state != eStateSuspended)
675f034231aSEd Maste GetPrivateStopInfo();
676f034231aSEd Maste
67714f1b3e8SDimitry Andric // This is a little dubious, but we are trying to limit how often we actually
678f73363f1SDimitry Andric // fetch stop info from the target, 'cause that slows down single stepping.
679f73363f1SDimitry Andric // So assume that if we got to the point where we're about to resume, and we
680f73363f1SDimitry Andric // haven't yet had to fetch the stop reason, then it doesn't need to know
681f034231aSEd Maste // about the fact that we are resuming...
682f034231aSEd Maste const uint32_t process_stop_id = GetProcess()->GetStopID();
683f034231aSEd Maste if (m_stop_info_stop_id == process_stop_id &&
68414f1b3e8SDimitry Andric (m_stop_info_sp && m_stop_info_sp->IsValid())) {
685f034231aSEd Maste StopInfo *stop_info = GetPrivateStopInfo().get();
686f034231aSEd Maste if (stop_info)
687f034231aSEd Maste stop_info->WillResume(resume_state);
688f034231aSEd Maste }
689f034231aSEd Maste
69014f1b3e8SDimitry Andric // Tell all the plans that we are about to resume in case they need to clear
691f73363f1SDimitry Andric // any state. We distinguish between the plan on the top of the stack and the
692f73363f1SDimitry Andric // lower plans in case a plan needs to do any special business before it
693f73363f1SDimitry Andric // runs.
694f034231aSEd Maste
695f034231aSEd Maste bool need_to_resume = false;
696f034231aSEd Maste ThreadPlan *plan_ptr = GetCurrentPlan();
69714f1b3e8SDimitry Andric if (plan_ptr) {
698f034231aSEd Maste need_to_resume = plan_ptr->WillResume(resume_state, true);
699f034231aSEd Maste
70014f1b3e8SDimitry Andric while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr) {
701f034231aSEd Maste plan_ptr->WillResume(resume_state, false);
702f034231aSEd Maste }
703f034231aSEd Maste
70414f1b3e8SDimitry Andric // If the WillResume for the plan says we are faking a resume, then it will
705f73363f1SDimitry Andric // have set an appropriate stop info. In that case, don't reset it here.
706f034231aSEd Maste
70714f1b3e8SDimitry Andric if (need_to_resume && resume_state != eStateSuspended) {
708f034231aSEd Maste m_stop_info_sp.reset();
709f034231aSEd Maste }
710f034231aSEd Maste }
711f034231aSEd Maste
71214f1b3e8SDimitry Andric if (need_to_resume) {
713f034231aSEd Maste ClearStackFrames();
714f034231aSEd Maste // Let Thread subclasses do any special work they need to prior to resuming
715f034231aSEd Maste WillResume(resume_state);
716f034231aSEd Maste }
717f034231aSEd Maste
718f034231aSEd Maste return need_to_resume;
719f034231aSEd Maste }
720f034231aSEd Maste
DidResume()721e3b55780SDimitry Andric void Thread::DidResume() {
722e3b55780SDimitry Andric SetResumeSignal(LLDB_INVALID_SIGNAL_NUMBER);
723e3b55780SDimitry Andric // This will get recomputed each time when we stop.
724e3b55780SDimitry Andric SetShouldRunBeforePublicStop(false);
725e3b55780SDimitry Andric }
726f034231aSEd Maste
DidStop()72714f1b3e8SDimitry Andric void Thread::DidStop() { SetState(eStateStopped); }
728f034231aSEd Maste
ShouldStop(Event * event_ptr)72914f1b3e8SDimitry Andric bool Thread::ShouldStop(Event *event_ptr) {
730f034231aSEd Maste ThreadPlan *current_plan = GetCurrentPlan();
731f034231aSEd Maste
732f034231aSEd Maste bool should_stop = true;
733f034231aSEd Maste
734145449b1SDimitry Andric Log *log = GetLog(LLDBLog::Step);
735f034231aSEd Maste
73614f1b3e8SDimitry Andric if (GetResumeState() == eStateSuspended) {
737ead24645SDimitry Andric LLDB_LOGF(log,
738ead24645SDimitry Andric "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
73914f1b3e8SDimitry Andric ", should_stop = 0 (ignore since thread was suspended)",
7400cac4ca3SEd Maste __FUNCTION__, GetID(), GetProtocolID());
741f034231aSEd Maste return false;
742f034231aSEd Maste }
743f034231aSEd Maste
74414f1b3e8SDimitry Andric if (GetTemporaryResumeState() == eStateSuspended) {
745ead24645SDimitry Andric LLDB_LOGF(log,
746ead24645SDimitry Andric "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
74714f1b3e8SDimitry Andric ", should_stop = 0 (ignore since thread was suspended)",
7480cac4ca3SEd Maste __FUNCTION__, GetID(), GetProtocolID());
749f034231aSEd Maste return false;
750f034231aSEd Maste }
751f034231aSEd Maste
752f034231aSEd Maste // Based on the current thread plan and process stop info, check if this
753f73363f1SDimitry Andric // thread caused the process to stop. NOTE: this must take place before the
754f73363f1SDimitry Andric // plan is moved from the current plan stack to the completed plan stack.
75514f1b3e8SDimitry Andric if (!ThreadStoppedForAReason()) {
756ead24645SDimitry Andric LLDB_LOGF(log,
757ead24645SDimitry Andric "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
75814f1b3e8SDimitry Andric ", pc = 0x%16.16" PRIx64
75914f1b3e8SDimitry Andric ", should_stop = 0 (ignore since no stop reason)",
7600cac4ca3SEd Maste __FUNCTION__, GetID(), GetProtocolID(),
76114f1b3e8SDimitry Andric GetRegisterContext() ? GetRegisterContext()->GetPC()
76214f1b3e8SDimitry Andric : LLDB_INVALID_ADDRESS);
763f034231aSEd Maste return false;
764f034231aSEd Maste }
765f034231aSEd Maste
766e3b55780SDimitry Andric // Clear the "must run me before stop" if it was set:
767e3b55780SDimitry Andric SetShouldRunBeforePublicStop(false);
768e3b55780SDimitry Andric
76914f1b3e8SDimitry Andric if (log) {
770ead24645SDimitry Andric LLDB_LOGF(log,
771ead24645SDimitry Andric "Thread::%s(%p) for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
77214f1b3e8SDimitry Andric ", pc = 0x%16.16" PRIx64,
773ead24645SDimitry Andric __FUNCTION__, static_cast<void *>(this), GetID(), GetProtocolID(),
77414f1b3e8SDimitry Andric GetRegisterContext() ? GetRegisterContext()->GetPC()
7750cac4ca3SEd Maste : LLDB_INVALID_ADDRESS);
776ead24645SDimitry Andric LLDB_LOGF(log, "^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^");
777f034231aSEd Maste StreamString s;
778f034231aSEd Maste s.IndentMore();
779cfca06d7SDimitry Andric GetProcess()->DumpThreadPlansForTID(
780cfca06d7SDimitry Andric s, GetID(), eDescriptionLevelVerbose, true /* internal */,
781cfca06d7SDimitry Andric false /* condense_trivial */, true /* skip_unreported */);
782ead24645SDimitry Andric LLDB_LOGF(log, "Plan stack initial state:\n%s", s.GetData());
783f034231aSEd Maste }
784f034231aSEd Maste
785f034231aSEd Maste // The top most plan always gets to do the trace log...
786f034231aSEd Maste current_plan->DoTraceLog();
787f034231aSEd Maste
78814f1b3e8SDimitry Andric // First query the stop info's ShouldStopSynchronous. This handles
789f73363f1SDimitry Andric // "synchronous" stop reasons, for example the breakpoint command on internal
790f73363f1SDimitry Andric // breakpoints. If a synchronous stop reason says we should not stop, then
791f73363f1SDimitry Andric // we don't have to do any more work on this stop.
792f034231aSEd Maste StopInfoSP private_stop_info(GetPrivateStopInfo());
79314f1b3e8SDimitry Andric if (private_stop_info &&
79414f1b3e8SDimitry Andric !private_stop_info->ShouldStopSynchronous(event_ptr)) {
795ead24645SDimitry Andric LLDB_LOGF(log, "StopInfo::ShouldStop async callback says we should not "
79614f1b3e8SDimitry Andric "stop, returning ShouldStop of false.");
797f034231aSEd Maste return false;
798f034231aSEd Maste }
799f034231aSEd Maste
800f73363f1SDimitry Andric // If we've already been restarted, don't query the plans since the state
801f73363f1SDimitry Andric // they would examine is not current.
802f034231aSEd Maste if (Process::ProcessEventData::GetRestartedFromEvent(event_ptr))
803f034231aSEd Maste return false;
804f034231aSEd Maste
80514f1b3e8SDimitry Andric // Before the plans see the state of the world, calculate the current inlined
80614f1b3e8SDimitry Andric // depth.
807f034231aSEd Maste GetStackFrameList()->CalculateCurrentInlinedDepth();
808f034231aSEd Maste
80914f1b3e8SDimitry Andric // If the base plan doesn't understand why we stopped, then we have to find a
810f73363f1SDimitry Andric // plan that does. If that plan is still working, then we don't need to do
811f73363f1SDimitry Andric // any more work. If the plan that explains the stop is done, then we should
812f73363f1SDimitry Andric // pop all the plans below it, and pop it, and then let the plans above it
813f73363f1SDimitry Andric // decide whether they still need to do more work.
814f034231aSEd Maste
815f034231aSEd Maste bool done_processing_current_plan = false;
816f034231aSEd Maste
81714f1b3e8SDimitry Andric if (!current_plan->PlanExplainsStop(event_ptr)) {
81814f1b3e8SDimitry Andric if (current_plan->TracerExplainsStop()) {
819f034231aSEd Maste done_processing_current_plan = true;
820f034231aSEd Maste should_stop = false;
82114f1b3e8SDimitry Andric } else {
822f73363f1SDimitry Andric // If the current plan doesn't explain the stop, then find one that does
823f73363f1SDimitry Andric // and let it handle the situation.
824f034231aSEd Maste ThreadPlan *plan_ptr = current_plan;
82514f1b3e8SDimitry Andric while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr) {
82614f1b3e8SDimitry Andric if (plan_ptr->PlanExplainsStop(event_ptr)) {
827344a3780SDimitry Andric LLDB_LOGF(log, "Plan %s explains stop.", plan_ptr->GetName());
828344a3780SDimitry Andric
829f034231aSEd Maste should_stop = plan_ptr->ShouldStop(event_ptr);
830f034231aSEd Maste
831f73363f1SDimitry Andric // plan_ptr explains the stop, next check whether plan_ptr is done,
832f73363f1SDimitry Andric // if so, then we should take it and all the plans below it off the
833f73363f1SDimitry Andric // stack.
834f034231aSEd Maste
83514f1b3e8SDimitry Andric if (plan_ptr->MischiefManaged()) {
83614f1b3e8SDimitry Andric // We're going to pop the plans up to and including the plan that
83714f1b3e8SDimitry Andric // explains the stop.
838f034231aSEd Maste ThreadPlan *prev_plan_ptr = GetPreviousPlan(plan_ptr);
839f034231aSEd Maste
84014f1b3e8SDimitry Andric do {
841f034231aSEd Maste if (should_stop)
842f034231aSEd Maste current_plan->WillStop();
843f034231aSEd Maste PopPlan();
84414f1b3e8SDimitry Andric } while ((current_plan = GetCurrentPlan()) != prev_plan_ptr);
845f73363f1SDimitry Andric // Now, if the responsible plan was not "Okay to discard" then
846f73363f1SDimitry Andric // we're done, otherwise we forward this to the next plan in the
847f73363f1SDimitry Andric // stack below.
84814f1b3e8SDimitry Andric done_processing_current_plan =
849c0981da4SDimitry Andric (plan_ptr->IsControllingPlan() && !plan_ptr->OkayToDiscard());
850e3b55780SDimitry Andric } else {
851e3b55780SDimitry Andric bool should_force_run = plan_ptr->ShouldRunBeforePublicStop();
852e3b55780SDimitry Andric if (should_force_run) {
853e3b55780SDimitry Andric SetShouldRunBeforePublicStop(true);
854e3b55780SDimitry Andric should_stop = false;
855e3b55780SDimitry Andric }
856f034231aSEd Maste done_processing_current_plan = true;
857e3b55780SDimitry Andric }
858f034231aSEd Maste break;
859f034231aSEd Maste }
860f034231aSEd Maste }
861f034231aSEd Maste }
862f034231aSEd Maste }
863f034231aSEd Maste
86414f1b3e8SDimitry Andric if (!done_processing_current_plan) {
865344a3780SDimitry Andric bool override_stop = false;
866f034231aSEd Maste
867f034231aSEd Maste // We're starting from the base plan, so just let it decide;
868cfca06d7SDimitry Andric if (current_plan->IsBasePlan()) {
869f034231aSEd Maste should_stop = current_plan->ShouldStop(event_ptr);
870ead24645SDimitry Andric LLDB_LOGF(log, "Base plan says should stop: %i.", should_stop);
87114f1b3e8SDimitry Andric } else {
872f73363f1SDimitry Andric // Otherwise, don't let the base plan override what the other plans say
873f73363f1SDimitry Andric // to do, since presumably if there were other plans they would know what
874f73363f1SDimitry Andric // to do...
8755f29bb8aSDimitry Andric while (true) {
876cfca06d7SDimitry Andric if (current_plan->IsBasePlan())
877f034231aSEd Maste break;
878f034231aSEd Maste
879f034231aSEd Maste should_stop = current_plan->ShouldStop(event_ptr);
880ead24645SDimitry Andric LLDB_LOGF(log, "Plan %s should stop: %d.", current_plan->GetName(),
88114f1b3e8SDimitry Andric should_stop);
88214f1b3e8SDimitry Andric if (current_plan->MischiefManaged()) {
883f034231aSEd Maste if (should_stop)
884f034231aSEd Maste current_plan->WillStop();
885f034231aSEd Maste
886344a3780SDimitry Andric if (current_plan->ShouldAutoContinue(event_ptr)) {
887344a3780SDimitry Andric override_stop = true;
888344a3780SDimitry Andric LLDB_LOGF(log, "Plan %s auto-continue: true.",
889344a3780SDimitry Andric current_plan->GetName());
890344a3780SDimitry Andric }
891f034231aSEd Maste
892c0981da4SDimitry Andric // If a Controlling Plan wants to stop, we let it. Otherwise, see if
893c0981da4SDimitry Andric // the plan's parent wants to stop.
894344a3780SDimitry Andric
895344a3780SDimitry Andric PopPlan();
896c0981da4SDimitry Andric if (should_stop && current_plan->IsControllingPlan() &&
89714f1b3e8SDimitry Andric !current_plan->OkayToDiscard()) {
898f034231aSEd Maste break;
899344a3780SDimitry Andric }
900f034231aSEd Maste
901f034231aSEd Maste current_plan = GetCurrentPlan();
90214f1b3e8SDimitry Andric if (current_plan == nullptr) {
903f034231aSEd Maste break;
904f034231aSEd Maste }
90514f1b3e8SDimitry Andric } else {
906f034231aSEd Maste break;
907f034231aSEd Maste }
908f034231aSEd Maste }
909f034231aSEd Maste }
910f034231aSEd Maste
911344a3780SDimitry Andric if (override_stop)
912f034231aSEd Maste should_stop = false;
913205afe67SEd Maste }
914205afe67SEd Maste
915c0981da4SDimitry Andric // One other potential problem is that we set up a controlling plan, then stop
916c0981da4SDimitry Andric // in before it is complete - for instance by hitting a breakpoint during a
917f73363f1SDimitry Andric // step-over - then do some step/finish/etc operations that wind up past the
918f73363f1SDimitry Andric // end point condition of the initial plan. We don't want to strand the
919f73363f1SDimitry Andric // original plan on the stack, This code clears stale plans off the stack.
920f034231aSEd Maste
92114f1b3e8SDimitry Andric if (should_stop) {
922f034231aSEd Maste ThreadPlan *plan_ptr = GetCurrentPlan();
92374a628f7SDimitry Andric
924f73363f1SDimitry Andric // Discard the stale plans and all plans below them in the stack, plus move
925f73363f1SDimitry Andric // the completed plans to the completed plan stack
926cfca06d7SDimitry Andric while (!plan_ptr->IsBasePlan()) {
927f034231aSEd Maste bool stale = plan_ptr->IsPlanStale();
928f034231aSEd Maste ThreadPlan *examined_plan = plan_ptr;
929f034231aSEd Maste plan_ptr = GetPreviousPlan(examined_plan);
930f034231aSEd Maste
93114f1b3e8SDimitry Andric if (stale) {
932ead24645SDimitry Andric LLDB_LOGF(
933ead24645SDimitry Andric log,
93414f1b3e8SDimitry Andric "Plan %s being discarded in cleanup, it says it is already done.",
9350cac4ca3SEd Maste examined_plan->GetName());
93674a628f7SDimitry Andric while (GetCurrentPlan() != examined_plan) {
93774a628f7SDimitry Andric DiscardPlan();
93874a628f7SDimitry Andric }
93974a628f7SDimitry Andric if (examined_plan->IsPlanComplete()) {
940f73363f1SDimitry Andric // plan is complete but does not explain the stop (example: step to a
941f73363f1SDimitry Andric // line with breakpoint), let us move the plan to
942f73363f1SDimitry Andric // completed_plan_stack anyway
94374a628f7SDimitry Andric PopPlan();
94474a628f7SDimitry Andric } else
94574a628f7SDimitry Andric DiscardPlan();
946f034231aSEd Maste }
947f034231aSEd Maste }
948f034231aSEd Maste }
949f034231aSEd Maste
95014f1b3e8SDimitry Andric if (log) {
951f034231aSEd Maste StreamString s;
952f034231aSEd Maste s.IndentMore();
953cfca06d7SDimitry Andric GetProcess()->DumpThreadPlansForTID(
954cfca06d7SDimitry Andric s, GetID(), eDescriptionLevelVerbose, true /* internal */,
955cfca06d7SDimitry Andric false /* condense_trivial */, true /* skip_unreported */);
956ead24645SDimitry Andric LLDB_LOGF(log, "Plan stack final state:\n%s", s.GetData());
957ead24645SDimitry Andric LLDB_LOGF(log, "vvvvvvvv Thread::ShouldStop End (returning %i) vvvvvvvv",
95814f1b3e8SDimitry Andric should_stop);
959f034231aSEd Maste }
960f034231aSEd Maste return should_stop;
961f034231aSEd Maste }
962f034231aSEd Maste
ShouldReportStop(Event * event_ptr)96314f1b3e8SDimitry Andric Vote Thread::ShouldReportStop(Event *event_ptr) {
964f034231aSEd Maste StateType thread_state = GetResumeState();
965f034231aSEd Maste StateType temp_thread_state = GetTemporaryResumeState();
966f034231aSEd Maste
967145449b1SDimitry Andric Log *log = GetLog(LLDBLog::Step);
968f034231aSEd Maste
96914f1b3e8SDimitry Andric if (thread_state == eStateSuspended || thread_state == eStateInvalid) {
970ead24645SDimitry Andric LLDB_LOGF(log,
971ead24645SDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
97214f1b3e8SDimitry Andric ": returning vote %i (state was suspended or invalid)",
97314f1b3e8SDimitry Andric GetID(), eVoteNoOpinion);
974f034231aSEd Maste return eVoteNoOpinion;
975f034231aSEd Maste }
976f034231aSEd Maste
97714f1b3e8SDimitry Andric if (temp_thread_state == eStateSuspended ||
97814f1b3e8SDimitry Andric temp_thread_state == eStateInvalid) {
979ead24645SDimitry Andric LLDB_LOGF(log,
98014f1b3e8SDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
98114f1b3e8SDimitry Andric ": returning vote %i (temporary state was suspended or invalid)",
98214f1b3e8SDimitry Andric GetID(), eVoteNoOpinion);
983f034231aSEd Maste return eVoteNoOpinion;
984f034231aSEd Maste }
985f034231aSEd Maste
98614f1b3e8SDimitry Andric if (!ThreadStoppedForAReason()) {
987ead24645SDimitry Andric LLDB_LOGF(log,
988ead24645SDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
98914f1b3e8SDimitry Andric ": returning vote %i (thread didn't stop for a reason.)",
99014f1b3e8SDimitry Andric GetID(), eVoteNoOpinion);
991f034231aSEd Maste return eVoteNoOpinion;
992f034231aSEd Maste }
993f034231aSEd Maste
994cfca06d7SDimitry Andric if (GetPlans().AnyCompletedPlans()) {
995cfca06d7SDimitry Andric // Pass skip_private = false to GetCompletedPlan, since we want to ask
996cfca06d7SDimitry Andric // the last plan, regardless of whether it is private or not.
997ead24645SDimitry Andric LLDB_LOGF(log,
998ead24645SDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
99914f1b3e8SDimitry Andric ": returning vote for complete stack's back plan",
100014f1b3e8SDimitry Andric GetID());
1001cfca06d7SDimitry Andric return GetPlans().GetCompletedPlan(false)->ShouldReportStop(event_ptr);
100214f1b3e8SDimitry Andric } else {
1003f034231aSEd Maste Vote thread_vote = eVoteNoOpinion;
1004f034231aSEd Maste ThreadPlan *plan_ptr = GetCurrentPlan();
10055f29bb8aSDimitry Andric while (true) {
100614f1b3e8SDimitry Andric if (plan_ptr->PlanExplainsStop(event_ptr)) {
1007f034231aSEd Maste thread_vote = plan_ptr->ShouldReportStop(event_ptr);
1008f034231aSEd Maste break;
1009f034231aSEd Maste }
1010cfca06d7SDimitry Andric if (plan_ptr->IsBasePlan())
1011f034231aSEd Maste break;
1012f034231aSEd Maste else
1013f034231aSEd Maste plan_ptr = GetPreviousPlan(plan_ptr);
1014f034231aSEd Maste }
1015ead24645SDimitry Andric LLDB_LOGF(log,
1016ead24645SDimitry Andric "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
101714f1b3e8SDimitry Andric ": returning vote %i for current plan",
101814f1b3e8SDimitry Andric GetID(), thread_vote);
1019f034231aSEd Maste
1020f034231aSEd Maste return thread_vote;
1021f034231aSEd Maste }
1022f034231aSEd Maste }
1023f034231aSEd Maste
ShouldReportRun(Event * event_ptr)102414f1b3e8SDimitry Andric Vote Thread::ShouldReportRun(Event *event_ptr) {
1025f034231aSEd Maste StateType thread_state = GetResumeState();
1026f034231aSEd Maste
102714f1b3e8SDimitry Andric if (thread_state == eStateSuspended || thread_state == eStateInvalid) {
1028f034231aSEd Maste return eVoteNoOpinion;
1029f034231aSEd Maste }
1030f034231aSEd Maste
1031145449b1SDimitry Andric Log *log = GetLog(LLDBLog::Step);
1032cfca06d7SDimitry Andric if (GetPlans().AnyCompletedPlans()) {
1033cfca06d7SDimitry Andric // Pass skip_private = false to GetCompletedPlan, since we want to ask
1034cfca06d7SDimitry Andric // the last plan, regardless of whether it is private or not.
1035ead24645SDimitry Andric LLDB_LOGF(log,
1036ead24645SDimitry Andric "Current Plan for thread %d(%p) (0x%4.4" PRIx64
103714f1b3e8SDimitry Andric ", %s): %s being asked whether we should report run.",
10380cac4ca3SEd Maste GetIndexID(), static_cast<void *>(this), GetID(),
1039f034231aSEd Maste StateAsCString(GetTemporaryResumeState()),
1040cfca06d7SDimitry Andric GetCompletedPlan()->GetName());
1041f034231aSEd Maste
1042cfca06d7SDimitry Andric return GetPlans().GetCompletedPlan(false)->ShouldReportRun(event_ptr);
104314f1b3e8SDimitry Andric } else {
1044ead24645SDimitry Andric LLDB_LOGF(log,
1045ead24645SDimitry Andric "Current Plan for thread %d(%p) (0x%4.4" PRIx64
104614f1b3e8SDimitry Andric ", %s): %s being asked whether we should report run.",
10470cac4ca3SEd Maste GetIndexID(), static_cast<void *>(this), GetID(),
1048f034231aSEd Maste StateAsCString(GetTemporaryResumeState()),
1049f034231aSEd Maste GetCurrentPlan()->GetName());
1050f034231aSEd Maste
1051f034231aSEd Maste return GetCurrentPlan()->ShouldReportRun(event_ptr);
1052f034231aSEd Maste }
1053f034231aSEd Maste }
1054f034231aSEd Maste
MatchesSpec(const ThreadSpec * spec)105514f1b3e8SDimitry Andric bool Thread::MatchesSpec(const ThreadSpec *spec) {
1056e81d9d49SDimitry Andric return (spec == nullptr) ? true : spec->ThreadPassesBasicTests(*this);
1057f034231aSEd Maste }
1058f034231aSEd Maste
GetPlans() const1059cfca06d7SDimitry Andric ThreadPlanStack &Thread::GetPlans() const {
1060cfca06d7SDimitry Andric ThreadPlanStack *plans = GetProcess()->FindThreadPlans(GetID());
1061cfca06d7SDimitry Andric if (plans)
1062cfca06d7SDimitry Andric return *plans;
1063f034231aSEd Maste
1064cfca06d7SDimitry Andric // History threads don't have a thread plan, but they do ask get asked to
1065cfca06d7SDimitry Andric // describe themselves, which usually involves pulling out the stop reason.
1066cfca06d7SDimitry Andric // That in turn will check for a completed plan on the ThreadPlanStack.
1067cfca06d7SDimitry Andric // Instead of special-casing at that point, we return a Stack with a
1068cfca06d7SDimitry Andric // ThreadPlanNull as its base plan. That will give the right answers to the
1069cfca06d7SDimitry Andric // queries GetDescription makes, and only assert if you try to run the thread.
1070cfca06d7SDimitry Andric if (!m_null_plan_stack_up)
1071cfca06d7SDimitry Andric m_null_plan_stack_up = std::make_unique<ThreadPlanStack>(*this, true);
1072e3b55780SDimitry Andric return *m_null_plan_stack_up;
1073cfca06d7SDimitry Andric }
1074cfca06d7SDimitry Andric
PushPlan(ThreadPlanSP thread_plan_sp)1075cfca06d7SDimitry Andric void Thread::PushPlan(ThreadPlanSP thread_plan_sp) {
1076cfca06d7SDimitry Andric assert(thread_plan_sp && "Don't push an empty thread plan.");
1077f034231aSEd Maste
1078145449b1SDimitry Andric Log *log = GetLog(LLDBLog::Step);
107914f1b3e8SDimitry Andric if (log) {
1080f034231aSEd Maste StreamString s;
1081f034231aSEd Maste thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull);
1082ead24645SDimitry Andric LLDB_LOGF(log, "Thread::PushPlan(0x%p): \"%s\", tid = 0x%4.4" PRIx64 ".",
10830cac4ca3SEd Maste static_cast<void *>(this), s.GetData(),
1084f034231aSEd Maste thread_plan_sp->GetThread().GetID());
1085f034231aSEd Maste }
1086cfca06d7SDimitry Andric
1087cfca06d7SDimitry Andric GetPlans().PushPlan(std::move(thread_plan_sp));
1088f034231aSEd Maste }
1089f034231aSEd Maste
PopPlan()109014f1b3e8SDimitry Andric void Thread::PopPlan() {
1091145449b1SDimitry Andric Log *log = GetLog(LLDBLog::Step);
1092cfca06d7SDimitry Andric ThreadPlanSP popped_plan_sp = GetPlans().PopPlan();
109314f1b3e8SDimitry Andric if (log) {
1094ead24645SDimitry Andric LLDB_LOGF(log, "Popping plan: \"%s\", tid = 0x%4.4" PRIx64 ".",
1095cfca06d7SDimitry Andric popped_plan_sp->GetName(), popped_plan_sp->GetThread().GetID());
1096f034231aSEd Maste }
1097f034231aSEd Maste }
1098f034231aSEd Maste
DiscardPlan()109914f1b3e8SDimitry Andric void Thread::DiscardPlan() {
1100145449b1SDimitry Andric Log *log = GetLog(LLDBLog::Step);
1101145449b1SDimitry Andric ThreadPlanSP discarded_plan_sp = GetPlans().DiscardPlan();
1102cfca06d7SDimitry Andric
1103ead24645SDimitry Andric LLDB_LOGF(log, "Discarding plan: \"%s\", tid = 0x%4.4" PRIx64 ".",
1104cfca06d7SDimitry Andric discarded_plan_sp->GetName(),
1105cfca06d7SDimitry Andric discarded_plan_sp->GetThread().GetID());
1106f034231aSEd Maste }
1107f034231aSEd Maste
AutoCompleteThreadPlans(CompletionRequest & request) const1108b60736ecSDimitry Andric void Thread::AutoCompleteThreadPlans(CompletionRequest &request) const {
1109b60736ecSDimitry Andric const ThreadPlanStack &plans = GetPlans();
1110b60736ecSDimitry Andric if (!plans.AnyPlans())
1111b60736ecSDimitry Andric return;
1112b60736ecSDimitry Andric
1113b60736ecSDimitry Andric // Iterate from the second plan (index: 1) to skip the base plan.
1114b60736ecSDimitry Andric ThreadPlanSP p;
1115b60736ecSDimitry Andric uint32_t i = 1;
1116b60736ecSDimitry Andric while ((p = plans.GetPlanByIndex(i, false))) {
1117b60736ecSDimitry Andric StreamString strm;
1118b60736ecSDimitry Andric p->GetDescription(&strm, eDescriptionLevelInitial);
1119b60736ecSDimitry Andric request.TryCompleteCurrentArg(std::to_string(i), strm.GetString());
1120b60736ecSDimitry Andric i++;
1121b60736ecSDimitry Andric }
1122b60736ecSDimitry Andric }
1123b60736ecSDimitry Andric
GetCurrentPlan() const1124cfca06d7SDimitry Andric ThreadPlan *Thread::GetCurrentPlan() const {
1125cfca06d7SDimitry Andric return GetPlans().GetCurrentPlan().get();
1126f034231aSEd Maste }
1127f034231aSEd Maste
GetCompletedPlan() const1128cfca06d7SDimitry Andric ThreadPlanSP Thread::GetCompletedPlan() const {
1129cfca06d7SDimitry Andric return GetPlans().GetCompletedPlan();
1130f034231aSEd Maste }
1131f034231aSEd Maste
GetReturnValueObject() const1132cfca06d7SDimitry Andric ValueObjectSP Thread::GetReturnValueObject() const {
1133cfca06d7SDimitry Andric return GetPlans().GetReturnValueObject();
1134f034231aSEd Maste }
1135f034231aSEd Maste
GetExpressionVariable() const1136cfca06d7SDimitry Andric ExpressionVariableSP Thread::GetExpressionVariable() const {
1137cfca06d7SDimitry Andric return GetPlans().GetExpressionVariable();
11380cac4ca3SEd Maste }
11390cac4ca3SEd Maste
IsThreadPlanDone(ThreadPlan * plan) const1140cfca06d7SDimitry Andric bool Thread::IsThreadPlanDone(ThreadPlan *plan) const {
1141cfca06d7SDimitry Andric return GetPlans().IsPlanDone(plan);
1142f034231aSEd Maste }
1143f034231aSEd Maste
WasThreadPlanDiscarded(ThreadPlan * plan) const1144cfca06d7SDimitry Andric bool Thread::WasThreadPlanDiscarded(ThreadPlan *plan) const {
1145cfca06d7SDimitry Andric return GetPlans().WasPlanDiscarded(plan);
1146f034231aSEd Maste }
1147f034231aSEd Maste
CompletedPlanOverridesBreakpoint() const1148cfca06d7SDimitry Andric bool Thread::CompletedPlanOverridesBreakpoint() const {
1149cfca06d7SDimitry Andric return GetPlans().AnyCompletedPlans();
115074a628f7SDimitry Andric }
115174a628f7SDimitry Andric
GetPreviousPlan(ThreadPlan * current_plan) const1152cfca06d7SDimitry Andric ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) const{
1153cfca06d7SDimitry Andric return GetPlans().GetPreviousPlan(current_plan);
1154f034231aSEd Maste }
1155f034231aSEd Maste
QueueThreadPlan(ThreadPlanSP & thread_plan_sp,bool abort_other_plans)115694994d37SDimitry Andric Status Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp,
115714f1b3e8SDimitry Andric bool abort_other_plans) {
115894994d37SDimitry Andric Status status;
115994994d37SDimitry Andric StreamString s;
116094994d37SDimitry Andric if (!thread_plan_sp->ValidatePlan(&s)) {
116194994d37SDimitry Andric DiscardThreadPlansUpToPlan(thread_plan_sp);
116294994d37SDimitry Andric thread_plan_sp.reset();
116394994d37SDimitry Andric status.SetErrorString(s.GetString());
116494994d37SDimitry Andric return status;
116594994d37SDimitry Andric }
116694994d37SDimitry Andric
1167f034231aSEd Maste if (abort_other_plans)
1168f034231aSEd Maste DiscardThreadPlans(true);
1169f034231aSEd Maste
1170f034231aSEd Maste PushPlan(thread_plan_sp);
117194994d37SDimitry Andric
117294994d37SDimitry Andric // This seems a little funny, but I don't want to have to split up the
117394994d37SDimitry Andric // constructor and the DidPush in the scripted plan, that seems annoying.
117494994d37SDimitry Andric // That means the constructor has to be in DidPush. So I have to validate the
117594994d37SDimitry Andric // plan AFTER pushing it, and then take it off again...
117694994d37SDimitry Andric if (!thread_plan_sp->ValidatePlan(&s)) {
117794994d37SDimitry Andric DiscardThreadPlansUpToPlan(thread_plan_sp);
117894994d37SDimitry Andric thread_plan_sp.reset();
117994994d37SDimitry Andric status.SetErrorString(s.GetString());
118094994d37SDimitry Andric return status;
118194994d37SDimitry Andric }
118294994d37SDimitry Andric
118394994d37SDimitry Andric return status;
1184f034231aSEd Maste }
1185f034231aSEd Maste
DiscardUserThreadPlansUpToIndex(uint32_t plan_index)1186cfca06d7SDimitry Andric bool Thread::DiscardUserThreadPlansUpToIndex(uint32_t plan_index) {
118714f1b3e8SDimitry Andric // Count the user thread plans from the back end to get the number of the one
1188f73363f1SDimitry Andric // we want to discard:
1189205afe67SEd Maste
1190cfca06d7SDimitry Andric ThreadPlan *up_to_plan_ptr = GetPlans().GetPlanByIndex(plan_index).get();
1191205afe67SEd Maste if (up_to_plan_ptr == nullptr)
1192205afe67SEd Maste return false;
1193205afe67SEd Maste
1194205afe67SEd Maste DiscardThreadPlansUpToPlan(up_to_plan_ptr);
1195205afe67SEd Maste return true;
1196205afe67SEd Maste }
1197205afe67SEd Maste
DiscardThreadPlansUpToPlan(lldb::ThreadPlanSP & up_to_plan_sp)119814f1b3e8SDimitry Andric void Thread::DiscardThreadPlansUpToPlan(lldb::ThreadPlanSP &up_to_plan_sp) {
1199f034231aSEd Maste DiscardThreadPlansUpToPlan(up_to_plan_sp.get());
1200f034231aSEd Maste }
1201f034231aSEd Maste
DiscardThreadPlansUpToPlan(ThreadPlan * up_to_plan_ptr)120214f1b3e8SDimitry Andric void Thread::DiscardThreadPlansUpToPlan(ThreadPlan *up_to_plan_ptr) {
1203145449b1SDimitry Andric Log *log = GetLog(LLDBLog::Step);
1204ead24645SDimitry Andric LLDB_LOGF(log,
1205ead24645SDimitry Andric "Discarding thread plans for thread tid = 0x%4.4" PRIx64
120614f1b3e8SDimitry Andric ", up to %p",
12070cac4ca3SEd Maste GetID(), static_cast<void *>(up_to_plan_ptr));
1208cfca06d7SDimitry Andric GetPlans().DiscardPlansUpToPlan(up_to_plan_ptr);
1209f034231aSEd Maste }
1210f034231aSEd Maste
DiscardThreadPlans(bool force)121114f1b3e8SDimitry Andric void Thread::DiscardThreadPlans(bool force) {
1212145449b1SDimitry Andric Log *log = GetLog(LLDBLog::Step);
121314f1b3e8SDimitry Andric if (log) {
1214ead24645SDimitry Andric LLDB_LOGF(log,
1215ead24645SDimitry Andric "Discarding thread plans for thread (tid = 0x%4.4" PRIx64
121614f1b3e8SDimitry Andric ", force %d)",
121714f1b3e8SDimitry Andric GetID(), force);
1218f034231aSEd Maste }
1219f034231aSEd Maste
122014f1b3e8SDimitry Andric if (force) {
1221cfca06d7SDimitry Andric GetPlans().DiscardAllPlans();
1222f034231aSEd Maste return;
1223f034231aSEd Maste }
1224c0981da4SDimitry Andric GetPlans().DiscardConsultingControllingPlans();
1225f034231aSEd Maste }
1226f034231aSEd Maste
UnwindInnermostExpression()1227b76161e4SDimitry Andric Status Thread::UnwindInnermostExpression() {
1228b76161e4SDimitry Andric Status error;
1229cfca06d7SDimitry Andric ThreadPlan *innermost_expr_plan = GetPlans().GetInnermostExpression();
1230cfca06d7SDimitry Andric if (!innermost_expr_plan) {
1231cfca06d7SDimitry Andric error.SetErrorString("No expressions currently active on this thread");
1232f034231aSEd Maste return error;
1233f034231aSEd Maste }
1234cfca06d7SDimitry Andric DiscardThreadPlansUpToPlan(innermost_expr_plan);
1235f034231aSEd Maste return error;
1236f034231aSEd Maste }
1237f034231aSEd Maste
QueueBasePlan(bool abort_other_plans)1238344a3780SDimitry Andric ThreadPlanSP Thread::QueueBasePlan(bool abort_other_plans) {
1239f034231aSEd Maste ThreadPlanSP thread_plan_sp(new ThreadPlanBase(*this));
1240f034231aSEd Maste QueueThreadPlan(thread_plan_sp, abort_other_plans);
1241f034231aSEd Maste return thread_plan_sp;
1242f034231aSEd Maste }
1243f034231aSEd Maste
QueueThreadPlanForStepSingleInstruction(bool step_over,bool abort_other_plans,bool stop_other_threads,Status & status)124414f1b3e8SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction(
124594994d37SDimitry Andric bool step_over, bool abort_other_plans, bool stop_other_threads,
124694994d37SDimitry Andric Status &status) {
124714f1b3e8SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepInstruction(
124814f1b3e8SDimitry Andric *this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
124994994d37SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
1250f034231aSEd Maste return thread_plan_sp;
1251f034231aSEd Maste }
1252f034231aSEd Maste
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)125314f1b3e8SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
125414f1b3e8SDimitry Andric bool abort_other_plans, const AddressRange &range,
125514f1b3e8SDimitry Andric const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
125694994d37SDimitry Andric Status &status, LazyBool step_out_avoids_code_withoug_debug_info) {
1257f034231aSEd Maste ThreadPlanSP thread_plan_sp;
12585f29bb8aSDimitry Andric thread_plan_sp = std::make_shared<ThreadPlanStepOverRange>(
125914f1b3e8SDimitry Andric *this, range, addr_context, stop_other_threads,
12605f29bb8aSDimitry Andric step_out_avoids_code_withoug_debug_info);
1261f034231aSEd Maste
126294994d37SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
1263f034231aSEd Maste return thread_plan_sp;
1264f034231aSEd Maste }
1265f034231aSEd Maste
1266f73363f1SDimitry Andric // Call the QueueThreadPlanForStepOverRange method which takes an address
1267f73363f1SDimitry 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)126814f1b3e8SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
126914f1b3e8SDimitry Andric bool abort_other_plans, const LineEntry &line_entry,
127014f1b3e8SDimitry Andric const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
127194994d37SDimitry Andric Status &status, LazyBool step_out_avoids_code_withoug_debug_info) {
12725f29bb8aSDimitry Andric const bool include_inlined_functions = true;
12735f29bb8aSDimitry Andric auto address_range =
12745f29bb8aSDimitry Andric line_entry.GetSameLineContiguousAddressRange(include_inlined_functions);
127514f1b3e8SDimitry Andric return QueueThreadPlanForStepOverRange(
12765f29bb8aSDimitry Andric abort_other_plans, address_range, addr_context, stop_other_threads,
12775f29bb8aSDimitry Andric status, step_out_avoids_code_withoug_debug_info);
1278e81d9d49SDimitry Andric }
1279e81d9d49SDimitry 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)128014f1b3e8SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
128114f1b3e8SDimitry Andric bool abort_other_plans, const AddressRange &range,
128214f1b3e8SDimitry Andric const SymbolContext &addr_context, const char *step_in_target,
128394994d37SDimitry Andric lldb::RunMode stop_other_threads, Status &status,
12840cac4ca3SEd Maste LazyBool step_in_avoids_code_without_debug_info,
128514f1b3e8SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) {
1286344a3780SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepInRange(
1287344a3780SDimitry Andric *this, range, addr_context, step_in_target, stop_other_threads,
12880cac4ca3SEd Maste step_in_avoids_code_without_debug_info,
1289205afe67SEd Maste step_out_avoids_code_without_debug_info));
129094994d37SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
1291f034231aSEd Maste return thread_plan_sp;
1292f034231aSEd Maste }
1293f034231aSEd Maste
1294e81d9d49SDimitry 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)129514f1b3e8SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
129614f1b3e8SDimitry Andric bool abort_other_plans, const LineEntry &line_entry,
129714f1b3e8SDimitry Andric const SymbolContext &addr_context, const char *step_in_target,
129894994d37SDimitry Andric lldb::RunMode stop_other_threads, Status &status,
1299e81d9d49SDimitry Andric LazyBool step_in_avoids_code_without_debug_info,
130014f1b3e8SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) {
13015f29bb8aSDimitry Andric const bool include_inlined_functions = false;
130214f1b3e8SDimitry Andric return QueueThreadPlanForStepInRange(
13035f29bb8aSDimitry Andric abort_other_plans,
13045f29bb8aSDimitry Andric line_entry.GetSameLineContiguousAddressRange(include_inlined_functions),
130594994d37SDimitry Andric addr_context, step_in_target, stop_other_threads, status,
1306e81d9d49SDimitry Andric step_in_avoids_code_without_debug_info,
1307e81d9d49SDimitry Andric step_out_avoids_code_without_debug_info);
1308e81d9d49SDimitry Andric }
1309e81d9d49SDimitry 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)131014f1b3e8SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepOut(
131114f1b3e8SDimitry Andric bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
1312344a3780SDimitry Andric bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote,
1313344a3780SDimitry Andric uint32_t frame_idx, Status &status,
1314344a3780SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) {
131514f1b3e8SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
1316344a3780SDimitry Andric *this, addr_context, first_insn, stop_other_threads, report_stop_vote,
1317344a3780SDimitry Andric report_run_vote, frame_idx, step_out_avoids_code_without_debug_info));
1318f034231aSEd Maste
131994994d37SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
13200cac4ca3SEd Maste return thread_plan_sp;
13210cac4ca3SEd Maste }
13220cac4ca3SEd Maste
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)132314f1b3e8SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepOutNoShouldStop(
132414f1b3e8SDimitry Andric bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
1325344a3780SDimitry Andric bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote,
1326344a3780SDimitry Andric uint32_t frame_idx, Status &status, bool continue_to_next_branch) {
132714f1b3e8SDimitry Andric const bool calculate_return_value =
132814f1b3e8SDimitry Andric false; // No need to calculate the return value here.
132914f1b3e8SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
1330344a3780SDimitry Andric *this, addr_context, first_insn, stop_other_threads, report_stop_vote,
1331344a3780SDimitry Andric report_run_vote, frame_idx, eLazyBoolNo, continue_to_next_branch,
1332344a3780SDimitry Andric calculate_return_value));
1333205afe67SEd Maste
133414f1b3e8SDimitry Andric ThreadPlanStepOut *new_plan =
133514f1b3e8SDimitry Andric static_cast<ThreadPlanStepOut *>(thread_plan_sp.get());
13360cac4ca3SEd Maste new_plan->ClearShouldStopHereCallbacks();
1337f034231aSEd Maste
133894994d37SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
1339f034231aSEd Maste return thread_plan_sp;
1340f034231aSEd Maste }
1341f034231aSEd Maste
QueueThreadPlanForStepThrough(StackID & return_stack_id,bool abort_other_plans,bool stop_other_threads,Status & status)134214f1b3e8SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepThrough(StackID &return_stack_id,
134314f1b3e8SDimitry Andric bool abort_other_plans,
134494994d37SDimitry Andric bool stop_other_threads,
134594994d37SDimitry Andric Status &status) {
134614f1b3e8SDimitry Andric ThreadPlanSP thread_plan_sp(
134714f1b3e8SDimitry Andric new ThreadPlanStepThrough(*this, return_stack_id, stop_other_threads));
1348e81d9d49SDimitry Andric if (!thread_plan_sp || !thread_plan_sp->ValidatePlan(nullptr))
1349f034231aSEd Maste return ThreadPlanSP();
1350f034231aSEd Maste
135194994d37SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
1352f034231aSEd Maste return thread_plan_sp;
1353f034231aSEd Maste }
1354f034231aSEd Maste
QueueThreadPlanForRunToAddress(bool abort_other_plans,Address & target_addr,bool stop_other_threads,Status & status)135514f1b3e8SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForRunToAddress(bool abort_other_plans,
1356f034231aSEd Maste Address &target_addr,
135794994d37SDimitry Andric bool stop_other_threads,
135894994d37SDimitry Andric Status &status) {
135914f1b3e8SDimitry Andric ThreadPlanSP thread_plan_sp(
136014f1b3e8SDimitry Andric new ThreadPlanRunToAddress(*this, target_addr, stop_other_threads));
136194994d37SDimitry Andric
136294994d37SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
1363f034231aSEd Maste return thread_plan_sp;
1364f034231aSEd Maste }
1365f034231aSEd Maste
QueueThreadPlanForStepUntil(bool abort_other_plans,lldb::addr_t * address_list,size_t num_addresses,bool stop_other_threads,uint32_t frame_idx,Status & status)136694994d37SDimitry Andric ThreadPlanSP Thread::QueueThreadPlanForStepUntil(
136794994d37SDimitry Andric bool abort_other_plans, lldb::addr_t *address_list, size_t num_addresses,
136894994d37SDimitry Andric bool stop_other_threads, uint32_t frame_idx, Status &status) {
136914f1b3e8SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanStepUntil(
137014f1b3e8SDimitry Andric *this, address_list, num_addresses, stop_other_threads, frame_idx));
137194994d37SDimitry Andric
137294994d37SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
1373f034231aSEd Maste return thread_plan_sp;
1374f034231aSEd Maste }
1375f034231aSEd Maste
QueueThreadPlanForStepScripted(bool abort_other_plans,const char * class_name,StructuredData::ObjectSP extra_args_sp,bool stop_other_threads,Status & status)137614f1b3e8SDimitry Andric lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
1377ead24645SDimitry Andric bool abort_other_plans, const char *class_name,
1378ead24645SDimitry Andric StructuredData::ObjectSP extra_args_sp, bool stop_other_threads,
137994994d37SDimitry Andric Status &status) {
1380ead24645SDimitry Andric
138177fc4c14SDimitry Andric ThreadPlanSP thread_plan_sp(new ThreadPlanPython(
138277fc4c14SDimitry Andric *this, class_name, StructuredDataImpl(extra_args_sp)));
1383b60736ecSDimitry Andric thread_plan_sp->SetStopOthers(stop_other_threads);
138494994d37SDimitry Andric status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
1385205afe67SEd Maste return thread_plan_sp;
1386205afe67SEd Maste }
1387205afe67SEd Maste
GetIndexID() const138814f1b3e8SDimitry Andric uint32_t Thread::GetIndexID() const { return m_index_id; }
1389f034231aSEd Maste
CalculateTarget()139014f1b3e8SDimitry Andric TargetSP Thread::CalculateTarget() {
1391f034231aSEd Maste TargetSP target_sp;
1392f034231aSEd Maste ProcessSP process_sp(GetProcess());
1393f034231aSEd Maste if (process_sp)
1394f034231aSEd Maste target_sp = process_sp->CalculateTarget();
1395f034231aSEd Maste return target_sp;
1396f034231aSEd Maste }
1397f034231aSEd Maste
CalculateProcess()139814f1b3e8SDimitry Andric ProcessSP Thread::CalculateProcess() { return GetProcess(); }
1399f034231aSEd Maste
CalculateThread()140014f1b3e8SDimitry Andric ThreadSP Thread::CalculateThread() { return shared_from_this(); }
1401f034231aSEd Maste
CalculateStackFrame()140214f1b3e8SDimitry Andric StackFrameSP Thread::CalculateStackFrame() { return StackFrameSP(); }
1403f034231aSEd Maste
CalculateExecutionContext(ExecutionContext & exe_ctx)140414f1b3e8SDimitry Andric void Thread::CalculateExecutionContext(ExecutionContext &exe_ctx) {
1405f034231aSEd Maste exe_ctx.SetContext(shared_from_this());
1406f034231aSEd Maste }
1407f034231aSEd Maste
GetStackFrameList()140814f1b3e8SDimitry Andric StackFrameListSP Thread::GetStackFrameList() {
1409f3fbd1c0SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
14105f29bb8aSDimitry Andric
14115f29bb8aSDimitry Andric if (!m_curr_frames_sp)
14125f29bb8aSDimitry Andric m_curr_frames_sp =
14135f29bb8aSDimitry Andric std::make_shared<StackFrameList>(*this, m_prev_frames_sp, true);
14145f29bb8aSDimitry Andric
14155f29bb8aSDimitry Andric return m_curr_frames_sp;
1416f034231aSEd Maste }
1417f034231aSEd Maste
GetPreviousFrameZeroPC()1418ac9a064cSDimitry Andric std::optional<addr_t> Thread::GetPreviousFrameZeroPC() {
1419ac9a064cSDimitry Andric return m_prev_framezero_pc;
1420ac9a064cSDimitry Andric }
1421ac9a064cSDimitry Andric
ClearStackFrames()142214f1b3e8SDimitry Andric void Thread::ClearStackFrames() {
1423f3fbd1c0SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
1424f034231aSEd Maste
1425cfca06d7SDimitry Andric GetUnwinder().Clear();
1426ac9a064cSDimitry Andric m_prev_framezero_pc.reset();
1427ac9a064cSDimitry Andric if (RegisterContextSP reg_ctx_sp = GetRegisterContext())
1428ac9a064cSDimitry Andric m_prev_framezero_pc = reg_ctx_sp->GetPC();
1429f034231aSEd Maste
143014f1b3e8SDimitry Andric // Only store away the old "reference" StackFrameList if we got all its
143114f1b3e8SDimitry Andric // frames:
143214f1b3e8SDimitry Andric // FIXME: At some point we can try to splice in the frames we have fetched
1433ac9a064cSDimitry Andric // into the new frame as we make it, but let's not try that now.
1434f034231aSEd Maste if (m_curr_frames_sp && m_curr_frames_sp->GetAllFramesFetched())
1435f034231aSEd Maste m_prev_frames_sp.swap(m_curr_frames_sp);
1436f034231aSEd Maste m_curr_frames_sp.reset();
14370cac4ca3SEd Maste
14380cac4ca3SEd Maste m_extended_info.reset();
14390cac4ca3SEd Maste m_extended_info_fetched = false;
1440f034231aSEd Maste }
1441f034231aSEd Maste
GetFrameWithConcreteFrameIndex(uint32_t unwind_idx)144214f1b3e8SDimitry Andric lldb::StackFrameSP Thread::GetFrameWithConcreteFrameIndex(uint32_t unwind_idx) {
1443f034231aSEd Maste return GetStackFrameList()->GetFrameWithConcreteFrameIndex(unwind_idx);
1444f034231aSEd Maste }
1445f034231aSEd Maste
ReturnFromFrameWithIndex(uint32_t frame_idx,lldb::ValueObjectSP return_value_sp,bool broadcast)1446b76161e4SDimitry Andric Status Thread::ReturnFromFrameWithIndex(uint32_t frame_idx,
144714f1b3e8SDimitry Andric lldb::ValueObjectSP return_value_sp,
144814f1b3e8SDimitry Andric bool broadcast) {
1449f034231aSEd Maste StackFrameSP frame_sp = GetStackFrameAtIndex(frame_idx);
1450b76161e4SDimitry Andric Status return_error;
1451f034231aSEd Maste
145214f1b3e8SDimitry Andric if (!frame_sp) {
145314f1b3e8SDimitry Andric return_error.SetErrorStringWithFormat(
145414f1b3e8SDimitry Andric "Could not find frame with index %d in thread 0x%" PRIx64 ".",
145514f1b3e8SDimitry Andric frame_idx, GetID());
1456f034231aSEd Maste }
1457f034231aSEd Maste
1458f034231aSEd Maste return ReturnFromFrame(frame_sp, return_value_sp, broadcast);
1459f034231aSEd Maste }
1460f034231aSEd Maste
ReturnFromFrame(lldb::StackFrameSP frame_sp,lldb::ValueObjectSP return_value_sp,bool broadcast)1461b76161e4SDimitry Andric Status Thread::ReturnFromFrame(lldb::StackFrameSP frame_sp,
146214f1b3e8SDimitry Andric lldb::ValueObjectSP return_value_sp,
146314f1b3e8SDimitry Andric bool broadcast) {
1464b76161e4SDimitry Andric Status return_error;
1465f034231aSEd Maste
146614f1b3e8SDimitry Andric if (!frame_sp) {
1467f034231aSEd Maste return_error.SetErrorString("Can't return to a null frame.");
1468f034231aSEd Maste return return_error;
1469f034231aSEd Maste }
1470f034231aSEd Maste
1471f034231aSEd Maste Thread *thread = frame_sp->GetThread().get();
1472f034231aSEd Maste uint32_t older_frame_idx = frame_sp->GetFrameIndex() + 1;
1473f034231aSEd Maste StackFrameSP older_frame_sp = thread->GetStackFrameAtIndex(older_frame_idx);
147414f1b3e8SDimitry Andric if (!older_frame_sp) {
1475f034231aSEd Maste return_error.SetErrorString("No older frame to return to.");
1476f034231aSEd Maste return return_error;
1477f034231aSEd Maste }
1478f034231aSEd Maste
147914f1b3e8SDimitry Andric if (return_value_sp) {
1480f034231aSEd Maste lldb::ABISP abi = thread->GetProcess()->GetABI();
148114f1b3e8SDimitry Andric if (!abi) {
1482f034231aSEd Maste return_error.SetErrorString("Could not find ABI to set return value.");
1483f034231aSEd Maste return return_error;
1484f034231aSEd Maste }
1485f034231aSEd Maste SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextFunction);
1486f034231aSEd Maste
148714f1b3e8SDimitry Andric // FIXME: ValueObject::Cast doesn't currently work correctly, at least not
148814f1b3e8SDimitry Andric // for scalars.
1489f034231aSEd Maste // Turn that back on when that works.
14905f29bb8aSDimitry Andric if (/* DISABLES CODE */ (false) && sc.function != nullptr) {
1491f034231aSEd Maste Type *function_type = sc.function->GetType();
149214f1b3e8SDimitry Andric if (function_type) {
149314f1b3e8SDimitry Andric CompilerType return_type =
149414f1b3e8SDimitry Andric sc.function->GetCompilerType().GetFunctionReturnType();
149514f1b3e8SDimitry Andric if (return_type) {
1496f034231aSEd Maste StreamString s;
1497f034231aSEd Maste return_type.DumpTypeDescription(&s);
1498f034231aSEd Maste ValueObjectSP cast_value_sp = return_value_sp->Cast(return_type);
149914f1b3e8SDimitry Andric if (cast_value_sp) {
1500f034231aSEd Maste cast_value_sp->SetFormat(eFormatHex);
1501f034231aSEd Maste return_value_sp = cast_value_sp;
1502f034231aSEd Maste }
1503f034231aSEd Maste }
1504f034231aSEd Maste }
1505f034231aSEd Maste }
1506f034231aSEd Maste
1507f034231aSEd Maste return_error = abi->SetReturnValueObject(older_frame_sp, return_value_sp);
1508f034231aSEd Maste if (!return_error.Success())
1509f034231aSEd Maste return return_error;
1510f034231aSEd Maste }
1511f034231aSEd Maste
1512f73363f1SDimitry Andric // Now write the return registers for the chosen frame: Note, we can't use
1513f73363f1SDimitry Andric // ReadAllRegisterValues->WriteAllRegisterValues, since the read & write cook
1514f73363f1SDimitry Andric // their data
1515f034231aSEd Maste
1516f034231aSEd Maste StackFrameSP youngest_frame_sp = thread->GetStackFrameAtIndex(0);
151714f1b3e8SDimitry Andric if (youngest_frame_sp) {
1518f034231aSEd Maste lldb::RegisterContextSP reg_ctx_sp(youngest_frame_sp->GetRegisterContext());
151914f1b3e8SDimitry Andric if (reg_ctx_sp) {
152014f1b3e8SDimitry Andric bool copy_success = reg_ctx_sp->CopyFromRegisterContext(
152114f1b3e8SDimitry Andric older_frame_sp->GetRegisterContext());
152214f1b3e8SDimitry Andric if (copy_success) {
1523f034231aSEd Maste thread->DiscardThreadPlans(true);
1524f034231aSEd Maste thread->ClearStackFrames();
15254df029ccSDimitry Andric if (broadcast && EventTypeHasListeners(eBroadcastBitStackChanged)) {
15264df029ccSDimitry Andric auto data_sp = std::make_shared<ThreadEventData>(shared_from_this());
15274df029ccSDimitry Andric BroadcastEvent(eBroadcastBitStackChanged, data_sp);
15284df029ccSDimitry Andric }
152914f1b3e8SDimitry Andric } else {
1530f034231aSEd Maste return_error.SetErrorString("Could not reset register values.");
1531f034231aSEd Maste }
153214f1b3e8SDimitry Andric } else {
1533f034231aSEd Maste return_error.SetErrorString("Frame has no register context.");
1534f034231aSEd Maste }
153514f1b3e8SDimitry Andric } else {
1536f034231aSEd Maste return_error.SetErrorString("Returned past top frame.");
1537f034231aSEd Maste }
1538f034231aSEd Maste return return_error;
1539f034231aSEd Maste }
1540f034231aSEd Maste
DumpAddressList(Stream & s,const std::vector<Address> & list,ExecutionContextScope * exe_scope)154114f1b3e8SDimitry Andric static void DumpAddressList(Stream &s, const std::vector<Address> &list,
154214f1b3e8SDimitry Andric ExecutionContextScope *exe_scope) {
154314f1b3e8SDimitry Andric for (size_t n = 0; n < list.size(); n++) {
1544f21a844fSEd Maste s << "\t";
154514f1b3e8SDimitry Andric list[n].Dump(&s, exe_scope, Address::DumpStyleResolvedDescription,
154614f1b3e8SDimitry Andric Address::DumpStyleSectionNameOffset);
1547f21a844fSEd Maste s << "\n";
1548f21a844fSEd Maste }
1549f21a844fSEd Maste }
1550f21a844fSEd Maste
JumpToLine(const FileSpec & file,uint32_t line,bool can_leave_function,std::string * warnings)1551b76161e4SDimitry Andric Status Thread::JumpToLine(const FileSpec &file, uint32_t line,
155214f1b3e8SDimitry Andric bool can_leave_function, std::string *warnings) {
1553f21a844fSEd Maste ExecutionContext exe_ctx(GetStackFrameAtIndex(0));
1554f21a844fSEd Maste Target *target = exe_ctx.GetTargetPtr();
1555f21a844fSEd Maste TargetSP target_sp = exe_ctx.GetTargetSP();
1556f21a844fSEd Maste RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
1557f21a844fSEd Maste StackFrame *frame = exe_ctx.GetFramePtr();
1558f21a844fSEd Maste const SymbolContext &sc = frame->GetSymbolContext(eSymbolContextFunction);
1559f21a844fSEd Maste
1560f21a844fSEd Maste // Find candidate locations.
1561f21a844fSEd Maste std::vector<Address> candidates, within_function, outside_function;
156214f1b3e8SDimitry Andric target->GetImages().FindAddressesForLine(target_sp, file, line, sc.function,
156314f1b3e8SDimitry Andric within_function, outside_function);
1564f21a844fSEd Maste
1565f73363f1SDimitry Andric // If possible, we try and stay within the current function. Within a
1566f73363f1SDimitry Andric // function, we accept multiple locations (optimized code may do this,
1567f73363f1SDimitry Andric // there's no solution here so we do the best we can). However if we're
1568f73363f1SDimitry Andric // trying to leave the function, we don't know how to pick the right
1569f73363f1SDimitry Andric // location, so if there's more than one then we bail.
1570f21a844fSEd Maste if (!within_function.empty())
1571f21a844fSEd Maste candidates = within_function;
1572f21a844fSEd Maste else if (outside_function.size() == 1 && can_leave_function)
1573f21a844fSEd Maste candidates = outside_function;
1574f21a844fSEd Maste
1575f21a844fSEd Maste // Check if we got anything.
157614f1b3e8SDimitry Andric if (candidates.empty()) {
157714f1b3e8SDimitry Andric if (outside_function.empty()) {
1578b76161e4SDimitry Andric return Status("Cannot locate an address for %s:%i.",
1579f21a844fSEd Maste file.GetFilename().AsCString(), line);
158014f1b3e8SDimitry Andric } else if (outside_function.size() == 1) {
1581b76161e4SDimitry Andric return Status("%s:%i is outside the current function.",
1582f21a844fSEd Maste file.GetFilename().AsCString(), line);
158314f1b3e8SDimitry Andric } else {
1584f21a844fSEd Maste StreamString sstr;
1585f21a844fSEd Maste DumpAddressList(sstr, outside_function, target);
1586b76161e4SDimitry Andric return Status("%s:%i has multiple candidate locations:\n%s",
158714f1b3e8SDimitry Andric file.GetFilename().AsCString(), line, sstr.GetData());
1588f21a844fSEd Maste }
1589f21a844fSEd Maste }
1590f21a844fSEd Maste
1591f21a844fSEd Maste // Accept the first location, warn about any others.
1592f21a844fSEd Maste Address dest = candidates[0];
159314f1b3e8SDimitry Andric if (warnings && candidates.size() > 1) {
1594f21a844fSEd Maste StreamString sstr;
159514f1b3e8SDimitry Andric sstr.Printf("%s:%i appears multiple times in this function, selecting the "
159614f1b3e8SDimitry Andric "first location:\n",
1597f21a844fSEd Maste file.GetFilename().AsCString(), line);
1598f21a844fSEd Maste DumpAddressList(sstr, candidates, target);
1599cfca06d7SDimitry Andric *warnings = std::string(sstr.GetString());
1600f21a844fSEd Maste }
1601f21a844fSEd Maste
1602f21a844fSEd Maste if (!reg_ctx->SetPC(dest))
1603b76161e4SDimitry Andric return Status("Cannot change PC to target address.");
1604f21a844fSEd Maste
1605b76161e4SDimitry Andric return Status();
1606f21a844fSEd Maste }
1607f21a844fSEd Maste
DumpUsingFormat(Stream & strm,uint32_t frame_idx,const FormatEntity::Entry * format)1608b1c73532SDimitry Andric bool Thread::DumpUsingFormat(Stream &strm, uint32_t frame_idx,
1609b1c73532SDimitry Andric const FormatEntity::Entry *format) {
1610f034231aSEd Maste ExecutionContext exe_ctx(shared_from_this());
1611f034231aSEd Maste Process *process = exe_ctx.GetProcessPtr();
1612b1c73532SDimitry Andric if (!process || !format)
1613b1c73532SDimitry Andric return false;
1614f034231aSEd Maste
1615f034231aSEd Maste StackFrameSP frame_sp;
1616f034231aSEd Maste SymbolContext frame_sc;
161714f1b3e8SDimitry Andric if (frame_idx != LLDB_INVALID_FRAME_ID) {
1618f034231aSEd Maste frame_sp = GetStackFrameAtIndex(frame_idx);
161914f1b3e8SDimitry Andric if (frame_sp) {
1620f034231aSEd Maste exe_ctx.SetFrameSP(frame_sp);
1621f034231aSEd Maste frame_sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
1622f034231aSEd Maste }
1623f034231aSEd Maste }
1624f034231aSEd Maste
1625b1c73532SDimitry Andric return FormatEntity::Format(*format, strm, frame_sp ? &frame_sc : nullptr,
1626b1c73532SDimitry Andric &exe_ctx, nullptr, nullptr, false, false);
1627b1c73532SDimitry Andric }
1628b1c73532SDimitry Andric
DumpUsingSettingsFormat(Stream & strm,uint32_t frame_idx,bool stop_format)1629b1c73532SDimitry Andric void Thread::DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx,
1630b1c73532SDimitry Andric bool stop_format) {
1631b1c73532SDimitry Andric ExecutionContext exe_ctx(shared_from_this());
1632b1c73532SDimitry Andric
163314f1b3e8SDimitry Andric const FormatEntity::Entry *thread_format;
163414f1b3e8SDimitry Andric if (stop_format)
163514f1b3e8SDimitry Andric thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadStopFormat();
163614f1b3e8SDimitry Andric else
163714f1b3e8SDimitry Andric thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat();
163814f1b3e8SDimitry Andric
1639f034231aSEd Maste assert(thread_format);
164012bd4897SEd Maste
1641b1c73532SDimitry Andric DumpUsingFormat(strm, frame_idx, thread_format);
1642f034231aSEd Maste }
1643f034231aSEd Maste
SettingsInitialize()164414f1b3e8SDimitry Andric void Thread::SettingsInitialize() {}
1645f034231aSEd Maste
SettingsTerminate()164614f1b3e8SDimitry Andric void Thread::SettingsTerminate() {}
1647f034231aSEd Maste
GetThreadPointer()1648b1c73532SDimitry Andric lldb::addr_t Thread::GetThreadPointer() {
1649b1c73532SDimitry Andric if (m_reg_context_sp)
1650b1c73532SDimitry Andric return m_reg_context_sp->GetThreadPointer();
1651b1c73532SDimitry Andric return LLDB_INVALID_ADDRESS;
1652b1c73532SDimitry Andric }
1653f21a844fSEd Maste
GetThreadLocalData(const ModuleSP module,lldb::addr_t tls_file_addr)165414f1b3e8SDimitry Andric addr_t Thread::GetThreadLocalData(const ModuleSP module,
165514f1b3e8SDimitry Andric lldb::addr_t tls_file_addr) {
1656f73363f1SDimitry Andric // The default implementation is to ask the dynamic loader for it. This can
1657f73363f1SDimitry Andric // be overridden for specific platforms.
1658f21a844fSEd Maste DynamicLoader *loader = GetProcess()->GetDynamicLoader();
1659f21a844fSEd Maste if (loader)
166014f1b3e8SDimitry Andric return loader->GetThreadLocalData(module, shared_from_this(),
166114f1b3e8SDimitry Andric tls_file_addr);
1662f21a844fSEd Maste else
1663f21a844fSEd Maste return LLDB_INVALID_ADDRESS;
1664f21a844fSEd Maste }
1665f21a844fSEd Maste
SafeToCallFunctions()166614f1b3e8SDimitry Andric bool Thread::SafeToCallFunctions() {
16670cac4ca3SEd Maste Process *process = GetProcess().get();
166814f1b3e8SDimitry Andric if (process) {
1669e3b55780SDimitry Andric DynamicLoader *loader = GetProcess()->GetDynamicLoader();
1670e3b55780SDimitry Andric if (loader && loader->IsFullyInitialized() == false)
1671e3b55780SDimitry Andric return false;
1672e3b55780SDimitry Andric
16730cac4ca3SEd Maste SystemRuntime *runtime = process->GetSystemRuntime();
167414f1b3e8SDimitry Andric if (runtime) {
16750cac4ca3SEd Maste return runtime->SafeToCallFunctionsOnThisThread(shared_from_this());
16760cac4ca3SEd Maste }
16770cac4ca3SEd Maste }
16780cac4ca3SEd Maste return true;
16790cac4ca3SEd Maste }
16800cac4ca3SEd Maste
1681f034231aSEd Maste lldb::StackFrameSP
GetStackFrameSPForStackFramePtr(StackFrame * stack_frame_ptr)168214f1b3e8SDimitry Andric Thread::GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr) {
1683f034231aSEd Maste return GetStackFrameList()->GetStackFrameSPForStackFramePtr(stack_frame_ptr);
1684f034231aSEd Maste }
1685f034231aSEd Maste
StopReasonAsString(lldb::StopReason reason)1686b60736ecSDimitry Andric std::string Thread::StopReasonAsString(lldb::StopReason reason) {
168714f1b3e8SDimitry Andric switch (reason) {
168814f1b3e8SDimitry Andric case eStopReasonInvalid:
168914f1b3e8SDimitry Andric return "invalid";
169014f1b3e8SDimitry Andric case eStopReasonNone:
169114f1b3e8SDimitry Andric return "none";
169214f1b3e8SDimitry Andric case eStopReasonTrace:
169314f1b3e8SDimitry Andric return "trace";
169414f1b3e8SDimitry Andric case eStopReasonBreakpoint:
169514f1b3e8SDimitry Andric return "breakpoint";
169614f1b3e8SDimitry Andric case eStopReasonWatchpoint:
169714f1b3e8SDimitry Andric return "watchpoint";
169814f1b3e8SDimitry Andric case eStopReasonSignal:
169914f1b3e8SDimitry Andric return "signal";
170014f1b3e8SDimitry Andric case eStopReasonException:
170114f1b3e8SDimitry Andric return "exception";
170214f1b3e8SDimitry Andric case eStopReasonExec:
170314f1b3e8SDimitry Andric return "exec";
1704344a3780SDimitry Andric case eStopReasonFork:
1705344a3780SDimitry Andric return "fork";
1706344a3780SDimitry Andric case eStopReasonVFork:
1707344a3780SDimitry Andric return "vfork";
1708344a3780SDimitry Andric case eStopReasonVForkDone:
1709344a3780SDimitry Andric return "vfork done";
171014f1b3e8SDimitry Andric case eStopReasonPlanComplete:
171114f1b3e8SDimitry Andric return "plan complete";
171214f1b3e8SDimitry Andric case eStopReasonThreadExiting:
171314f1b3e8SDimitry Andric return "thread exiting";
171414f1b3e8SDimitry Andric case eStopReasonInstrumentation:
171514f1b3e8SDimitry Andric return "instrumentation break";
1716344a3780SDimitry Andric case eStopReasonProcessorTrace:
1717344a3780SDimitry Andric return "processor trace";
1718f034231aSEd Maste }
1719f034231aSEd Maste
1720b60736ecSDimitry Andric return "StopReason = " + std::to_string(reason);
1721f034231aSEd Maste }
1722f034231aSEd Maste
RunModeAsString(lldb::RunMode mode)1723b60736ecSDimitry Andric std::string Thread::RunModeAsString(lldb::RunMode mode) {
172414f1b3e8SDimitry Andric switch (mode) {
172514f1b3e8SDimitry Andric case eOnlyThisThread:
172614f1b3e8SDimitry Andric return "only this thread";
172714f1b3e8SDimitry Andric case eAllThreads:
172814f1b3e8SDimitry Andric return "all threads";
172914f1b3e8SDimitry Andric case eOnlyDuringStepping:
173014f1b3e8SDimitry Andric return "only during stepping";
1731f034231aSEd Maste }
1732f034231aSEd Maste
1733b60736ecSDimitry Andric return "RunMode = " + std::to_string(mode);
1734f034231aSEd Maste }
1735f034231aSEd Maste
GetStatus(Stream & strm,uint32_t start_frame,uint32_t num_frames,uint32_t num_frames_with_source,bool stop_format,bool only_stacks)173614f1b3e8SDimitry Andric size_t Thread::GetStatus(Stream &strm, uint32_t start_frame,
173714f1b3e8SDimitry Andric uint32_t num_frames, uint32_t num_frames_with_source,
17384befb1f9SDimitry Andric bool stop_format, bool only_stacks) {
17394befb1f9SDimitry Andric
17404befb1f9SDimitry Andric if (!only_stacks) {
1741f034231aSEd Maste ExecutionContext exe_ctx(shared_from_this());
1742f034231aSEd Maste Target *target = exe_ctx.GetTargetPtr();
1743f034231aSEd Maste Process *process = exe_ctx.GetProcessPtr();
1744f034231aSEd Maste strm.Indent();
1745f034231aSEd Maste bool is_selected = false;
174614f1b3e8SDimitry Andric if (process) {
1747f034231aSEd Maste if (process->GetThreadList().GetSelectedThread().get() == this)
1748f034231aSEd Maste is_selected = true;
1749f034231aSEd Maste }
1750f034231aSEd Maste strm.Printf("%c ", is_selected ? '*' : ' ');
175114f1b3e8SDimitry Andric if (target && target->GetDebugger().GetUseExternalEditor()) {
1752f034231aSEd Maste StackFrameSP frame_sp = GetStackFrameAtIndex(start_frame);
175314f1b3e8SDimitry Andric if (frame_sp) {
175414f1b3e8SDimitry Andric SymbolContext frame_sc(
175514f1b3e8SDimitry Andric frame_sp->GetSymbolContext(eSymbolContextLineEntry));
1756ac9a064cSDimitry Andric if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.GetFile()) {
17577fa27ce4SDimitry Andric if (llvm::Error e = Host::OpenFileInExternalEditor(
17587fa27ce4SDimitry Andric target->GetDebugger().GetExternalEditor(),
1759ac9a064cSDimitry Andric frame_sc.line_entry.GetFile(), frame_sc.line_entry.line)) {
17607fa27ce4SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e),
17617fa27ce4SDimitry Andric "OpenFileInExternalEditor failed: {0}");
17627fa27ce4SDimitry Andric }
1763f034231aSEd Maste }
1764f034231aSEd Maste }
1765f034231aSEd Maste }
1766f034231aSEd Maste
176714f1b3e8SDimitry Andric DumpUsingSettingsFormat(strm, start_frame, stop_format);
17684befb1f9SDimitry Andric }
1769f034231aSEd Maste
17704befb1f9SDimitry Andric size_t num_frames_shown = 0;
177114f1b3e8SDimitry Andric if (num_frames > 0) {
1772f034231aSEd Maste strm.IndentMore();
1773f034231aSEd Maste
1774f034231aSEd Maste const bool show_frame_info = true;
17754befb1f9SDimitry Andric const bool show_frame_unique = only_stacks;
1776e81d9d49SDimitry Andric const char *selected_frame_marker = nullptr;
17774befb1f9SDimitry Andric if (num_frames == 1 || only_stacks ||
177814f1b3e8SDimitry Andric (GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID()))
1779f034231aSEd Maste strm.IndentMore();
1780f21a844fSEd Maste else
1781f21a844fSEd Maste selected_frame_marker = "* ";
1782f21a844fSEd Maste
178314f1b3e8SDimitry Andric num_frames_shown = GetStackFrameList()->GetStatus(
178414f1b3e8SDimitry Andric strm, start_frame, num_frames, show_frame_info, num_frames_with_source,
17854befb1f9SDimitry Andric show_frame_unique, selected_frame_marker);
1786f21a844fSEd Maste if (num_frames == 1)
1787f034231aSEd Maste strm.IndentLess();
1788f034231aSEd Maste strm.IndentLess();
1789f034231aSEd Maste }
1790f034231aSEd Maste return num_frames_shown;
1791f034231aSEd Maste }
1792f034231aSEd Maste
GetDescription(Stream & strm,lldb::DescriptionLevel level,bool print_json_thread,bool print_json_stopinfo)179314f1b3e8SDimitry Andric bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level,
179414f1b3e8SDimitry Andric bool print_json_thread, bool print_json_stopinfo) {
179514f1b3e8SDimitry Andric const bool stop_format = false;
179614f1b3e8SDimitry Andric DumpUsingSettingsFormat(strm, 0, stop_format);
17970cac4ca3SEd Maste strm.Printf("\n");
17980cac4ca3SEd Maste
17990cac4ca3SEd Maste StructuredData::ObjectSP thread_info = GetExtendedInfo();
18000cac4ca3SEd Maste
180114f1b3e8SDimitry Andric if (print_json_thread || print_json_stopinfo) {
180214f1b3e8SDimitry Andric if (thread_info && print_json_thread) {
18030cac4ca3SEd Maste thread_info->Dump(strm);
18040cac4ca3SEd Maste strm.Printf("\n");
1805205afe67SEd Maste }
1806205afe67SEd Maste
180714f1b3e8SDimitry Andric if (print_json_stopinfo && m_stop_info_sp) {
18085e95aa85SEd Maste StructuredData::ObjectSP stop_info = m_stop_info_sp->GetExtendedInfo();
180914f1b3e8SDimitry Andric if (stop_info) {
1810205afe67SEd Maste stop_info->Dump(strm);
1811205afe67SEd Maste strm.Printf("\n");
1812205afe67SEd Maste }
18135e95aa85SEd Maste }
1814205afe67SEd Maste
18150cac4ca3SEd Maste return true;
18160cac4ca3SEd Maste }
18170cac4ca3SEd Maste
181814f1b3e8SDimitry Andric if (thread_info) {
181914f1b3e8SDimitry Andric StructuredData::ObjectSP activity =
182014f1b3e8SDimitry Andric thread_info->GetObjectForDotSeparatedPath("activity");
182114f1b3e8SDimitry Andric StructuredData::ObjectSP breadcrumb =
182214f1b3e8SDimitry Andric thread_info->GetObjectForDotSeparatedPath("breadcrumb");
182314f1b3e8SDimitry Andric StructuredData::ObjectSP messages =
182414f1b3e8SDimitry Andric thread_info->GetObjectForDotSeparatedPath("trace_messages");
18250cac4ca3SEd Maste
18260cac4ca3SEd Maste bool printed_activity = false;
182761b440f5SDimitry Andric if (activity && activity->GetType() == eStructuredDataTypeDictionary) {
18280cac4ca3SEd Maste StructuredData::Dictionary *activity_dict = activity->GetAsDictionary();
18290cac4ca3SEd Maste StructuredData::ObjectSP id = activity_dict->GetValueForKey("id");
18300cac4ca3SEd Maste StructuredData::ObjectSP name = activity_dict->GetValueForKey("name");
183161b440f5SDimitry Andric if (name && name->GetType() == eStructuredDataTypeString && id &&
183261b440f5SDimitry Andric id->GetType() == eStructuredDataTypeInteger) {
1833b76161e4SDimitry Andric strm.Format(" Activity '{0}', {1:x}\n",
1834b76161e4SDimitry Andric name->GetAsString()->GetValue(),
18357fa27ce4SDimitry Andric id->GetUnsignedIntegerValue());
18360cac4ca3SEd Maste }
18370cac4ca3SEd Maste printed_activity = true;
18380cac4ca3SEd Maste }
18390cac4ca3SEd Maste bool printed_breadcrumb = false;
184061b440f5SDimitry Andric if (breadcrumb && breadcrumb->GetType() == eStructuredDataTypeDictionary) {
18410cac4ca3SEd Maste if (printed_activity)
18420cac4ca3SEd Maste strm.Printf("\n");
184314f1b3e8SDimitry Andric StructuredData::Dictionary *breadcrumb_dict =
184414f1b3e8SDimitry Andric breadcrumb->GetAsDictionary();
184514f1b3e8SDimitry Andric StructuredData::ObjectSP breadcrumb_text =
184614f1b3e8SDimitry Andric breadcrumb_dict->GetValueForKey("name");
184714f1b3e8SDimitry Andric if (breadcrumb_text &&
184861b440f5SDimitry Andric breadcrumb_text->GetType() == eStructuredDataTypeString) {
1849b76161e4SDimitry Andric strm.Format(" Current Breadcrumb: {0}\n",
1850b76161e4SDimitry Andric breadcrumb_text->GetAsString()->GetValue());
18510cac4ca3SEd Maste }
18520cac4ca3SEd Maste printed_breadcrumb = true;
18530cac4ca3SEd Maste }
185461b440f5SDimitry Andric if (messages && messages->GetType() == eStructuredDataTypeArray) {
18550cac4ca3SEd Maste if (printed_breadcrumb)
18560cac4ca3SEd Maste strm.Printf("\n");
18570cac4ca3SEd Maste StructuredData::Array *messages_array = messages->GetAsArray();
18580cac4ca3SEd Maste const size_t msg_count = messages_array->GetSize();
185914f1b3e8SDimitry Andric if (msg_count > 0) {
18600cac4ca3SEd Maste strm.Printf(" %zu trace messages:\n", msg_count);
186114f1b3e8SDimitry Andric for (size_t i = 0; i < msg_count; i++) {
18620cac4ca3SEd Maste StructuredData::ObjectSP message = messages_array->GetItemAtIndex(i);
186361b440f5SDimitry Andric if (message && message->GetType() == eStructuredDataTypeDictionary) {
186414f1b3e8SDimitry Andric StructuredData::Dictionary *message_dict =
186514f1b3e8SDimitry Andric message->GetAsDictionary();
186614f1b3e8SDimitry Andric StructuredData::ObjectSP message_text =
186714f1b3e8SDimitry Andric message_dict->GetValueForKey("message");
186814f1b3e8SDimitry Andric if (message_text &&
186961b440f5SDimitry Andric message_text->GetType() == eStructuredDataTypeString) {
1870b76161e4SDimitry Andric strm.Format(" {0}\n", message_text->GetAsString()->GetValue());
18710cac4ca3SEd Maste }
18720cac4ca3SEd Maste }
18730cac4ca3SEd Maste }
18740cac4ca3SEd Maste }
18750cac4ca3SEd Maste }
18760cac4ca3SEd Maste }
18770cac4ca3SEd Maste
18780cac4ca3SEd Maste return true;
18790cac4ca3SEd Maste }
18800cac4ca3SEd Maste
GetStackFrameStatus(Stream & strm,uint32_t first_frame,uint32_t num_frames,bool show_frame_info,uint32_t num_frames_with_source)188114f1b3e8SDimitry Andric size_t Thread::GetStackFrameStatus(Stream &strm, uint32_t first_frame,
188214f1b3e8SDimitry Andric uint32_t num_frames, bool show_frame_info,
188314f1b3e8SDimitry Andric uint32_t num_frames_with_source) {
188414f1b3e8SDimitry Andric return GetStackFrameList()->GetStatus(
188514f1b3e8SDimitry Andric strm, first_frame, num_frames, show_frame_info, num_frames_with_source);
1886f034231aSEd Maste }
1887f034231aSEd Maste
GetUnwinder()1888cfca06d7SDimitry Andric Unwind &Thread::GetUnwinder() {
1889cfca06d7SDimitry Andric if (!m_unwinder_up)
1890cfca06d7SDimitry Andric m_unwinder_up = std::make_unique<UnwindLLDB>(*this);
1891cfca06d7SDimitry Andric return *m_unwinder_up;
1892f034231aSEd Maste }
1893f034231aSEd Maste
Flush()189414f1b3e8SDimitry Andric void Thread::Flush() {
1895f034231aSEd Maste ClearStackFrames();
1896f034231aSEd Maste m_reg_context_sp.reset();
1897f034231aSEd Maste }
1898f034231aSEd Maste
IsStillAtLastBreakpointHit()189914f1b3e8SDimitry Andric bool Thread::IsStillAtLastBreakpointHit() {
190014f1b3e8SDimitry Andric // If we are currently stopped at a breakpoint, always return that stopinfo
1901f73363f1SDimitry Andric // and don't reset it. This allows threads to maintain their breakpoint
1902f73363f1SDimitry Andric // stopinfo, such as when thread-stepping in multithreaded programs.
1903f034231aSEd Maste if (m_stop_info_sp) {
1904f034231aSEd Maste StopReason stop_reason = m_stop_info_sp->GetStopReason();
1905f034231aSEd Maste if (stop_reason == lldb::eStopReasonBreakpoint) {
1906f034231aSEd Maste uint64_t value = m_stop_info_sp->GetValue();
1907f034231aSEd Maste lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());
190814f1b3e8SDimitry Andric if (reg_ctx_sp) {
1909f034231aSEd Maste lldb::addr_t pc = reg_ctx_sp->GetPC();
191014f1b3e8SDimitry Andric BreakpointSiteSP bp_site_sp =
191114f1b3e8SDimitry Andric GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
191214f1b3e8SDimitry Andric if (bp_site_sp && static_cast<break_id_t>(value) == bp_site_sp->GetID())
1913f034231aSEd Maste return true;
1914f034231aSEd Maste }
1915f034231aSEd Maste }
1916f034231aSEd Maste }
1917f034231aSEd Maste return false;
1918f034231aSEd Maste }
1919866dcdacSEd Maste
StepIn(bool source_step,LazyBool step_in_avoids_code_without_debug_info,LazyBool step_out_avoids_code_without_debug_info)1920b76161e4SDimitry Andric Status Thread::StepIn(bool source_step,
19210cac4ca3SEd Maste LazyBool step_in_avoids_code_without_debug_info,
19220cac4ca3SEd Maste LazyBool step_out_avoids_code_without_debug_info)
1923866dcdacSEd Maste
1924866dcdacSEd Maste {
1925b76161e4SDimitry Andric Status error;
1926866dcdacSEd Maste Process *process = GetProcess().get();
192714f1b3e8SDimitry Andric if (StateIsStoppedState(process->GetState(), true)) {
1928866dcdacSEd Maste StackFrameSP frame_sp = GetStackFrameAtIndex(0);
1929866dcdacSEd Maste ThreadPlanSP new_plan_sp;
1930866dcdacSEd Maste const lldb::RunMode run_mode = eOnlyThisThread;
1931866dcdacSEd Maste const bool abort_other_plans = false;
1932866dcdacSEd Maste
193314f1b3e8SDimitry Andric if (source_step && frame_sp && frame_sp->HasDebugInformation()) {
1934866dcdacSEd Maste SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
193514f1b3e8SDimitry Andric new_plan_sp = QueueThreadPlanForStepInRange(
193694994d37SDimitry Andric abort_other_plans, sc.line_entry, sc, nullptr, run_mode, error,
19370cac4ca3SEd Maste step_in_avoids_code_without_debug_info,
19380cac4ca3SEd Maste step_out_avoids_code_without_debug_info);
193914f1b3e8SDimitry Andric } else {
194014f1b3e8SDimitry Andric new_plan_sp = QueueThreadPlanForStepSingleInstruction(
194194994d37SDimitry Andric false, abort_other_plans, run_mode, error);
1942866dcdacSEd Maste }
1943866dcdacSEd Maste
1944c0981da4SDimitry Andric new_plan_sp->SetIsControllingPlan(true);
1945866dcdacSEd Maste new_plan_sp->SetOkayToDiscard(false);
1946866dcdacSEd Maste
1947866dcdacSEd Maste // Why do we need to set the current thread by ID here???
1948866dcdacSEd Maste process->GetThreadList().SetSelectedThreadByID(GetID());
1949866dcdacSEd Maste error = process->Resume();
195014f1b3e8SDimitry Andric } else {
1951866dcdacSEd Maste error.SetErrorString("process not stopped");
1952866dcdacSEd Maste }
1953866dcdacSEd Maste return error;
1954866dcdacSEd Maste }
1955866dcdacSEd Maste
StepOver(bool source_step,LazyBool step_out_avoids_code_without_debug_info)1956b76161e4SDimitry Andric Status Thread::StepOver(bool source_step,
195714f1b3e8SDimitry Andric LazyBool step_out_avoids_code_without_debug_info) {
1958b76161e4SDimitry Andric Status error;
1959866dcdacSEd Maste Process *process = GetProcess().get();
196014f1b3e8SDimitry Andric if (StateIsStoppedState(process->GetState(), true)) {
1961866dcdacSEd Maste StackFrameSP frame_sp = GetStackFrameAtIndex(0);
1962866dcdacSEd Maste ThreadPlanSP new_plan_sp;
1963866dcdacSEd Maste
1964866dcdacSEd Maste const lldb::RunMode run_mode = eOnlyThisThread;
1965866dcdacSEd Maste const bool abort_other_plans = false;
1966866dcdacSEd Maste
196714f1b3e8SDimitry Andric if (source_step && frame_sp && frame_sp->HasDebugInformation()) {
1968866dcdacSEd Maste SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
196914f1b3e8SDimitry Andric new_plan_sp = QueueThreadPlanForStepOverRange(
197094994d37SDimitry Andric abort_other_plans, sc.line_entry, sc, run_mode, error,
19710cac4ca3SEd Maste step_out_avoids_code_without_debug_info);
197214f1b3e8SDimitry Andric } else {
197314f1b3e8SDimitry Andric new_plan_sp = QueueThreadPlanForStepSingleInstruction(
197494994d37SDimitry Andric true, abort_other_plans, run_mode, error);
1975866dcdacSEd Maste }
1976866dcdacSEd Maste
1977c0981da4SDimitry Andric new_plan_sp->SetIsControllingPlan(true);
1978866dcdacSEd Maste new_plan_sp->SetOkayToDiscard(false);
1979866dcdacSEd Maste
1980866dcdacSEd Maste // Why do we need to set the current thread by ID here???
1981866dcdacSEd Maste process->GetThreadList().SetSelectedThreadByID(GetID());
1982866dcdacSEd Maste error = process->Resume();
198314f1b3e8SDimitry Andric } else {
1984866dcdacSEd Maste error.SetErrorString("process not stopped");
1985866dcdacSEd Maste }
1986866dcdacSEd Maste return error;
1987866dcdacSEd Maste }
1988866dcdacSEd Maste
StepOut(uint32_t frame_idx)1989145449b1SDimitry Andric Status Thread::StepOut(uint32_t frame_idx) {
1990b76161e4SDimitry Andric Status error;
1991866dcdacSEd Maste Process *process = GetProcess().get();
199214f1b3e8SDimitry Andric if (StateIsStoppedState(process->GetState(), true)) {
1993866dcdacSEd Maste const bool first_instruction = false;
1994866dcdacSEd Maste const bool stop_other_threads = false;
1995866dcdacSEd Maste const bool abort_other_plans = false;
1996866dcdacSEd Maste
199714f1b3e8SDimitry Andric ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut(
199814f1b3e8SDimitry Andric abort_other_plans, nullptr, first_instruction, stop_other_threads,
1999145449b1SDimitry Andric eVoteYes, eVoteNoOpinion, frame_idx, error));
2000866dcdacSEd Maste
2001c0981da4SDimitry Andric new_plan_sp->SetIsControllingPlan(true);
2002866dcdacSEd Maste new_plan_sp->SetOkayToDiscard(false);
2003866dcdacSEd Maste
2004866dcdacSEd Maste // Why do we need to set the current thread by ID here???
2005866dcdacSEd Maste process->GetThreadList().SetSelectedThreadByID(GetID());
2006866dcdacSEd Maste error = process->Resume();
200714f1b3e8SDimitry Andric } else {
2008866dcdacSEd Maste error.SetErrorString("process not stopped");
2009866dcdacSEd Maste }
2010866dcdacSEd Maste return error;
2011866dcdacSEd Maste }
201294994d37SDimitry Andric
GetCurrentException()201394994d37SDimitry Andric ValueObjectSP Thread::GetCurrentException() {
201494994d37SDimitry Andric if (auto frame_sp = GetStackFrameAtIndex(0))
201594994d37SDimitry Andric if (auto recognized_frame = frame_sp->GetRecognizedFrame())
201694994d37SDimitry Andric if (auto e = recognized_frame->GetExceptionObject())
201794994d37SDimitry Andric return e;
201894994d37SDimitry Andric
20195f29bb8aSDimitry Andric // NOTE: Even though this behavior is generalized, only ObjC is actually
20205f29bb8aSDimitry Andric // supported at the moment.
20215f29bb8aSDimitry Andric for (LanguageRuntime *runtime : GetProcess()->GetLanguageRuntimes()) {
202294994d37SDimitry Andric if (auto e = runtime->GetExceptionObjectForThread(shared_from_this()))
202394994d37SDimitry Andric return e;
20245f29bb8aSDimitry Andric }
202594994d37SDimitry Andric
202694994d37SDimitry Andric return ValueObjectSP();
202794994d37SDimitry Andric }
202894994d37SDimitry Andric
GetCurrentExceptionBacktrace()202994994d37SDimitry Andric ThreadSP Thread::GetCurrentExceptionBacktrace() {
203094994d37SDimitry Andric ValueObjectSP exception = GetCurrentException();
20315f29bb8aSDimitry Andric if (!exception)
20325f29bb8aSDimitry Andric return ThreadSP();
203394994d37SDimitry Andric
20345f29bb8aSDimitry Andric // NOTE: Even though this behavior is generalized, only ObjC is actually
20355f29bb8aSDimitry Andric // supported at the moment.
20365f29bb8aSDimitry Andric for (LanguageRuntime *runtime : GetProcess()->GetLanguageRuntimes()) {
20375f29bb8aSDimitry Andric if (auto bt = runtime->GetBacktraceThreadFromException(exception))
20385f29bb8aSDimitry Andric return bt;
20395f29bb8aSDimitry Andric }
204094994d37SDimitry Andric
20415f29bb8aSDimitry Andric return ThreadSP();
204294994d37SDimitry Andric }
2043ecbca9f5SDimitry Andric
GetSiginfoValue()2044ecbca9f5SDimitry Andric lldb::ValueObjectSP Thread::GetSiginfoValue() {
2045ecbca9f5SDimitry Andric ProcessSP process_sp = GetProcess();
2046ecbca9f5SDimitry Andric assert(process_sp);
2047ecbca9f5SDimitry Andric Target &target = process_sp->GetTarget();
2048ecbca9f5SDimitry Andric PlatformSP platform_sp = target.GetPlatform();
2049ecbca9f5SDimitry Andric assert(platform_sp);
2050ecbca9f5SDimitry Andric ArchSpec arch = target.GetArchitecture();
2051ecbca9f5SDimitry Andric
2052ecbca9f5SDimitry Andric CompilerType type = platform_sp->GetSiginfoType(arch.GetTriple());
2053ecbca9f5SDimitry Andric if (!type.IsValid())
2054ecbca9f5SDimitry Andric return ValueObjectConstResult::Create(&target, Status("no siginfo_t for the platform"));
2055ecbca9f5SDimitry Andric
2056e3b55780SDimitry Andric std::optional<uint64_t> type_size = type.GetByteSize(nullptr);
2057ecbca9f5SDimitry Andric assert(type_size);
20584b4fe385SDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> data =
2059e3b55780SDimitry Andric GetSiginfo(*type_size);
2060ecbca9f5SDimitry Andric if (!data)
2061ecbca9f5SDimitry Andric return ValueObjectConstResult::Create(&target, Status(data.takeError()));
2062ecbca9f5SDimitry Andric
2063ecbca9f5SDimitry Andric DataExtractor data_extractor{data.get()->getBufferStart(), data.get()->getBufferSize(),
2064ecbca9f5SDimitry Andric process_sp->GetByteOrder(), arch.GetAddressByteSize()};
2065ecbca9f5SDimitry Andric return ValueObjectConstResult::Create(&target, type, ConstString("__lldb_siginfo"), data_extractor);
2066ecbca9f5SDimitry Andric }
2067