LLDB  mainline
ThreadPlanStepRange.cpp
Go to the documentation of this file.
1 //===-- ThreadPlanStepRange.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 
12 #include "lldb/Core/Disassembler.h"
13 #include "lldb/Symbol/Function.h"
14 #include "lldb/Symbol/Symbol.h"
16 #include "lldb/Target/Process.h"
18 #include "lldb/Target/StopInfo.h"
19 #include "lldb/Target/Target.h"
20 #include "lldb/Target/Thread.h"
22 #include "lldb/Utility/Log.h"
23 #include "lldb/Utility/Stream.h"
24 
25 using namespace lldb;
26 using namespace lldb_private;
27 
28 // ThreadPlanStepRange: Step through a stack range, either stepping over or
29 // into based on the value of \a type.
30 
31 ThreadPlanStepRange::ThreadPlanStepRange(ThreadPlanKind kind, const char *name,
32  Thread &thread,
33  const AddressRange &range,
34  const SymbolContext &addr_context,
35  lldb::RunMode stop_others,
36  bool given_ranges_only)
37  : ThreadPlan(kind, name, thread, eVoteNoOpinion, eVoteNoOpinion),
38  m_addr_context(addr_context), m_address_ranges(),
39  m_stop_others(stop_others), m_stack_id(), m_parent_stack_id(),
40  m_no_more_plans(false), m_first_run_event(true), m_use_fast_step(false),
41  m_given_ranges_only(given_ranges_only) {
43  AddRange(range);
44  m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
45  StackFrameSP parent_stack = m_thread.GetStackFrameAtIndex(1);
46  if (parent_stack)
47  m_parent_stack_id = parent_stack->GetStackID();
48 }
49 
51 
53  // See if we can find a "next range" breakpoint:
55 }
56 
59  if (error)
60  error->PutCString(
61  "Could not create hardware breakpoint for thread plan.");
62  return false;
63  }
64  return true;
65 }
66 
69 
70  const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo;
71  if (log)
72  log->Printf("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n",
73  vote);
74  return vote;
75 }
76 
78  // For now I'm just adding the ranges. At some point we may want to condense
79  // the ranges if they overlap, though I don't think it is likely to be very
80  // important.
81  m_address_ranges.push_back(new_range);
82 
83  // Fill the slot for this address range with an empty DisassemblerSP in the
84  // instruction ranges. I want the indices to match, but I don't want to do
85  // the work to disassemble this range if I don't step into it.
86  m_instruction_ranges.push_back(DisassemblerSP());
87 }
88 
90  size_t num_ranges = m_address_ranges.size();
91  if (num_ranges == 1) {
92  m_address_ranges[0].Dump(s, m_thread.CalculateTarget().get(),
94  } else {
95  for (size_t i = 0; i < num_ranges; i++) {
96  s->Printf(" %" PRIu64 ": ", uint64_t(i));
97  m_address_ranges[i].Dump(s, m_thread.CalculateTarget().get(),
99  }
100  }
101 }
102 
105  bool ret_value = false;
106 
107  lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC();
108 
109  size_t num_ranges = m_address_ranges.size();
110  for (size_t i = 0; i < num_ranges; i++) {
111  ret_value = m_address_ranges[i].ContainsLoadAddress(
112  pc_load_addr, m_thread.CalculateTarget().get());
113  if (ret_value)
114  break;
115  }
116 
117  if (!ret_value && !m_given_ranges_only) {
118  // See if we've just stepped to another part of the same line number...
119  StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get();
120 
121  SymbolContext new_context(
122  frame->GetSymbolContext(eSymbolContextEverything));
124  new_context.line_entry.IsValid()) {
126  new_context.line_entry.original_file) {
127  if (m_addr_context.line_entry.line == new_context.line_entry.line) {
128  m_addr_context = new_context;
129  const bool include_inlined_functions =
132  include_inlined_functions));
133  ret_value = true;
134  if (log) {
135  StreamString s;
139 
140  log->Printf(
141  "Step range plan stepped to another range of same line: %s",
142  s.GetData());
143  }
144  } else if (new_context.line_entry.line == 0) {
145  new_context.line_entry.line = m_addr_context.line_entry.line;
146  m_addr_context = new_context;
147  const bool include_inlined_functions =
150  include_inlined_functions));
151  ret_value = true;
152  if (log) {
153  StreamString s;
157 
158  log->Printf("Step range plan stepped to a range at linenumber 0 "
159  "stepping through that range: %s",
160  s.GetData());
161  }
162  } else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(
163  m_thread.CalculateTarget().get()) != pc_load_addr) {
164  // Another thing that sometimes happens here is that we step out of
165  // one line into the MIDDLE of another line. So far I mostly see
166  // this due to bugs in the debug information. But we probably don't
167  // want to be in the middle of a line range, so in that case reset
168  // the stepping range to the line we've stepped into the middle of
169  // and continue.
170  m_addr_context = new_context;
171  m_address_ranges.clear();
173  ret_value = true;
174  if (log) {
175  StreamString s;
179 
180  log->Printf("Step range plan stepped to the middle of new "
181  "line(%d): %s, continuing to clear this line.",
182  new_context.line_entry.line, s.GetData());
183  }
184  }
185  }
186  }
187  }
188 
189  if (!ret_value && log)
190  log->Printf("Step range plan out of range to 0x%" PRIx64, pc_load_addr);
191 
192  return ret_value;
193 }
194 
196  lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
197  if (m_addr_context.function != nullptr) {
199  cur_pc, m_thread.CalculateTarget().get());
203  return range.ContainsLoadAddress(cur_pc, m_thread.CalculateTarget().get());
204  }
205  return false;
206 }
207 
208 // FIXME: This should also handle inlining if we aren't going to do inlining in
209 // the
210 // main stack.
211 //
212 // Ideally we should remember the whole stack frame list, and then compare that
213 // to the current list.
214 
216  FrameComparison frame_order;
217 
218  StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
219 
220  if (cur_frame_id == m_stack_id) {
221  frame_order = eFrameCompareEqual;
222  } else if (cur_frame_id < m_stack_id) {
223  frame_order = eFrameCompareYounger;
224  } else {
225  StackFrameSP cur_parent_frame = m_thread.GetStackFrameAtIndex(1);
226  StackID cur_parent_id;
227  if (cur_parent_frame)
228  cur_parent_id = cur_parent_frame->GetStackID();
229  if (m_parent_stack_id.IsValid() && cur_parent_id.IsValid() &&
230  m_parent_stack_id == cur_parent_id)
231  frame_order = eFrameCompareSameParent;
232  else
233  frame_order = eFrameCompareOlder;
234  }
235  return frame_order;
236 }
237 
241 }
242 
244  lldb::addr_t addr, size_t &range_index, size_t &insn_offset) {
245  size_t num_ranges = m_address_ranges.size();
246  for (size_t i = 0; i < num_ranges; i++) {
247  if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget())) {
248  // Some joker added a zero size range to the stepping range...
249  if (m_address_ranges[i].GetByteSize() == 0)
250  return nullptr;
251 
252  if (!m_instruction_ranges[i]) {
253  // Disassemble the address range given:
255  const char *plugin_name = nullptr;
256  const char *flavor = nullptr;
257  const bool prefer_file_cache = true;
258  m_instruction_ranges[i] = Disassembler::DisassembleRange(
259  GetTarget().GetArchitecture(), plugin_name, flavor, exe_ctx,
260  m_address_ranges[i], prefer_file_cache);
261  }
262  if (!m_instruction_ranges[i])
263  return nullptr;
264  else {
265  // Find where we are in the instruction list as well. If we aren't at
266  // an instruction, return nullptr. In this case, we're probably lost,
267  // and shouldn't try to do anything fancy.
268 
269  insn_offset =
270  m_instruction_ranges[i]
271  ->GetInstructionList()
272  .GetIndexOfInstructionAtLoadAddress(addr, GetTarget());
273  if (insn_offset == UINT32_MAX)
274  return nullptr;
275  else {
276  range_index = i;
277  return &m_instruction_ranges[i]->GetInstructionList();
278  }
279  }
280  }
281  }
282  return nullptr;
283 }
284 
286  if (m_next_branch_bp_sp) {
288  if (log)
289  log->Printf("Removing next branch breakpoint: %d.",
290  m_next_branch_bp_sp->GetID());
292  m_next_branch_bp_sp.reset();
294  }
295 }
296 
299  return true;
300 
302  // Stepping through ranges using breakpoints doesn't work yet, but with this
303  // off we fall back to instruction single stepping.
304  if (!m_use_fast_step)
305  return false;
306 
307  lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC();
308  // Find the current address in our address ranges, and fetch the disassembly
309  // if we haven't already:
310  size_t pc_index;
311  size_t range_index;
312  InstructionList *instructions =
313  GetInstructionsForAddress(cur_addr, range_index, pc_index);
314  if (instructions == nullptr)
315  return false;
316  else {
317  Target &target = GetThread().GetProcess()->GetTarget();
318  uint32_t branch_index;
319  branch_index =
320  instructions->GetIndexOfNextBranchInstruction(pc_index, target);
321 
322  Address run_to_address;
323 
324  // If we didn't find a branch, run to the end of the range.
325  if (branch_index == UINT32_MAX) {
326  uint32_t last_index = instructions->GetSize() - 1;
327  if (last_index - pc_index > 1) {
328  InstructionSP last_inst =
329  instructions->GetInstructionAtIndex(last_index);
330  size_t last_inst_size = last_inst->GetOpcode().GetByteSize();
331  run_to_address = last_inst->GetAddress();
332  run_to_address.Slide(last_inst_size);
333  }
334  } else if (branch_index - pc_index > 1) {
335  run_to_address =
336  instructions->GetInstructionAtIndex(branch_index)->GetAddress();
337  }
338 
339  if (run_to_address.IsValid()) {
340  const bool is_internal = true;
342  GetTarget().CreateBreakpoint(run_to_address, is_internal, false);
343  if (m_next_branch_bp_sp) {
344 
345  if (m_next_branch_bp_sp->IsHardware() &&
346  !m_next_branch_bp_sp->HasResolvedLocations())
348 
349  if (log) {
351  BreakpointLocationSP bp_loc =
352  m_next_branch_bp_sp->GetLocationAtIndex(0);
353  if (bp_loc) {
354  BreakpointSiteSP bp_site = bp_loc->GetBreakpointSite();
355  if (bp_site) {
356  bp_site_id = bp_site->GetID();
357  }
358  }
359  log->Printf("ThreadPlanStepRange::SetNextBranchBreakpoint - Setting "
360  "breakpoint %d (site %d) to run to address 0x%" PRIx64,
361  m_next_branch_bp_sp->GetID(), bp_site_id,
362  run_to_address.GetLoadAddress(
363  &m_thread.GetProcess()->GetTarget()));
364  }
365 
366  m_next_branch_bp_sp->SetThreadID(m_thread.GetID());
367  m_next_branch_bp_sp->SetBreakpointKind("next-branch-location");
368 
369  return true;
370  } else
371  return false;
372  }
373  }
374  return false;
375 }
376 
378  lldb::StopInfoSP stop_info_sp) {
380  if (!m_next_branch_bp_sp)
381  return false;
382 
383  break_id_t bp_site_id = stop_info_sp->GetValue();
384  BreakpointSiteSP bp_site_sp =
385  m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id);
386  if (!bp_site_sp)
387  return false;
388  else if (!bp_site_sp->IsBreakpointAtThisSite(m_next_branch_bp_sp->GetID()))
389  return false;
390  else {
391  // If we've hit the next branch breakpoint, then clear it.
392  size_t num_owners = bp_site_sp->GetNumberOfOwners();
393  bool explains_stop = true;
394  // If all the owners are internal, then we are probably just stepping over
395  // this range from multiple threads, or multiple frames, so we want to
396  // continue. If one is not internal, then we should not explain the stop,
397  // and let the user breakpoint handle the stop.
398  for (size_t i = 0; i < num_owners; i++) {
399  if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) {
400  explains_stop = false;
401  break;
402  }
403  }
404  if (log)
405  log->Printf("ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit "
406  "next range breakpoint which has %" PRIu64
407  " owners - explains stop: %u.",
408  (uint64_t)num_owners, explains_stop);
410  return explains_stop;
411  }
412 }
413 
414 bool ThreadPlanStepRange::WillStop() { return true; }
415 
418  return eStateRunning;
419  else
420  return eStateStepping;
421 }
422 
424  // If we have pushed some plans between ShouldStop & MischiefManaged, then
425  // we're not done...
426  // I do this check first because we might have stepped somewhere that will
427  // fool InRange into
428  // thinking it needs to step past the end of that line. This happens, for
429  // instance, when stepping over inlined code that is in the middle of the
430  // current line.
431 
432  if (!m_no_more_plans)
433  return false;
434 
435  bool done = true;
436  if (!IsPlanComplete()) {
437  if (InRange()) {
438  done = false;
439  } else {
441  done = (frame_order != eFrameCompareOlder) ? m_no_more_plans : true;
442  }
443  }
444 
445  if (done) {
447  if (log)
448  log->Printf("Completed step through range plan.");
451  return true;
452  } else {
453  return false;
454  }
455 }
456 
460 
461  if (frame_order == eFrameCompareOlder) {
462  if (log) {
463  log->Printf("ThreadPlanStepRange::IsPlanStale returning true, we've "
464  "stepped out.");
465  }
466  return true;
467  } else if (frame_order == eFrameCompareEqual && InSymbol()) {
468  // If we are not in a place we should step through, we've gotten stale. One
469  // tricky bit here is that some stubs don't push a frame, so we should.
470  // check that we are in the same symbol.
471  if (!InRange()) {
472  // Set plan Complete when we reach next instruction just after the range
473  lldb::addr_t addr = m_thread.GetRegisterContext()->GetPC() - 1;
474  size_t num_ranges = m_address_ranges.size();
475  for (size_t i = 0; i < num_ranges; i++) {
476  bool in_range = m_address_ranges[i].ContainsLoadAddress(
477  addr, m_thread.CalculateTarget().get());
478  if (in_range) {
479  SetPlanComplete();
480  }
481  }
482  return true;
483  }
484  }
485  return false;
486 }
Address & GetAddressRef()
Definition: Symbol.h:56
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
bool RemoveBreakpointByID(lldb::break_id_t break_id)
Definition: Target.cpp:940
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
int32_t break_id_t
Definition: lldb-types.h:88
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
FileSpec original_file
The original source file, from debug info.
Definition: LineEntry.h:153
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:33
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition: Address.cpp:292
bool IsValid() const
Check if a line entry object is valid.
Definition: LineEntry.cpp:47
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
std::vector< AddressRange > m_address_ranges
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:49
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
const char * GetData() const
Definition: StreamString.h:43
void AddRange(const AddressRange &new_range)
uint32_t GetIndexOfNextBranchInstruction(uint32_t start, Target &target) const
Symbol * symbol
The Symbol for a given query.
lldb::FrameComparison CompareCurrentFrameToStartFrame()
const SymbolContext & GetSymbolContext(lldb::SymbolContextItem resolve_scope)
Provide a SymbolContext for this StackFrame&#39;s current pc value.
Definition: StackFrame.cpp:267
Function * function
The Function for a given query.
bool ContainsLoadAddress(const Address &so_addr, Target *target) const
Check if a section offset so_addr when represented as a load address is contained within this object&#39;...
#define UINT32_MAX
Definition: lldb-defines.h:31
bool Slide(int64_t offset)
Definition: Address.h:430
ThreadPlanKind GetKind() const
Definition: ThreadPlan.h:468
lldb::addr_t GetByteSize() const
Definition: Symbol.cpp:408
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
bool ValidatePlan(Stream *error) override
Returns whether this plan could be successfully created.
lldb::TargetSP CalculateTarget() override
Definition: Thread.cpp:1584
static lldb::DisassemblerSP DisassembleRange(const ArchSpec &arch, const char *plugin_name, const char *flavor, const ExecutionContext &exe_ctx, const AddressRange &disasm_range, bool prefer_file_cache)
InstructionList * GetInstructionsForAddress(lldb::addr_t addr, size_t &range_index, size_t &insn_offset)
virtual lldb::RegisterContextSP GetRegisterContext()=0
virtual bool MischiefManaged()
Definition: ThreadPlan.cpp:57
uint32_t line
The source line number, or zero if there is no line number information.
Definition: LineEntry.h:154
bool ValueIsAddress() const
Definition: Symbol.cpp:114
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
Process or thread is in the process of stepping and can not be examined.
bool IsValid() const
Check if the object state is valid.
Definition: Address.h:343
A section + offset based address class.
Definition: Address.h:80
void SetPlanComplete(bool success=true)
Definition: ThreadPlan.cpp:51
lldb::ProcessSP GetProcess() const
Definition: Thread.h:154
lldb::InstructionSP GetInstructionAtIndex(size_t idx) const
uint64_t addr_t
Definition: lldb-types.h:83
Display as the load address (if resolved).
Definition: Address.h:104
bool NextRangeBreakpointExplainsStop(lldb::StopInfoSP stop_info_sp)
LineEntry line_entry
The LineEntry for a given query.
Definition: SBAddress.h:15
#define LLDB_INVALID_BREAK_ID
Definition: lldb-defines.h:49
lldb::StateType GetPlanRunState() override
Vote ShouldReportStop(Event *event_ptr) override
bool IsValid() const
Definition: StackID.h:49
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
const AddressRange & GetAddressRange()
Definition: Function.h:371
#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
bool Dump(Stream *s, Target *target, bool show_file, Address::DumpStyle style, Address::DumpStyle fallback_style, bool show_range) const
Dump a description of this object to a Stream.
Definition: LineEntry.cpp:71
This base class provides an interface to stack frames.
Definition: StackFrame.h:40
lldb::BreakpointSP CreateBreakpoint(const FileSpecList *containingModules, const FileSpec &file, uint32_t line_no, uint32_t column, lldb::addr_t offset, LazyBool check_inlines, LazyBool skip_prologue, bool internal, bool request_hardware, LazyBool move_to_nearest_code)
Definition: Target.cpp:325
AddressRange range
The section offset address range for this line entry.
Definition: LineEntry.h:150
Process or thread is running and can&#39;t be examined.