blob: 1d8cc18db4d65755056b41a4ca85026e1f1c2fd4 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Chris Lattner30fdc8d2010-06-08 16:52:24 +00006//
7//===----------------------------------------------------------------------===//
8
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +00009#include "lldb/Target/ThreadPlan.h"
Jim Ingham06e827c2010-11-11 19:26:09 +000010#include "lldb/Core/Debugger.h"
Jim Ingham06e827c2010-11-11 19:26:09 +000011#include "lldb/Target/Process.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000012#include "lldb/Target/RegisterContext.h"
Jim Ingham06e827c2010-11-11 19:26:09 +000013#include "lldb/Target/Target.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000014#include "lldb/Target/Thread.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000015#include "lldb/Utility/Log.h"
Pavel Labathd821c992018-08-07 11:07:21 +000016#include "lldb/Utility/State.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017
18using namespace lldb;
19using namespace lldb_private;
20
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021// ThreadPlan constructor
Kate Stoneb9c1b512016-09-06 20:57:50 +000022ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,
23 Vote stop_vote, Vote run_vote)
24 : m_thread(thread), m_stop_vote(stop_vote), m_run_vote(run_vote),
Jonas Devliegheree103ae92018-11-15 01:18:15 +000025 m_takes_iteration_count(false), m_could_not_resolve_hw_bp(false),
Kate Stoneb9c1b512016-09-06 20:57:50 +000026 m_kind(kind), m_name(name), m_plan_complete_mutex(),
27 m_cached_plan_explains_stop(eLazyBoolCalculate), m_plan_complete(false),
28 m_plan_private(false), m_okay_to_discard(true), m_is_master_plan(false),
29 m_plan_succeeded(true) {
30 SetID(GetNextID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +000031}
32
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033// Destructor
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +000034ThreadPlan::~ThreadPlan() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035
Kate Stoneb9c1b512016-09-06 20:57:50 +000036bool ThreadPlan::PlanExplainsStop(Event *event_ptr) {
37 if (m_cached_plan_explains_stop == eLazyBoolCalculate) {
38 bool actual_value = DoPlanExplainsStop(event_ptr);
39 m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
40 return actual_value;
41 } else {
42 return m_cached_plan_explains_stop == eLazyBoolYes;
43 }
44}
45
46bool ThreadPlan::IsPlanComplete() {
47 std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
48 return m_plan_complete;
49}
50
51void ThreadPlan::SetPlanComplete(bool success) {
52 std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
53 m_plan_complete = true;
54 m_plan_succeeded = success;
55}
56
57bool ThreadPlan::MischiefManaged() {
58 std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
59 // Mark the plan is complete, but don't override the success flag.
60 m_plan_complete = true;
61 return true;
62}
63
64Vote ThreadPlan::ShouldReportStop(Event *event_ptr) {
65 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
66
67 if (m_stop_vote == eVoteNoOpinion) {
68 ThreadPlan *prev_plan = GetPreviousPlan();
69 if (prev_plan) {
70 Vote prev_vote = prev_plan->ShouldReportStop(event_ptr);
Pavel Labath05d382c2017-02-03 18:50:45 +000071 LLDB_LOG(log, "returning previous thread plan vote: {0}", prev_vote);
Kate Stoneb9c1b512016-09-06 20:57:50 +000072 return prev_vote;
Jim Ingham221d51c2013-05-08 00:35:16 +000073 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000074 }
Pavel Labath05d382c2017-02-03 18:50:45 +000075 LLDB_LOG(log, "Returning vote: {0}", m_stop_vote);
Kate Stoneb9c1b512016-09-06 20:57:50 +000076 return m_stop_vote;
77}
78
79Vote ThreadPlan::ShouldReportRun(Event *event_ptr) {
80 if (m_run_vote == eVoteNoOpinion) {
81 ThreadPlan *prev_plan = GetPreviousPlan();
82 if (prev_plan)
83 return prev_plan->ShouldReportRun(event_ptr);
84 }
85 return m_run_vote;
86}
87
88bool ThreadPlan::StopOthers() {
89 ThreadPlan *prev_plan;
90 prev_plan = GetPreviousPlan();
91 return (prev_plan == nullptr) ? false : prev_plan->StopOthers();
92}
93
94void ThreadPlan::SetStopOthers(bool new_value) {
Adrian Prantl05097242018-04-30 16:49:04 +000095 // SetStopOthers doesn't work up the hierarchy. You have to set the explicit
96 // ThreadPlan you want to affect.
Kate Stoneb9c1b512016-09-06 20:57:50 +000097}
98
99bool ThreadPlan::WillResume(StateType resume_state, bool current_plan) {
100 m_cached_plan_explains_stop = eLazyBoolCalculate;
101
102 if (current_plan) {
103 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
104
105 if (log) {
106 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
107 assert(reg_ctx);
108 addr_t pc = reg_ctx->GetPC();
109 addr_t sp = reg_ctx->GetSP();
110 addr_t fp = reg_ctx->GetFP();
111 log->Printf(
112 "%s Thread #%u (0x%p): tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64
113 ", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", "
114 "plan = '%s', state = %s, stop others = %d",
115 __FUNCTION__, m_thread.GetIndexID(), static_cast<void *>(&m_thread),
116 m_thread.GetID(), static_cast<uint64_t>(pc),
117 static_cast<uint64_t>(sp), static_cast<uint64_t>(fp), m_name.c_str(),
118 StateAsCString(resume_state), StopOthers());
Jim Ingham221d51c2013-05-08 00:35:16 +0000119 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000120 }
121 return DoWillResume(resume_state, current_plan);
Jim Ingham221d51c2013-05-08 00:35:16 +0000122}
123
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124lldb::user_id_t ThreadPlan::GetNextID() {
125 static uint32_t g_nextPlanID = 0;
126 return ++g_nextPlanID;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000127}
128
Kate Stoneb9c1b512016-09-06 20:57:50 +0000129void ThreadPlan::DidPush() {}
130
131void ThreadPlan::WillPop() {}
132
133bool ThreadPlan::OkayToDiscard() {
134 return IsMasterPlan() ? m_okay_to_discard : true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000135}
136
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137lldb::StateType ThreadPlan::RunState() {
138 if (m_tracer_sp && m_tracer_sp->TracingEnabled() &&
139 m_tracer_sp->SingleStepEnabled())
140 return eStateStepping;
141 else
142 return GetPlanRunState();
143}
144
145bool ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason) {
146 switch (reason) {
147 case eStopReasonWatchpoint:
148 case eStopReasonSignal:
149 case eStopReasonException:
150 case eStopReasonExec:
151 case eStopReasonThreadExiting:
152 case eStopReasonInstrumentation:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000154 default:
155 return false;
156 }
Jim Ingham9b03fa02015-07-23 19:55:02 +0000157}
158
Greg Clayton6e10f142013-07-30 00:23:06 +0000159// ThreadPlanNull
Greg Clayton6e10f142013-07-30 00:23:06 +0000160
Kate Stoneb9c1b512016-09-06 20:57:50 +0000161ThreadPlanNull::ThreadPlanNull(Thread &thread)
162 : ThreadPlan(ThreadPlan::eKindNull, "Null Thread Plan", thread,
163 eVoteNoOpinion, eVoteNoOpinion) {}
Greg Clayton6e10f142013-07-30 00:23:06 +0000164
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +0000165ThreadPlanNull::~ThreadPlanNull() = default;
Greg Clayton6e10f142013-07-30 00:23:06 +0000166
Kate Stoneb9c1b512016-09-06 20:57:50 +0000167void ThreadPlanNull::GetDescription(Stream *s, lldb::DescriptionLevel level) {
168 s->PutCString("Null thread plan - thread has been destroyed.");
Greg Clayton6e10f142013-07-30 00:23:06 +0000169}
170
Kate Stoneb9c1b512016-09-06 20:57:50 +0000171bool ThreadPlanNull::ValidatePlan(Stream *error) {
Greg Clayton6e10f142013-07-30 00:23:06 +0000172#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173 fprintf(stderr,
174 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
175 ", ptid = 0x%" PRIx64 ")",
176 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06 +0000177#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000178 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
179 if (log)
180 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
181 ", ptid = 0x%" PRIx64 ")",
182 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
183 m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06 +0000184#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000185 return true;
Greg Clayton6e10f142013-07-30 00:23:06 +0000186}
187
Kate Stoneb9c1b512016-09-06 20:57:50 +0000188bool ThreadPlanNull::ShouldStop(Event *event_ptr) {
Greg Clayton6e10f142013-07-30 00:23:06 +0000189#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50 +0000190 fprintf(stderr,
191 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
192 ", ptid = 0x%" PRIx64 ")",
193 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06 +0000194#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000195 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
196 if (log)
197 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
198 ", ptid = 0x%" PRIx64 ")",
199 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
200 m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06 +0000201#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000202 return true;
Greg Clayton6e10f142013-07-30 00:23:06 +0000203}
204
Kate Stoneb9c1b512016-09-06 20:57:50 +0000205bool ThreadPlanNull::WillStop() {
Greg Clayton6e10f142013-07-30 00:23:06 +0000206#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50 +0000207 fprintf(stderr,
208 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
209 ", ptid = 0x%" PRIx64 ")",
210 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06 +0000211#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000212 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
213 if (log)
214 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
215 ", ptid = 0x%" PRIx64 ")",
216 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
217 m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06 +0000218#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000219 return true;
Greg Clayton6e10f142013-07-30 00:23:06 +0000220}
221
Kate Stoneb9c1b512016-09-06 20:57:50 +0000222bool ThreadPlanNull::DoPlanExplainsStop(Event *event_ptr) {
Greg Clayton6e10f142013-07-30 00:23:06 +0000223#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50 +0000224 fprintf(stderr,
225 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
226 ", ptid = 0x%" PRIx64 ")",
227 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06 +0000228#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000229 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
230 if (log)
231 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
232 ", ptid = 0x%" PRIx64 ")",
233 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
234 m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06 +0000235#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000236 return true;
Greg Clayton6e10f142013-07-30 00:23:06 +0000237}
238
239// The null plan is never done.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000240bool ThreadPlanNull::MischiefManaged() {
241// The null plan is never done.
Greg Clayton6e10f142013-07-30 00:23:06 +0000242#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50 +0000243 fprintf(stderr,
244 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
245 ", ptid = 0x%" PRIx64 ")",
246 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06 +0000247#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000248 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
249 if (log)
250 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
251 ", ptid = 0x%" PRIx64 ")",
252 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
253 m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06 +0000254#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000255 return false;
Greg Clayton6e10f142013-07-30 00:23:06 +0000256}
257
Kate Stoneb9c1b512016-09-06 20:57:50 +0000258lldb::StateType ThreadPlanNull::GetPlanRunState() {
259// Not sure what to return here. This is a dead thread.
Greg Clayton6e10f142013-07-30 00:23:06 +0000260#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50 +0000261 fprintf(stderr,
262 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
263 ", ptid = 0x%" PRIx64 ")",
264 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06 +0000265#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000266 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
267 if (log)
268 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
269 ", ptid = 0x%" PRIx64 ")",
270 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
271 m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06 +0000272#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000273 return eStateRunning;
Greg Clayton6e10f142013-07-30 00:23:06 +0000274}