LLDB  mainline
ThreadPlanStepOut.cpp
Go to the documentation of this file.
1 //===-- ThreadPlanStepOut.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 
11 #include "lldb/Core/Value.h"
13 #include "lldb/Symbol/Block.h"
14 #include "lldb/Symbol/Function.h"
15 #include "lldb/Symbol/Symbol.h"
16 #include "lldb/Symbol/Type.h"
17 #include "lldb/Target/ABI.h"
18 #include "lldb/Target/Process.h"
20 #include "lldb/Target/StopInfo.h"
21 #include "lldb/Target/Target.h"
24 #include "lldb/Utility/Log.h"
25 
26 #include <memory>
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 
31 uint32_t ThreadPlanStepOut::s_default_flag_values = 0;
32 
33 // ThreadPlanStepOut: Step out of the current frame
34 ThreadPlanStepOut::ThreadPlanStepOut(
35  Thread &thread, SymbolContext *context, bool first_insn, bool stop_others,
36  Vote stop_vote, Vote run_vote, uint32_t frame_idx,
37  LazyBool step_out_avoids_code_without_debug_info,
38  bool continue_to_next_branch, bool gather_return_value)
39  : ThreadPlan(ThreadPlan::eKindStepOut, "Step out", thread, stop_vote,
40  run_vote),
41  ThreadPlanShouldStopHere(this), m_step_from_insn(LLDB_INVALID_ADDRESS),
42  m_return_bp_id(LLDB_INVALID_BREAK_ID),
43  m_return_addr(LLDB_INVALID_ADDRESS), m_stop_others(stop_others),
44  m_immediate_step_from_function(nullptr),
45  m_calculate_return_value(gather_return_value) {
48  SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
49 
50  m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
51 
52  uint32_t return_frame_index = frame_idx + 1;
53  StackFrameSP return_frame_sp(
54  m_thread.GetStackFrameAtIndex(return_frame_index));
55  StackFrameSP immediate_return_from_sp(
56  m_thread.GetStackFrameAtIndex(frame_idx));
57 
58  if (!return_frame_sp || !immediate_return_from_sp)
59  return; // we can't do anything here. ValidatePlan() will return false.
60 
61  // While stepping out, behave as-if artificial frames are not present.
62  while (return_frame_sp->IsArtificial()) {
63  m_stepped_past_frames.push_back(return_frame_sp);
64 
65  ++return_frame_index;
66  return_frame_sp = m_thread.GetStackFrameAtIndex(return_frame_index);
67 
68  // We never expect to see an artificial frame without a regular ancestor.
69  // If this happens, log the issue and defensively refuse to step out.
70  if (!return_frame_sp) {
71  LLDB_LOG(log, "Can't step out of frame with artificial ancestors");
72  return;
73  }
74  }
75 
76  m_step_out_to_id = return_frame_sp->GetStackID();
77  m_immediate_step_from_id = immediate_return_from_sp->GetStackID();
78 
79  // If the frame directly below the one we are returning to is inlined, we
80  // have to be a little more careful. It is non-trivial to determine the real
81  // "return code address" for an inlined frame, so we have to work our way to
82  // that frame and then step out.
83  if (immediate_return_from_sp->IsInlined()) {
84  if (frame_idx > 0) {
85  // First queue a plan that gets us to this inlined frame, and when we get
86  // there we'll queue a second plan that walks us out of this frame.
87  m_step_out_to_inline_plan_sp = std::make_shared<ThreadPlanStepOut>(
88  m_thread, nullptr, false, stop_others, eVoteNoOpinion, eVoteNoOpinion,
89  frame_idx - 1, eLazyBoolNo, continue_to_next_branch);
90  static_cast<ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get())
91  ->SetShouldStopHereCallbacks(nullptr, nullptr);
92  m_step_out_to_inline_plan_sp->SetPrivate(true);
93  } else {
94  // If we're already at the inlined frame we're stepping through, then
95  // just do that now.
96  QueueInlinedStepPlan(false);
97  }
98  } else {
99  // Find the return address and set a breakpoint there:
100  // FIXME - can we do this more securely if we know first_insn?
101 
102  Address return_address(return_frame_sp->GetFrameCodeAddress());
103  if (continue_to_next_branch) {
104  SymbolContext return_address_sc;
105  AddressRange range;
106  Address return_address_decr_pc = return_address;
107  if (return_address_decr_pc.GetOffset() > 0)
108  return_address_decr_pc.Slide(-1);
109 
110  return_address_decr_pc.CalculateSymbolContext(
111  &return_address_sc, lldb::eSymbolContextLineEntry);
112  if (return_address_sc.line_entry.IsValid()) {
113  const bool include_inlined_functions = false;
114  range = return_address_sc.line_entry.GetSameLineContiguousAddressRange(
115  include_inlined_functions);
116  if (range.GetByteSize() > 0) {
117  return_address =
118  m_thread.GetProcess()->AdvanceAddressToNextBranchInstruction(
119  return_address, range);
120  }
121  }
122  }
123  m_return_addr =
124  return_address.GetLoadAddress(&m_thread.GetProcess()->GetTarget());
125 
126  if (m_return_addr == LLDB_INVALID_ADDRESS)
127  return;
128 
129  Breakpoint *return_bp = m_thread.CalculateTarget()
130  ->CreateBreakpoint(m_return_addr, true, false)
131  .get();
132 
133  if (return_bp != nullptr) {
134  if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
136  return_bp->SetThreadID(m_thread.GetID());
137  m_return_bp_id = return_bp->GetID();
138  return_bp->SetBreakpointKind("step-out");
139  }
140 
141  if (immediate_return_from_sp) {
142  const SymbolContext &sc =
143  immediate_return_from_sp->GetSymbolContext(eSymbolContextFunction);
144  if (sc.function) {
145  m_immediate_step_from_function = sc.function;
146  }
147  }
148  }
149 }
150 
151 void ThreadPlanStepOut::SetupAvoidNoDebug(
152  LazyBool step_out_avoids_code_without_debug_info) {
153  bool avoid_nodebug = true;
154  switch (step_out_avoids_code_without_debug_info) {
155  case eLazyBoolYes:
156  avoid_nodebug = true;
157  break;
158  case eLazyBoolNo:
159  avoid_nodebug = false;
160  break;
161  case eLazyBoolCalculate:
162  avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
163  break;
164  }
165  if (avoid_nodebug)
167  else
169 }
170 
172  if (m_step_out_to_inline_plan_sp)
173  m_thread.QueueThreadPlan(m_step_out_to_inline_plan_sp, false);
174  else if (m_step_through_inline_plan_sp)
175  m_thread.QueueThreadPlan(m_step_through_inline_plan_sp, false);
176 }
177 
179  if (m_return_bp_id != LLDB_INVALID_BREAK_ID)
180  m_thread.CalculateTarget()->RemoveBreakpointByID(m_return_bp_id);
181 }
182 
184  lldb::DescriptionLevel level) {
185  if (level == lldb::eDescriptionLevelBrief)
186  s->Printf("step out");
187  else {
188  if (m_step_out_to_inline_plan_sp)
189  s->Printf("Stepping out to inlined frame so we can walk through it.");
190  else if (m_step_through_inline_plan_sp)
191  s->Printf("Stepping out by stepping through inlined function.");
192  else {
193  s->Printf("Stepping out from ");
194  Address tmp_address;
195  if (tmp_address.SetLoadAddress(m_step_from_insn, &GetTarget())) {
198  } else {
199  s->Printf("address 0x%" PRIx64 "", (uint64_t)m_step_from_insn);
200  }
201 
202  // FIXME: find some useful way to present the m_return_id, since there may
203  // be multiple copies of the
204  // same function on the stack.
205 
206  s->Printf(" returning to frame at ");
207  if (tmp_address.SetLoadAddress(m_return_addr, &GetTarget())) {
210  } else {
211  s->Printf("address 0x%" PRIx64 "", (uint64_t)m_return_addr);
212  }
213 
214  if (level == eDescriptionLevelVerbose)
215  s->Printf(" using breakpoint site %d", m_return_bp_id);
216  }
217  }
218 
219  s->Printf("\n");
220  for (StackFrameSP frame_sp : m_stepped_past_frames) {
221  s->Printf("Stepped out past: ");
222  frame_sp->DumpUsingSettingsFormat(s);
223  }
224 }
225 
227  if (m_step_out_to_inline_plan_sp)
228  return m_step_out_to_inline_plan_sp->ValidatePlan(error);
229 
230  if (m_step_through_inline_plan_sp)
231  return m_step_through_inline_plan_sp->ValidatePlan(error);
232 
234  if (error)
235  error->PutCString(
236  "Could not create hardware breakpoint for thread plan.");
237  return false;
238  }
239 
240  if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
241  if (error)
242  error->PutCString("Could not create return address breakpoint.");
243  return false;
244  }
245 
246  return true;
247 }
248 
250  // If the step out plan is done, then we just need to step through the
251  // inlined frame.
252  if (m_step_out_to_inline_plan_sp) {
253  return m_step_out_to_inline_plan_sp->MischiefManaged();
254  } else if (m_step_through_inline_plan_sp) {
255  if (m_step_through_inline_plan_sp->MischiefManaged()) {
256  CalculateReturnValue();
257  SetPlanComplete();
258  return true;
259  } else
260  return false;
261  } else if (m_step_out_further_plan_sp) {
262  return m_step_out_further_plan_sp->MischiefManaged();
263  }
264 
265  // We don't explain signals or breakpoints (breakpoints that handle stepping
266  // in or out will be handled by a child plan.
267 
268  StopInfoSP stop_info_sp = GetPrivateStopInfo();
269  if (stop_info_sp) {
270  StopReason reason = stop_info_sp->GetStopReason();
271  if (reason == eStopReasonBreakpoint) {
272  // If this is OUR breakpoint, we're fine, otherwise we don't know why
273  // this happened...
274  BreakpointSiteSP site_sp(
275  m_thread.GetProcess()->GetBreakpointSiteList().FindByID(
276  stop_info_sp->GetValue()));
277  if (site_sp && site_sp->IsBreakpointAtThisSite(m_return_bp_id)) {
278  bool done;
279 
280  StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
281 
282  if (m_step_out_to_id == frame_zero_id)
283  done = true;
284  else if (m_step_out_to_id < frame_zero_id) {
285  // Either we stepped past the breakpoint, or the stack ID calculation
286  // was incorrect and we should probably stop.
287  done = true;
288  } else {
289  done = (m_immediate_step_from_id < frame_zero_id);
290  }
291 
292  if (done) {
294  CalculateReturnValue();
295  SetPlanComplete();
296  }
297  }
298 
299  // If there was only one owner, then we're done. But if we also hit
300  // some user breakpoint on our way out, we should mark ourselves as
301  // done, but also not claim to explain the stop, since it is more
302  // important to report the user breakpoint than the step out
303  // completion.
304 
305  if (site_sp->GetNumberOfOwners() == 1)
306  return true;
307  }
308  return false;
309  } else if (IsUsuallyUnexplainedStopReason(reason))
310  return false;
311  else
312  return true;
313  }
314  return true;
315 }
316 
318  if (IsPlanComplete())
319  return true;
320 
321  bool done = false;
322  if (m_step_out_to_inline_plan_sp) {
323  if (m_step_out_to_inline_plan_sp->MischiefManaged()) {
324  // Now step through the inlined stack we are in:
325  if (QueueInlinedStepPlan(true)) {
326  // If we can't queue a plan to do this, then just call ourselves done.
327  m_step_out_to_inline_plan_sp.reset();
328  SetPlanComplete(false);
329  return true;
330  } else
331  done = true;
332  } else
333  return m_step_out_to_inline_plan_sp->ShouldStop(event_ptr);
334  } else if (m_step_through_inline_plan_sp) {
335  if (m_step_through_inline_plan_sp->MischiefManaged())
336  done = true;
337  else
338  return m_step_through_inline_plan_sp->ShouldStop(event_ptr);
339  } else if (m_step_out_further_plan_sp) {
340  if (m_step_out_further_plan_sp->MischiefManaged())
341  m_step_out_further_plan_sp.reset();
342  else
343  return m_step_out_further_plan_sp->ShouldStop(event_ptr);
344  }
345 
346  if (!done) {
347  StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
348  done = !(frame_zero_id < m_step_out_to_id);
349  }
350 
351  // The normal step out computations think we are done, so all we need to do
352  // is consult the ShouldStopHere, and we are done.
353 
354  if (done) {
356  CalculateReturnValue();
357  SetPlanComplete();
358  } else {
359  m_step_out_further_plan_sp =
361  done = false;
362  }
363  }
364 
365  return done;
366 }
367 
368 bool ThreadPlanStepOut::StopOthers() { return m_stop_others; }
369 
371 
373  bool current_plan) {
374  if (m_step_out_to_inline_plan_sp || m_step_through_inline_plan_sp)
375  return true;
376 
377  if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
378  return false;
379 
380  if (current_plan) {
381  Breakpoint *return_bp =
382  m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get();
383  if (return_bp != nullptr)
384  return_bp->SetEnabled(true);
385  }
386  return true;
387 }
388 
390  if (m_return_bp_id != LLDB_INVALID_BREAK_ID) {
391  Breakpoint *return_bp =
392  m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get();
393  if (return_bp != nullptr)
394  return_bp->SetEnabled(false);
395  }
396 
397  return true;
398 }
399 
401  if (IsPlanComplete()) {
402  // Did I reach my breakpoint? If so I'm done.
403  //
404  // I also check the stack depth, since if we've blown past the breakpoint
405  // for some
406  // reason and we're now stopping for some other reason altogether, then
407  // we're done with this step out operation.
408 
410  if (log)
411  log->Printf("Completed step out plan.");
412  if (m_return_bp_id != LLDB_INVALID_BREAK_ID) {
413  m_thread.CalculateTarget()->RemoveBreakpointByID(m_return_bp_id);
414  m_return_bp_id = LLDB_INVALID_BREAK_ID;
415  }
416 
418  return true;
419  } else {
420  return false;
421  }
422 }
423 
425  // Now figure out the range of this inlined block, and set up a "step through
426  // range" plan for that. If we've been provided with a context, then use the
427  // block in that context.
428  StackFrameSP immediate_return_from_sp(m_thread.GetStackFrameAtIndex(0));
429  if (!immediate_return_from_sp)
430  return false;
431 
433  if (log) {
434  StreamString s;
435  immediate_return_from_sp->Dump(&s, true, false);
436  log->Printf("Queuing inlined frame to step past: %s.", s.GetData());
437  }
438 
439  Block *from_block = immediate_return_from_sp->GetFrameBlock();
440  if (from_block) {
441  Block *inlined_block = from_block->GetContainingInlinedBlock();
442  if (inlined_block) {
443  size_t num_ranges = inlined_block->GetNumRanges();
444  AddressRange inline_range;
445  if (inlined_block->GetRangeAtIndex(0, inline_range)) {
446  SymbolContext inlined_sc;
447  inlined_block->CalculateSymbolContext(&inlined_sc);
448  inlined_sc.target_sp = GetTarget().shared_from_this();
449  RunMode run_mode =
450  m_stop_others ? lldb::eOnlyThisThread : lldb::eAllThreads;
451  const LazyBool avoid_no_debug = eLazyBoolNo;
452 
453  m_step_through_inline_plan_sp =
454  std::make_shared<ThreadPlanStepOverRange>(
455  m_thread, inline_range, inlined_sc, run_mode, avoid_no_debug);
456  ThreadPlanStepOverRange *step_through_inline_plan_ptr =
457  static_cast<ThreadPlanStepOverRange *>(
458  m_step_through_inline_plan_sp.get());
459  m_step_through_inline_plan_sp->SetPrivate(true);
460 
461  step_through_inline_plan_ptr->SetOkayToDiscard(true);
462  StreamString errors;
463  if (!step_through_inline_plan_ptr->ValidatePlan(&errors)) {
464  // FIXME: Log this failure.
465  delete step_through_inline_plan_ptr;
466  return false;
467  }
468 
469  for (size_t i = 1; i < num_ranges; i++) {
470  if (inlined_block->GetRangeAtIndex(i, inline_range))
471  step_through_inline_plan_ptr->AddRange(inline_range);
472  }
473 
474  if (queue_now)
475  m_thread.QueueThreadPlan(m_step_through_inline_plan_sp, false);
476  return true;
477  }
478  }
479  }
480 
481  return false;
482 }
483 
484 void ThreadPlanStepOut::CalculateReturnValue() {
485  if (m_return_valobj_sp)
486  return;
487 
488  if (!m_calculate_return_value)
489  return;
490 
491  if (m_immediate_step_from_function != nullptr) {
492  CompilerType return_compiler_type =
493  m_immediate_step_from_function->GetCompilerType()
495  if (return_compiler_type) {
496  lldb::ABISP abi_sp = m_thread.GetProcess()->GetABI();
497  if (abi_sp)
498  m_return_valobj_sp =
499  abi_sp->GetReturnValueObject(m_thread, return_compiler_type);
500  }
501  }
502 }
503 
505  // If we are still lower on the stack than the frame we are returning to,
506  // then there's something for us to do. Otherwise, we're stale.
507 
508  StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
509  return !(frame_zero_id < m_step_out_to_id);
510 }
void SetShouldStopHereCallbacks(const ThreadPlanShouldStopHereCallbacks *callbacks, void *baton)
bool DoPlanExplainsStop(Event *event_ptr) override
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
lldb::TargetSP target_sp
The Target for a given query.
bool IsUsuallyUnexplainedStopReason(lldb::StopReason)
Definition: ThreadPlan.cpp:145
lldb::StopInfoSP GetPrivateStopInfo()
Definition: ThreadPlan.h:564
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
bool ShouldStop(Event *event_ptr) override
lldb::addr_t GetByteSize() const
Get accessor for the byte size of this range.
Definition: AddressRange.h:232
uint32_t CalculateSymbolContext(SymbolContext *sc, lldb::SymbolContextItem resolve_scope=lldb::eSymbolContextEverything) const
Reconstruct a symbol context from an address.
Definition: Address.cpp:782
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
bool QueueInlinedStepPlan(bool queue_now)
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:33
bool IsValid() const
Check if a line entry object is valid.
Definition: LineEntry.cpp:47
General Outline: A breakpoint has four main parts, a filter, a resolver, the list of breakpoint locat...
Definition: Breakpoint.h:78
AddressRange GetSameLineContiguousAddressRange(bool include_inlined_functions) const
Give the range for this LineEntry + any additional LineEntries for this same source line that are con...
Definition: LineEntry.cpp:193
bool Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style=DumpStyleInvalid, uint32_t addr_byte_size=UINT32_MAX) const
Dump a description of this object to a Stream.
Definition: Address.cpp:374
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
const char * GetData() const
Definition: StreamString.h:43
A class that describes a single lexical block.
Definition: Block.h:41
bool SetLoadAddress(lldb::addr_t load_addr, Target *target, bool allow_section_end=false)
Set the address to represent load_addr.
Definition: Address.cpp:998
#define LLDB_LOG(log,...)
Definition: Log.h:209
Function * function
The Function for a given query.
lldb::addr_t GetOffset() const
Get the section relative offset value.
Definition: Address.h:317
ValueType Clear(ValueType mask=~(ValueType) 0)
Clear one or more flags.
Definition: Flags.h:72
bool GetRangeAtIndex(uint32_t range_idx, AddressRange &range)
Definition: Block.cpp:293
bool Slide(int64_t offset)
Definition: Address.h:430
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
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
lldb::TargetSP CalculateTarget() override
Definition: Thread.cpp:1584
lldb::break_id_t GetID() const
Definition: Stoppoint.cpp:22
bool InvokeShouldStopHereCallback(lldb::FrameComparison operation, Status &status)
Block * GetContainingInlinedBlock()
Get the inlined block that contains this block.
Definition: Block.cpp:198
virtual lldb::RegisterContextSP GetRegisterContext()=0
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 CalculateSymbolContext(SymbolContext *sc) override
Reconstruct the object&#39;s symbol context into sc.
Definition: Block.cpp:126
A section + offset based address class.
Definition: Address.h:80
ValueType Set(ValueType mask)
Set one or more flags by logical OR&#39;ing mask with the current flags.
Definition: Flags.h:84
void SetPlanComplete(bool success=true)
Definition: ThreadPlan.cpp:51
lldb::ProcessSP GetProcess() const
Definition: Thread.h:154
bool ValidatePlan(Stream *error) override
Returns whether this plan could be successfully created.
bool HasResolvedLocations() const
Return whether this breakpoint has any resolved locations.
Definition: Breakpoint.cpp:849
CompilerType GetCompilerType()
Definition: Function.cpp:469
Display the details about what an address resolves to.
Definition: Address.h:108
Status QueueThreadPlan(lldb::ThreadPlanSP &plan_sp, bool abort_other_plans)
Queues a generic thread plan.
Definition: Thread.cpp:1179
void GetDescription(Stream *s, lldb::DescriptionLevel level) override
Print a description of this thread to the stream s.
Display as the load address (if resolved).
Definition: Address.h:104
LineEntry line_entry
The LineEntry for a given query.
size_t GetNumRanges() const
Definition: Block.h:361
Definition: SBAddress.h:15
CompilerType GetFunctionReturnType() const
bool DoWillResume(lldb::StateType resume_state, bool current_plan) override
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
virtual lldb::ThreadPlanSP QueueStepOutFromHerePlan(Flags &flags, lldb::FrameComparison operation, Status &status)
Thread & GetThread()
Returns the Thread that is using this thread plan.
Definition: ThreadPlan.h:372
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:395
bool GetStepOutAvoidsNoDebug() const
Definition: Thread.cpp:162
#define LIBLLDB_LOG_STEP
Definition: Logging.h:21
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
A section + offset based address range class.
Definition: AddressRange.h:32
lldb::StateType GetPlanRunState() override
Process or thread is running and can&#39;t be examined.