]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Target/ThreadPlan.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / source / Target / ThreadPlan.cpp
1 //===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Target/ThreadPlan.h"
15 #include "lldb/Core/Debugger.h"
16 #include "lldb/Core/Log.h"
17 #include "lldb/Core/State.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/RegisterContext.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Target/Thread.h"
22 #include "lldb/Utility/ConvertEnum.h"
23
24 using namespace lldb;
25 using namespace lldb_private;
26
27 //----------------------------------------------------------------------
28 // ThreadPlan constructor
29 //----------------------------------------------------------------------
30 ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,
31                        Vote stop_vote, Vote run_vote)
32     : m_thread(thread), m_stop_vote(stop_vote), m_run_vote(run_vote),
33       m_kind(kind), m_name(name), m_plan_complete_mutex(),
34       m_cached_plan_explains_stop(eLazyBoolCalculate), m_plan_complete(false),
35       m_plan_private(false), m_okay_to_discard(true), m_is_master_plan(false),
36       m_plan_succeeded(true) {
37   SetID(GetNextID());
38 }
39
40 //----------------------------------------------------------------------
41 // Destructor
42 //----------------------------------------------------------------------
43 ThreadPlan::~ThreadPlan() = default;
44
45 bool ThreadPlan::PlanExplainsStop(Event *event_ptr) {
46   if (m_cached_plan_explains_stop == eLazyBoolCalculate) {
47     bool actual_value = DoPlanExplainsStop(event_ptr);
48     m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
49     return actual_value;
50   } else {
51     return m_cached_plan_explains_stop == eLazyBoolYes;
52   }
53 }
54
55 bool ThreadPlan::IsPlanComplete() {
56   std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
57   return m_plan_complete;
58 }
59
60 void ThreadPlan::SetPlanComplete(bool success) {
61   std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
62   m_plan_complete = true;
63   m_plan_succeeded = success;
64 }
65
66 bool ThreadPlan::MischiefManaged() {
67   std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
68   // Mark the plan is complete, but don't override the success flag.
69   m_plan_complete = true;
70   return true;
71 }
72
73 Vote ThreadPlan::ShouldReportStop(Event *event_ptr) {
74   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
75
76   if (m_stop_vote == eVoteNoOpinion) {
77     ThreadPlan *prev_plan = GetPreviousPlan();
78     if (prev_plan) {
79       Vote prev_vote = prev_plan->ShouldReportStop(event_ptr);
80       if (log)
81         log->Printf("ThreadPlan::ShouldReportStop() returning previous thread "
82                     "plan vote: %s",
83                     GetVoteAsCString(prev_vote));
84       return prev_vote;
85     }
86   }
87   if (log)
88     log->Printf("ThreadPlan::ShouldReportStop() returning vote: %s",
89                 GetVoteAsCString(m_stop_vote));
90   return m_stop_vote;
91 }
92
93 Vote ThreadPlan::ShouldReportRun(Event *event_ptr) {
94   if (m_run_vote == eVoteNoOpinion) {
95     ThreadPlan *prev_plan = GetPreviousPlan();
96     if (prev_plan)
97       return prev_plan->ShouldReportRun(event_ptr);
98   }
99   return m_run_vote;
100 }
101
102 bool ThreadPlan::StopOthers() {
103   ThreadPlan *prev_plan;
104   prev_plan = GetPreviousPlan();
105   return (prev_plan == nullptr) ? false : prev_plan->StopOthers();
106 }
107
108 void ThreadPlan::SetStopOthers(bool new_value) {
109   // SetStopOthers doesn't work up the hierarchy.  You have to set the
110   // explicit ThreadPlan you want to affect.
111 }
112
113 bool ThreadPlan::WillResume(StateType resume_state, bool current_plan) {
114   m_cached_plan_explains_stop = eLazyBoolCalculate;
115
116   if (current_plan) {
117     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
118
119     if (log) {
120       RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
121       assert(reg_ctx);
122       addr_t pc = reg_ctx->GetPC();
123       addr_t sp = reg_ctx->GetSP();
124       addr_t fp = reg_ctx->GetFP();
125       log->Printf(
126           "%s Thread #%u (0x%p): tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64
127           ", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", "
128           "plan = '%s', state = %s, stop others = %d",
129           __FUNCTION__, m_thread.GetIndexID(), static_cast<void *>(&m_thread),
130           m_thread.GetID(), static_cast<uint64_t>(pc),
131           static_cast<uint64_t>(sp), static_cast<uint64_t>(fp), m_name.c_str(),
132           StateAsCString(resume_state), StopOthers());
133     }
134   }
135   return DoWillResume(resume_state, current_plan);
136 }
137
138 lldb::user_id_t ThreadPlan::GetNextID() {
139   static uint32_t g_nextPlanID = 0;
140   return ++g_nextPlanID;
141 }
142
143 void ThreadPlan::DidPush() {}
144
145 void ThreadPlan::WillPop() {}
146
147 bool ThreadPlan::OkayToDiscard() {
148   return IsMasterPlan() ? m_okay_to_discard : true;
149 }
150
151 lldb::StateType ThreadPlan::RunState() {
152   if (m_tracer_sp && m_tracer_sp->TracingEnabled() &&
153       m_tracer_sp->SingleStepEnabled())
154     return eStateStepping;
155   else
156     return GetPlanRunState();
157 }
158
159 bool ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason) {
160   switch (reason) {
161   case eStopReasonWatchpoint:
162   case eStopReasonSignal:
163   case eStopReasonException:
164   case eStopReasonExec:
165   case eStopReasonThreadExiting:
166   case eStopReasonInstrumentation:
167     return true;
168   default:
169     return false;
170   }
171 }
172
173 //----------------------------------------------------------------------
174 // ThreadPlanNull
175 //----------------------------------------------------------------------
176
177 ThreadPlanNull::ThreadPlanNull(Thread &thread)
178     : ThreadPlan(ThreadPlan::eKindNull, "Null Thread Plan", thread,
179                  eVoteNoOpinion, eVoteNoOpinion) {}
180
181 ThreadPlanNull::~ThreadPlanNull() = default;
182
183 void ThreadPlanNull::GetDescription(Stream *s, lldb::DescriptionLevel level) {
184   s->PutCString("Null thread plan - thread has been destroyed.");
185 }
186
187 bool ThreadPlanNull::ValidatePlan(Stream *error) {
188 #ifdef LLDB_CONFIGURATION_DEBUG
189   fprintf(stderr,
190           "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
191           ", ptid = 0x%" PRIx64 ")",
192           LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
193 #else
194   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
195   if (log)
196     log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
197                ", ptid = 0x%" PRIx64 ")",
198                LLVM_PRETTY_FUNCTION, m_thread.GetID(),
199                m_thread.GetProtocolID());
200 #endif
201   return true;
202 }
203
204 bool ThreadPlanNull::ShouldStop(Event *event_ptr) {
205 #ifdef LLDB_CONFIGURATION_DEBUG
206   fprintf(stderr,
207           "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
208           ", ptid = 0x%" PRIx64 ")",
209           LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
210 #else
211   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
212   if (log)
213     log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
214                ", ptid = 0x%" PRIx64 ")",
215                LLVM_PRETTY_FUNCTION, m_thread.GetID(),
216                m_thread.GetProtocolID());
217 #endif
218   return true;
219 }
220
221 bool ThreadPlanNull::WillStop() {
222 #ifdef LLDB_CONFIGURATION_DEBUG
223   fprintf(stderr,
224           "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
225           ", ptid = 0x%" PRIx64 ")",
226           LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
227 #else
228   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
229   if (log)
230     log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
231                ", ptid = 0x%" PRIx64 ")",
232                LLVM_PRETTY_FUNCTION, m_thread.GetID(),
233                m_thread.GetProtocolID());
234 #endif
235   return true;
236 }
237
238 bool ThreadPlanNull::DoPlanExplainsStop(Event *event_ptr) {
239 #ifdef LLDB_CONFIGURATION_DEBUG
240   fprintf(stderr,
241           "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
242           ", ptid = 0x%" PRIx64 ")",
243           LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
244 #else
245   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
246   if (log)
247     log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
248                ", ptid = 0x%" PRIx64 ")",
249                LLVM_PRETTY_FUNCTION, m_thread.GetID(),
250                m_thread.GetProtocolID());
251 #endif
252   return true;
253 }
254
255 // The null plan is never done.
256 bool ThreadPlanNull::MischiefManaged() {
257 // The null plan is never done.
258 #ifdef LLDB_CONFIGURATION_DEBUG
259   fprintf(stderr,
260           "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
261           ", ptid = 0x%" PRIx64 ")",
262           LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
263 #else
264   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
265   if (log)
266     log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
267                ", ptid = 0x%" PRIx64 ")",
268                LLVM_PRETTY_FUNCTION, m_thread.GetID(),
269                m_thread.GetProtocolID());
270 #endif
271   return false;
272 }
273
274 lldb::StateType ThreadPlanNull::GetPlanRunState() {
275 // Not sure what to return here.  This is a dead thread.
276 #ifdef LLDB_CONFIGURATION_DEBUG
277   fprintf(stderr,
278           "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
279           ", ptid = 0x%" PRIx64 ")",
280           LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
281 #else
282   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
283   if (log)
284     log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
285                ", ptid = 0x%" PRIx64 ")",
286                LLVM_PRETTY_FUNCTION, m_thread.GetID(),
287                m_thread.GetProtocolID());
288 #endif
289   return eStateRunning;
290 }