LLDB  mainline
ThreadPlanStepUntil.cpp
Go to the documentation of this file.
1 //===-- ThreadPlanStepUntil.cpp ---------------------------------*- C++ -*-===//
2 //
3 // 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
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
13 #include "lldb/Target/Process.h"
15 #include "lldb/Target/StopInfo.h"
16 #include "lldb/Target/Target.h"
17 #include "lldb/Utility/Log.h"
18 
19 using namespace lldb;
20 using namespace lldb_private;
21 
22 // ThreadPlanStepUntil: Run until we reach a given line number or step out of
23 // the current frame
24 
25 ThreadPlanStepUntil::ThreadPlanStepUntil(Thread &thread,
26  lldb::addr_t *address_list,
27  size_t num_addresses, bool stop_others,
28  uint32_t frame_idx)
29  : ThreadPlan(ThreadPlan::eKindStepUntil, "Step until", thread,
31  m_step_from_insn(LLDB_INVALID_ADDRESS),
32  m_return_bp_id(LLDB_INVALID_BREAK_ID),
33  m_return_addr(LLDB_INVALID_ADDRESS), m_stepped_out(false),
34  m_should_stop(false), m_ran_analyze(false), m_explains_stop(false),
35  m_until_points(), m_stop_others(stop_others) {
36  // Stash away our "until" addresses:
37  TargetSP target_sp(m_thread.CalculateTarget());
38 
39  StackFrameSP frame_sp(m_thread.GetStackFrameAtIndex(frame_idx));
40  if (frame_sp) {
41  m_step_from_insn = frame_sp->GetStackID().GetPC();
42  lldb::user_id_t thread_id = m_thread.GetID();
43 
44  // Find the return address and set a breakpoint there:
45  // FIXME - can we do this more securely if we know first_insn?
46 
47  StackFrameSP return_frame_sp(m_thread.GetStackFrameAtIndex(frame_idx + 1));
48  if (return_frame_sp) {
49  // TODO: add inline functionality
50  m_return_addr = return_frame_sp->GetStackID().GetPC();
51  Breakpoint *return_bp =
52  target_sp->CreateBreakpoint(m_return_addr, true, false).get();
53 
54  if (return_bp != nullptr) {
55  if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
57  return_bp->SetThreadID(thread_id);
58  m_return_bp_id = return_bp->GetID();
59  return_bp->SetBreakpointKind("until-return-backstop");
60  }
61  }
62 
63  m_stack_id = frame_sp->GetStackID();
64 
65  // Now set breakpoints on all our return addresses:
66  for (size_t i = 0; i < num_addresses; i++) {
67  Breakpoint *until_bp =
68  target_sp->CreateBreakpoint(address_list[i], true, false).get();
69  if (until_bp != nullptr) {
70  until_bp->SetThreadID(thread_id);
71  m_until_points[address_list[i]] = until_bp->GetID();
72  until_bp->SetBreakpointKind("until-target");
73  } else {
74  m_until_points[address_list[i]] = LLDB_INVALID_BREAK_ID;
75  }
76  }
77  }
78 }
79 
81 
82 void ThreadPlanStepUntil::Clear() {
83  TargetSP target_sp(m_thread.CalculateTarget());
84  if (target_sp) {
85  if (m_return_bp_id != LLDB_INVALID_BREAK_ID) {
86  target_sp->RemoveBreakpointByID(m_return_bp_id);
87  m_return_bp_id = LLDB_INVALID_BREAK_ID;
88  }
89 
90  until_collection::iterator pos, end = m_until_points.end();
91  for (pos = m_until_points.begin(); pos != end; pos++) {
92  target_sp->RemoveBreakpointByID((*pos).second);
93  }
94  }
95  m_until_points.clear();
97 }
98 
100  lldb::DescriptionLevel level) {
101  if (level == lldb::eDescriptionLevelBrief) {
102  s->Printf("step until");
103  if (m_stepped_out)
104  s->Printf(" - stepped out");
105  } else {
106  if (m_until_points.size() == 1)
107  s->Printf("Stepping from address 0x%" PRIx64 " until we reach 0x%" PRIx64
108  " using breakpoint %d",
109  (uint64_t)m_step_from_insn,
110  (uint64_t)(*m_until_points.begin()).first,
111  (*m_until_points.begin()).second);
112  else {
113  until_collection::iterator pos, end = m_until_points.end();
114  s->Printf("Stepping from address 0x%" PRIx64 " until we reach one of:",
115  (uint64_t)m_step_from_insn);
116  for (pos = m_until_points.begin(); pos != end; pos++) {
117  s->Printf("\n\t0x%" PRIx64 " (bp: %d)", (uint64_t)(*pos).first,
118  (*pos).second);
119  }
120  }
121  s->Printf(" stepped out address is 0x%" PRIx64 ".",
122  (uint64_t)m_return_addr);
123  }
124 }
125 
128  if (error)
129  error->PutCString(
130  "Could not create hardware breakpoint for thread plan.");
131  return false;
132  } else if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
133  if (error)
134  error->PutCString("Could not create return breakpoint.");
135  return false;
136  } else {
137  until_collection::iterator pos, end = m_until_points.end();
138  for (pos = m_until_points.begin(); pos != end; pos++) {
139  if (!LLDB_BREAK_ID_IS_VALID((*pos).second))
140  return false;
141  }
142  return true;
143  }
144 }
145 
147  if (m_ran_analyze)
148  return;
149 
150  StopInfoSP stop_info_sp = GetPrivateStopInfo();
151  m_should_stop = true;
152  m_explains_stop = false;
153 
154  if (stop_info_sp) {
155  StopReason reason = stop_info_sp->GetStopReason();
156 
157  if (reason == eStopReasonBreakpoint) {
158  // If this is OUR breakpoint, we're fine, otherwise we don't know why
159  // this happened...
160  BreakpointSiteSP this_site =
161  m_thread.GetProcess()->GetBreakpointSiteList().FindByID(
162  stop_info_sp->GetValue());
163  if (!this_site) {
164  m_explains_stop = false;
165  return;
166  }
167 
168  if (this_site->IsBreakpointAtThisSite(m_return_bp_id)) {
169  // If we are at our "step out" breakpoint, and the stack depth has
170  // shrunk, then this is indeed our stop. If the stack depth has grown,
171  // then we've hit our step out breakpoint recursively. If we are the
172  // only breakpoint at that location, then we do explain the stop, and
173  // we'll just continue. If there was another breakpoint here, then we
174  // don't explain the stop, but we won't mark ourselves Completed,
175  // because maybe that breakpoint will continue, and then we'll finish
176  // the "until".
177  bool done;
178  StackID cur_frame_zero_id;
179 
180  done = (m_stack_id < cur_frame_zero_id);
181 
182  if (done) {
183  m_stepped_out = true;
184  SetPlanComplete();
185  } else
186  m_should_stop = false;
187 
188  if (this_site->GetNumberOfOwners() == 1)
189  m_explains_stop = true;
190  else
191  m_explains_stop = false;
192  return;
193  } else {
194  // Check if we've hit one of our "until" breakpoints.
195  until_collection::iterator pos, end = m_until_points.end();
196  for (pos = m_until_points.begin(); pos != end; pos++) {
197  if (this_site->IsBreakpointAtThisSite((*pos).second)) {
198  // If we're at the right stack depth, then we're done.
199 
200  bool done;
201  StackID frame_zero_id =
202  m_thread.GetStackFrameAtIndex(0)->GetStackID();
203 
204  if (frame_zero_id == m_stack_id)
205  done = true;
206  else if (frame_zero_id < m_stack_id)
207  done = false;
208  else {
209  StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(1);
210 
211  // But if we can't even unwind one frame we should just get out
212  // of here & stop...
213  if (older_frame_sp) {
214  const SymbolContext &older_context =
215  older_frame_sp->GetSymbolContext(eSymbolContextEverything);
216  SymbolContext stack_context;
218  &stack_context);
219 
220  done = (older_context == stack_context);
221  } else
222  done = false;
223  }
224 
225  if (done)
226  SetPlanComplete();
227  else
228  m_should_stop = false;
229 
230  // Otherwise we've hit this breakpoint recursively. If we're the
231  // only breakpoint here, then we do explain the stop, and we'll
232  // continue. If not then we should let higher plans handle this
233  // stop.
234  if (this_site->GetNumberOfOwners() == 1)
235  m_explains_stop = true;
236  else {
237  m_should_stop = true;
238  m_explains_stop = false;
239  }
240  return;
241  }
242  }
243  }
244  // If we get here we haven't hit any of our breakpoints, so let the
245  // higher plans take care of the stop.
246  m_explains_stop = false;
247  return;
248  } else if (IsUsuallyUnexplainedStopReason(reason)) {
249  m_explains_stop = false;
250  } else {
251  m_explains_stop = true;
252  }
253  }
254 }
255 
257  // We don't explain signals or breakpoints (breakpoints that handle stepping
258  // in or out will be handled by a child plan.
259  AnalyzeStop();
260  return m_explains_stop;
261 }
262 
264  // If we've told our self in ExplainsStop that we plan to continue, then do
265  // so here. Otherwise, as long as this thread has stopped for a reason, we
266  // will stop.
267 
268  StopInfoSP stop_info_sp = GetPrivateStopInfo();
269  if (!stop_info_sp || stop_info_sp->GetStopReason() == eStopReasonNone)
270  return false;
271 
272  AnalyzeStop();
273  return m_should_stop;
274 }
275 
276 bool ThreadPlanStepUntil::StopOthers() { return m_stop_others; }
277 
279 
281  bool current_plan) {
282  if (current_plan) {
283  TargetSP target_sp(m_thread.CalculateTarget());
284  if (target_sp) {
285  Breakpoint *return_bp =
286  target_sp->GetBreakpointByID(m_return_bp_id).get();
287  if (return_bp != nullptr)
288  return_bp->SetEnabled(true);
289 
290  until_collection::iterator pos, end = m_until_points.end();
291  for (pos = m_until_points.begin(); pos != end; pos++) {
292  Breakpoint *until_bp =
293  target_sp->GetBreakpointByID((*pos).second).get();
294  if (until_bp != nullptr)
295  until_bp->SetEnabled(true);
296  }
297  }
298  }
299 
300  m_should_stop = true;
301  m_ran_analyze = false;
302  m_explains_stop = false;
303  return true;
304 }
305 
307  TargetSP target_sp(m_thread.CalculateTarget());
308  if (target_sp) {
309  Breakpoint *return_bp = target_sp->GetBreakpointByID(m_return_bp_id).get();
310  if (return_bp != nullptr)
311  return_bp->SetEnabled(false);
312 
313  until_collection::iterator pos, end = m_until_points.end();
314  for (pos = m_until_points.begin(); pos != end; pos++) {
315  Breakpoint *until_bp = target_sp->GetBreakpointByID((*pos).second).get();
316  if (until_bp != nullptr)
317  until_bp->SetEnabled(false);
318  }
319  }
320  return true;
321 }
322 
324  // I'm letting "PlanExplainsStop" do all the work, and just reporting that
325  // here.
326  bool done = false;
327  if (IsPlanComplete()) {
329  if (log)
330  log->Printf("Completed step until plan.");
331 
332  Clear();
333  done = true;
334  }
335  if (done)
337 
338  return done;
339 }
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
bool IsUsuallyUnexplainedStopReason(lldb::StopReason)
Definition: ThreadPlan.cpp:145
lldb::StopInfoSP GetPrivateStopInfo()
Definition: ThreadPlan.h:564
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
bool DoWillResume(lldb::StateType resume_state, bool current_plan) override
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:33
General Outline: A breakpoint has four main parts, a filter, a resolver, the list of breakpoint locat...
Definition: Breakpoint.h:78
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:49
void SetBreakpointKind(const char *kind)
Set the "kind" description for a breakpoint.
Definition: Breakpoint.h:456
SymbolContextScope * GetSymbolContextScope() const
Definition: StackID.h:37
void SetEnabled(bool enable) override
If enable is true, enable the breakpoint, if false disable it.
Definition: Breakpoint.cpp:287
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
uint64_t user_id_t
Definition: lldb-types.h:84
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
lldb::TargetSP CalculateTarget() override
Definition: Thread.cpp:1584
void GetDescription(Stream *s, lldb::DescriptionLevel level) override
Print a description of this thread to the stream s.
lldb::break_id_t GetID() const
Definition: Stoppoint.cpp:22
virtual bool MischiefManaged()
Definition: ThreadPlan.cpp:57
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
bool IsHardware() const
Definition: Breakpoint.h:524
void SetPlanComplete(bool success=true)
Definition: ThreadPlan.cpp:51
lldb::ProcessSP GetProcess() const
Definition: Thread.h:154
bool HasResolvedLocations() const
Return whether this breakpoint has any resolved locations.
Definition: Breakpoint.cpp:849
virtual void CalculateSymbolContext(SymbolContext *sc)=0
Reconstruct the object&#39;s symbol context into sc.
uint64_t addr_t
Definition: lldb-types.h:83
bool ShouldStop(Event *event_ptr) override
Definition: SBAddress.h:15
void SetThreadID(lldb::tid_t thread_id)
Set the valid thread to be checked when the breakpoint is hit.
Definition: Breakpoint.cpp:349
#define LLDB_INVALID_BREAK_ID
Definition: lldb-defines.h:49
bool ValidatePlan(Stream *error) override
Returns whether this plan could be successfully created.
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:395
#define LLDB_BREAK_ID_IS_VALID(bid)
Definition: lldb-defines.h:51
lldb::StateType GetPlanRunState() override
#define LIBLLDB_LOG_STEP
Definition: Logging.h:21
bool DoPlanExplainsStop(Event *event_ptr) override
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
Process or thread is running and can&#39;t be examined.