LLDB  mainline
ThreadPlanStepInstruction.cpp
Go to the documentation of this file.
1 //===-- ThreadPlanStepInstruction.cpp -------------------------------------===//
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 #include "lldb/Target/Process.h"
13 #include "lldb/Target/StopInfo.h"
14 #include "lldb/Target/Target.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/Stream.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 // ThreadPlanStepInstruction: Step over the current instruction
22 
23 ThreadPlanStepInstruction::ThreadPlanStepInstruction(Thread &thread,
24  bool step_over,
25  bool stop_other_threads,
26  Vote report_stop_vote,
27  Vote report_run_vote)
28  : ThreadPlan(ThreadPlan::eKindStepInstruction,
29  "Step over single instruction", thread, report_stop_vote,
30  report_run_vote),
31  m_instruction_addr(0), m_stop_other_threads(stop_other_threads),
32  m_step_over(step_over) {
34  SetUpState();
35 }
36 
38 
40  Thread &thread = GetThread();
41  m_instruction_addr = thread.GetRegisterContext()->GetPC(0);
42  StackFrameSP start_frame_sp(thread.GetStackFrameAtIndex(0));
43  m_stack_id = start_frame_sp->GetStackID();
44 
46  start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != nullptr;
47 
48  StackFrameSP parent_frame_sp = thread.GetStackFrameAtIndex(1);
49  if (parent_frame_sp)
50  m_parent_frame_id = parent_frame_sp->GetStackID();
51 }
52 
54  lldb::DescriptionLevel level) {
55  auto PrintFailureIfAny = [&]() {
56  if (m_status.Success())
57  return;
58  s->Printf(" failed (%s)", m_status.AsCString());
59  };
60 
61  if (level == lldb::eDescriptionLevelBrief) {
62  if (m_step_over)
63  s->Printf("instruction step over");
64  else
65  s->Printf("instruction step into");
66 
67  PrintFailureIfAny();
68  } else {
69  s->Printf("Stepping one instruction past ");
71  if (!m_start_has_symbol)
72  s->Printf(" which has no symbol");
73 
74  if (m_step_over)
75  s->Printf(" stepping over calls");
76  else
77  s->Printf(" stepping into calls");
78 
79  PrintFailureIfAny();
80  }
81 }
82 
84  // Since we read the instruction we're stepping over from the thread, this
85  // plan will always work.
86  return true;
87 }
88 
90  StopInfoSP stop_info_sp = GetPrivateStopInfo();
91  if (stop_info_sp) {
92  StopReason reason = stop_info_sp->GetStopReason();
93  return (reason == eStopReasonTrace || reason == eStopReasonNone);
94  }
95  return false;
96 }
97 
100  Thread &thread = GetThread();
101  StackID cur_frame_id = thread.GetStackFrameAtIndex(0)->GetStackID();
102  if (cur_frame_id == m_stack_id) {
103  // Set plan Complete when we reach next instruction
104  uint64_t pc = thread.GetRegisterContext()->GetPC(0);
105  uint32_t max_opcode_size =
107  bool next_instruction_reached = (pc > m_instruction_addr) &&
108  (pc <= m_instruction_addr + max_opcode_size);
109  if (next_instruction_reached) {
110  SetPlanComplete();
111  }
112  return (thread.GetRegisterContext()->GetPC(0) != m_instruction_addr);
113  } else if (cur_frame_id < m_stack_id) {
114  // If the current frame is younger than the start frame and we are stepping
115  // over, then we need to continue, but if we are doing just one step, we're
116  // done.
117  return !m_step_over;
118  } else {
119  if (log) {
120  LLDB_LOGF(log,
121  "ThreadPlanStepInstruction::IsPlanStale - Current frame is "
122  "older than start frame, plan is stale.");
123  }
124  return true;
125  }
126 }
127 
129  Thread &thread = GetThread();
130  if (m_step_over) {
132  StackFrameSP cur_frame_sp = thread.GetStackFrameAtIndex(0);
133  if (!cur_frame_sp) {
134  LLDB_LOGF(
135  log,
136  "ThreadPlanStepInstruction couldn't get the 0th frame, stopping.");
137  SetPlanComplete();
138  return true;
139  }
140 
141  StackID cur_frame_zero_id = cur_frame_sp->GetStackID();
142 
143  if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id) {
144  if (thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) {
145  if (--m_iteration_count <= 0) {
146  SetPlanComplete();
147  return true;
148  } else {
149  // We are still stepping, reset the start pc, and in case we've
150  // stepped out, reset the current stack id.
151  SetUpState();
152  return false;
153  }
154  } else
155  return false;
156  } else {
157  // We've stepped in, step back out again:
158  StackFrame *return_frame = thread.GetStackFrameAtIndex(1).get();
159  if (return_frame) {
160  if (return_frame->GetStackID() != m_parent_frame_id ||
162  // next-instruction shouldn't step out of inlined functions. But we
163  // may have stepped into a real function that starts with an inlined
164  // function, and we do want to step out of that...
165 
166  if (cur_frame_sp->IsInlined()) {
167  StackFrameSP parent_frame_sp =
169 
170  if (parent_frame_sp &&
171  parent_frame_sp->GetConcreteFrameIndex() ==
172  cur_frame_sp->GetConcreteFrameIndex()) {
173  SetPlanComplete();
174  if (log) {
175  LLDB_LOGF(log,
176  "Frame we stepped into is inlined into the frame "
177  "we were stepping from, stopping.");
178  }
179  return true;
180  }
181  }
182 
183  if (log) {
184  StreamString s;
185  s.PutCString("Stepped in to: ");
186  addr_t stop_addr =
187  thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
188  DumpAddress(s.AsRawOstream(), stop_addr,
189  GetTarget().GetArchitecture().GetAddressByteSize());
190  s.PutCString(" stepping out to: ");
191  addr_t return_addr = return_frame->GetRegisterContext()->GetPC();
192  DumpAddress(s.AsRawOstream(), return_addr,
193  GetTarget().GetArchitecture().GetAddressByteSize());
194  LLDB_LOGF(log, "%s.", s.GetData());
195  }
196 
197  // StepInstruction should probably have the tri-state RunMode, but
198  // for now it is safer to run others.
199  const bool stop_others = false;
201  false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
202  m_status);
203  return false;
204  } else {
205  if (log) {
206  log->PutCString(
207  "The stack id we are stepping in changed, but our parent frame "
208  "did not when stepping from code with no symbols. "
209  "We are probably just confused about where we are, stopping.");
210  }
211  SetPlanComplete();
212  return true;
213  }
214  } else {
215  LLDB_LOGF(log, "Could not find previous frame, stopping.");
216  SetPlanComplete();
217  return true;
218  }
219  }
220  } else {
221  lldb::addr_t pc_addr = thread.GetRegisterContext()->GetPC(0);
222  if (pc_addr != m_instruction_addr) {
223  if (--m_iteration_count <= 0) {
224  SetPlanComplete();
225  return true;
226  } else {
227  // We are still stepping, reset the start pc, and in case we've stepped
228  // in or out, reset the current stack id.
229  SetUpState();
230  return false;
231  }
232  } else
233  return false;
234  }
235 }
236 
238 
240  return eStateStepping;
241 }
242 
243 bool ThreadPlanStepInstruction::WillStop() { return true; }
244 
246  if (IsPlanComplete()) {
248  LLDB_LOGF(log, "Completed single instruction step plan.");
250  return true;
251  } else {
252  return false;
253  }
254 }
lldb_private::ThreadPlanStepInstruction::m_parent_frame_id
StackID m_parent_frame_id
Definition: ThreadPlanStepInstruction.h:50
lldb_private::ThreadPlan::GetThread
Thread & GetThread()
Returns the Thread that is using this thread plan.
Definition: ThreadPlan.cpp:41
lldb_private::ArchSpec::GetMaximumOpcodeByteSize
uint32_t GetMaximumOpcodeByteSize() const
Definition: ArchSpec.cpp:923
lldb_private::Event
Definition: Event.h:180
lldb_private::ThreadPlan::IsPlanComplete
bool IsPlanComplete()
Definition: ThreadPlan.cpp:60
lldb_private::Thread::GetFrameWithStackID
virtual lldb::StackFrameSP GetFrameWithStackID(const StackID &stack_id)
Definition: Thread.h:425
lldb_private::Thread::QueueThreadPlanForStepOutNoShouldStop
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOutNoShouldStop(bool abort_other_plans, SymbolContext *addr_context, bool first_insn, bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote, uint32_t frame_idx, Status &status, bool continue_to_next_branch=false)
Queue the plan used to step out of the function at the current PC of a thread.
Definition: Thread.cpp:1317
LLDB_LOGF
#define LLDB_LOGF(log,...)
Definition: Log.h:249
lldb::StopReason
StopReason
Thread stop reasons.
Definition: lldb-enumerations.h:239
lldb_private::ThreadPlanStepInstruction::MischiefManaged
bool MischiefManaged() override
Definition: ThreadPlanStepInstruction.cpp:245
lldb_private::eVoteNoOpinion
@ eVoteNoOpinion
Definition: lldb-private-enumerations.h:59
lldb_private::Stream
Definition: Stream.h:28
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
pc
@ pc
Definition: CompactUnwindInfo.cpp:1250
lldb::eStopReasonTrace
@ eStopReasonTrace
Definition: lldb-enumerations.h:242
lldb_private::ThreadPlanStepInstruction::StopOthers
bool StopOthers() override
Definition: ThreadPlanStepInstruction.cpp:237
Process.h
lldb_private::ThreadPlanStepInstruction::~ThreadPlanStepInstruction
~ThreadPlanStepInstruction() override
lldb_private::ThreadPlanStepInstruction::m_stack_id
StackID m_stack_id
Definition: ThreadPlanStepInstruction.h:49
Target.h
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::Status::Success
bool Success() const
Test for success condition.
Definition: Status.cpp:288
lldb_private::ThreadPlan::GetTarget
Target & GetTarget()
Definition: ThreadPlan.cpp:37
lldb_private::ThreadPlan
Definition: ThreadPlan.h:282
lldb_private::eVoteNo
@ eVoteNo
Definition: lldb-private-enumerations.h:59
Log.h
lldb_private::ThreadPlanStepInstruction::GetPlanRunState
lldb::StateType GetPlanRunState() override
Definition: ThreadPlanStepInstruction.cpp:239
lldb_private::ThreadPlan::MischiefManaged
virtual bool MischiefManaged()
Definition: ThreadPlan.cpp:71
lldb_private::ThreadPlanStepInstruction::ValidatePlan
bool ValidatePlan(Stream *error) override
Returns whether this plan could be successfully created.
Definition: ThreadPlanStepInstruction.cpp:83
lldb_private::DumpAddress
void DumpAddress(llvm::raw_ostream &s, uint64_t addr, uint32_t addr_size, const char *prefix=nullptr, const char *suffix=nullptr)
Output an address value to this stream.
Definition: Stream.cpp:81
lldb_private::ThreadPlanStepInstruction::SetUpState
void SetUpState()
Definition: ThreadPlanStepInstruction.cpp:39
lldb_private::Thread
Definition: Thread.h:62
lldb::eStopReasonNone
@ eStopReasonNone
Definition: lldb-enumerations.h:241
lldb_private::ThreadPlanStepInstruction::m_start_has_symbol
bool m_start_has_symbol
Definition: ThreadPlanStepInstruction.h:48
lldb_private::StreamString::GetData
const char * GetData() const
Definition: StreamString.h:43
lldb_private::StreamString
Definition: StreamString.h:23
lldb_private::ThreadPlanStepInstruction::m_instruction_addr
lldb::addr_t m_instruction_addr
Definition: ThreadPlanStepInstruction.h:44
lldb_private::GetLogIfAllCategoriesSet
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:58
lldb_private::ThreadPlanStepInstruction::IsPlanStale
bool IsPlanStale() override
Definition: ThreadPlanStepInstruction.cpp:98
lldb_private::ThreadPlan::m_status
Status m_status
Definition: ThreadPlan.h:522
lldb_private::ThreadPlanStepInstruction::WillStop
bool WillStop() override
Definition: ThreadPlanStepInstruction.cpp:243
lldb_private::StackFrame::GetStackID
StackID & GetStackID()
Definition: StackFrame.cpp:143
lldb::eStateStepping
@ eStateStepping
Process or thread is in the process of stepping and can not be examined.
Definition: lldb-enumerations.h:86
lldb_private::Target::GetArchitecture
const ArchSpec & GetArchitecture() const
Definition: Target.h:970
lldb_private::ThreadPlan::SetPlanComplete
void SetPlanComplete(bool success=true)
Definition: ThreadPlan.cpp:65
lldb_private::ThreadPlanStepInstruction::ShouldStop
bool ShouldStop(Event *event_ptr) override
Definition: ThreadPlanStepInstruction.cpp:128
uint32_t
ThreadPlanStepInstruction.h
lldb_private::Stream::AsRawOstream
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition: Stream.h:357
StopInfo.h
lldb_private::ThreadPlan::m_iteration_count
int32_t m_iteration_count
Definition: ThreadPlan.h:529
lldb_private::Vote
Vote
Definition: lldb-private-enumerations.h:59
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::StackFrame::GetRegisterContext
lldb::RegisterContextSP GetRegisterContext()
Get the RegisterContext for this frame, if possible.
Definition: StackFrame.cpp:1123
LIBLLDB_LOG_STEP
#define LIBLLDB_LOG_STEP
Definition: Logging.h:21
lldb_private::ThreadPlanStepInstruction::GetDescription
void GetDescription(Stream *s, lldb::DescriptionLevel level) override
Print a description of this thread to the stream s.
Definition: ThreadPlanStepInstruction.cpp:53
lldb_private::StackID
Definition: StackID.h:17
lldb::StateType
StateType
Process and Thread States.
Definition: lldb-enumerations.h:73
Stream.h
lldb_private::Log
Definition: Log.h:49
lldb_private::Stream::PutCString
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:63
lldb_private::ThreadPlan::m_takes_iteration_count
bool m_takes_iteration_count
Definition: ThreadPlan.h:527
lldb_private::Thread::GetStackFrameAtIndex
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:399
lldb_private::ThreadPlanStepInstruction::m_step_over
bool m_step_over
Definition: ThreadPlanStepInstruction.h:46
lldb_private::ThreadPlan::GetPrivateStopInfo
lldb::StopInfoSP GetPrivateStopInfo()
Definition: ThreadPlan.h:510
lldb_private::Thread::GetRegisterContext
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb_private::StackFrame
Definition: StackFrame.h:40
lldb_private::ThreadPlanStepInstruction::m_stop_other_threads
bool m_stop_other_threads
Definition: ThreadPlanStepInstruction.h:45
lldb
Definition: SBAddress.h:15
RegisterContext.h
lldb::eDescriptionLevelBrief
@ eDescriptionLevelBrief
Definition: lldb-enumerations.h:208
lldb::DescriptionLevel
DescriptionLevel
Description levels for "void GetDescription(Stream *, DescriptionLevel)" calls.
Definition: lldb-enumerations.h:207
lldb_private::Status::AsCString
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:131
lldb_private::Log::PutCString
void PutCString(const char *cstr)
Definition: Log.cpp:118
lldb_private::ThreadPlanStepInstruction::DoPlanExplainsStop
bool DoPlanExplainsStop(Event *event_ptr) override
Definition: ThreadPlanStepInstruction.cpp:89