LLDB  mainline
ThreadPlanStepThrough.cpp
Go to the documentation of this file.
1 //===-- ThreadPlanStepThrough.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 
13 #include "lldb/Target/Process.h"
15 #include "lldb/Target/Target.h"
16 #include "lldb/Utility/Log.h"
17 #include "lldb/Utility/Stream.h"
18 
19 using namespace lldb;
20 using namespace lldb_private;
21 
22 // ThreadPlanStepThrough: If the current instruction is a trampoline, step
23 // through it If it is the beginning of the prologue of a function, step
24 // through that as well.
25 
26 ThreadPlanStepThrough::ThreadPlanStepThrough(Thread &thread,
27  StackID &m_stack_id,
28  bool stop_others)
29  : ThreadPlan(ThreadPlan::eKindStepThrough,
30  "Step through trampolines and prologues", thread,
32  m_start_address(0), m_backstop_bkpt_id(LLDB_INVALID_BREAK_ID),
33  m_backstop_addr(LLDB_INVALID_ADDRESS), m_return_stack_id(m_stack_id),
34  m_stop_others(stop_others) {
36 
37  // If we don't get a valid step through plan, don't bother to set up a
38  // backstop.
39  if (m_sub_plan_sp) {
41 
42  // We are going to return back to the concrete frame 1, we might pass by
43  // some inlined code that we're in the middle of by doing this, but it's
44  // easier than trying to figure out where the inlined code might return to.
45 
46  StackFrameSP return_frame_sp = thread.GetFrameWithStackID(m_stack_id);
47 
48  if (return_frame_sp) {
49  m_backstop_addr = return_frame_sp->GetFrameCodeAddress().GetLoadAddress(
50  thread.CalculateTarget().get());
51  Breakpoint *return_bp =
53  .CreateBreakpoint(m_backstop_addr, true, false)
54  .get();
55 
56  if (return_bp != nullptr) {
57  if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
59  return_bp->SetThreadID(m_tid);
60  m_backstop_bkpt_id = return_bp->GetID();
61  return_bp->SetBreakpointKind("step-through-backstop");
62  }
64  if (log) {
65  LLDB_LOGF(log, "Setting backstop breakpoint %d at address: 0x%" PRIx64,
67  }
68  }
69  }
70 }
71 
73 
75  if (m_sub_plan_sp)
77 }
78 
80  Thread &thread = GetThread();
81  DynamicLoader *loader = thread.GetProcess()->GetDynamicLoader();
82  if (loader)
84 
85  // If the DynamicLoader was unable to provide us with a ThreadPlan, then we
86  // try the LanguageRuntimes.
87  if (!m_sub_plan_sp) {
88  for (LanguageRuntime *runtime : m_process.GetLanguageRuntimes()) {
90  runtime->GetStepThroughTrampolinePlan(thread, m_stop_others);
91 
92  if (m_sub_plan_sp)
93  break;
94  }
95  }
96 
98  if (log) {
99  lldb::addr_t current_address = GetThread().GetRegisterContext()->GetPC(0);
100  if (m_sub_plan_sp) {
101  StreamString s;
102  m_sub_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull);
103  LLDB_LOGF(log, "Found step through plan from 0x%" PRIx64 ": %s",
104  current_address, s.GetData());
105  } else {
106  LLDB_LOGF(log,
107  "Couldn't find step through plan from address 0x%" PRIx64 ".",
108  current_address);
109  }
110  }
111 }
112 
114  lldb::DescriptionLevel level) {
115  if (level == lldb::eDescriptionLevelBrief)
116  s->Printf("Step through");
117  else {
118  s->PutCString("Stepping through trampoline code from: ");
121  s->Printf(" with backstop breakpoint ID: %d at address: ",
124  } else
125  s->PutCString(" unable to set a backstop breakpoint.");
126  }
127 }
128 
131  if (error)
132  error->PutCString(
133  "Could not create hardware breakpoint for thread plan.");
134  return false;
135  }
136 
138  if (error)
139  error->PutCString("Could not create backstop breakpoint.");
140  return false;
141  }
142 
143  if (!m_sub_plan_sp.get()) {
144  if (error)
145  error->PutCString("Does not have a subplan.");
146  return false;
147  }
148 
149  return true;
150 }
151 
153  // If we have a sub-plan, it will have been asked first if we explain the
154  // stop, and we won't get asked. The only time we would be the one directly
155  // asked this question is if we hit our backstop breakpoint.
156 
157  return HitOurBackstopBreakpoint();
158 }
159 
161  // If we've already marked ourselves done, then we're done...
162  if (IsPlanComplete())
163  return true;
164 
165  // First, did we hit the backstop breakpoint?
166  if (HitOurBackstopBreakpoint()) {
167  SetPlanComplete(true);
168  return true;
169  }
170 
171  // If we don't have a sub-plan, then we're also done (can't see how we would
172  // ever get here without a plan, but just in case.
173 
174  if (!m_sub_plan_sp) {
175  SetPlanComplete();
176  return true;
177  }
178 
179  // If the current sub plan is not done, we don't want to stop. Actually, we
180  // probably won't ever get here in this state, since we generally won't get
181  // asked any questions if out current sub-plan is not done...
182  if (!m_sub_plan_sp->IsPlanComplete())
183  return false;
184 
185  // If our current sub plan failed, then let's just run to our backstop. If
186  // we can't do that then just stop.
187  if (!m_sub_plan_sp->PlanSucceeded()) {
189  m_sub_plan_sp.reset();
190  return false;
191  } else {
192  SetPlanComplete(false);
193  return true;
194  }
195  }
196 
197  // Next see if there is a specific step through plan at our current pc (these
198  // might chain, for instance stepping through a dylib trampoline to the objc
199  // dispatch function...)
201  if (m_sub_plan_sp) {
203  return false;
204  } else {
205  SetPlanComplete();
206  return true;
207  }
208 }
209 
211 
213 
215  bool current_plan) {
216  return true;
217 }
218 
219 bool ThreadPlanStepThrough::WillStop() { return true; }
220 
226  }
227 }
228 
231 
232  if (!IsPlanComplete()) {
233  return false;
234  } else {
235  LLDB_LOGF(log, "Completed step through step plan.");
236 
239  return true;
240  }
241 }
242 
244  Thread &thread = GetThread();
245  StopInfoSP stop_info_sp(thread.GetStopInfo());
246  if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
247  break_id_t stop_value = (break_id_t)stop_info_sp->GetValue();
248  BreakpointSiteSP cur_site_sp =
250  if (cur_site_sp &&
251  cur_site_sp->IsBreakpointAtThisSite(m_backstop_bkpt_id)) {
252  StackID cur_frame_zero_id = thread.GetStackFrameAtIndex(0)->GetStackID();
253 
254  if (cur_frame_zero_id == m_return_stack_id) {
256  if (log)
257  log->PutCString("ThreadPlanStepThrough hit backstop breakpoint.");
258  return true;
259  }
260  }
261  }
262  return false;
263 }
lldb_private::Breakpoint::HasResolvedLocations
bool HasResolvedLocations() const
Return whether this breakpoint has any resolved locations.
Definition: Breakpoint.cpp:835
lldb_private::ThreadPlanStepThrough::DidPush
void DidPush() override
Definition: ThreadPlanStepThrough.cpp:74
lldb_private::ThreadPlan::GetThread
Thread & GetThread()
Returns the Thread that is using this thread plan.
Definition: ThreadPlan.cpp:41
lldb_private::Stoppoint::GetID
lldb::break_id_t GetID() const
Definition: Stoppoint.cpp:22
lldb_private::ThreadPlanStepThrough::m_return_stack_id
StackID m_return_stack_id
Definition: ThreadPlanStepThrough.h:53
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::ThreadPlanStepThrough::LookForPlanToStepThroughFromCurrentPC
void LookForPlanToStepThroughFromCurrentPC()
Definition: ThreadPlanStepThrough.cpp:79
lldb_private::ThreadPlanStepThrough::m_sub_plan_sp
lldb::ThreadPlanSP m_sub_plan_sp
Definition: ThreadPlanStepThrough.h:49
lldb_private::Breakpoint::SetBreakpointKind
void SetBreakpointKind(const char *kind)
Set the "kind" description for a breakpoint.
Definition: Breakpoint.h:442
lldb_private::ThreadPlanStepThrough::ShouldStop
bool ShouldStop(Event *event_ptr) override
Definition: ThreadPlanStepThrough.cpp:160
LLDB_LOGF
#define LLDB_LOGF(log,...)
Definition: Log.h:249
lldb_private::ThreadPlanStepThrough::DoWillResume
bool DoWillResume(lldb::StateType resume_state, bool current_plan) override
Definition: ThreadPlanStepThrough.cpp:214
lldb_private::Thread::CalculateTarget
lldb::TargetSP CalculateTarget() override
Definition: Thread.cpp:1390
lldb_private::Process::GetBreakpointSiteList
BreakpointSiteList & GetBreakpointSiteList()
Definition: Process.cpp:1554
lldb_private::Process::GetTarget
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1214
lldb_private::ThreadPlanStepThrough::m_backstop_bkpt_id
lldb::break_id_t m_backstop_bkpt_id
Definition: ThreadPlanStepThrough.h:51
lldb_private::eVoteNoOpinion
@ eVoteNoOpinion
Definition: lldb-private-enumerations.h:59
lldb_private::ThreadPlanStepThrough::HitOurBackstopBreakpoint
bool HitOurBackstopBreakpoint()
Definition: ThreadPlanStepThrough.cpp:243
lldb_private::Stream
Definition: Stream.h:28
lldb_private::Target::CreateBreakpoint
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:331
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
ThreadPlanStepThrough.h
Process.h
Target.h
lldb_private::Thread::GetProcess
lldb::ProcessSP GetProcess() const
Definition: Thread.h:154
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::ThreadPlan
Definition: ThreadPlan.h:282
Log.h
lldb_private::ThreadPlan::MischiefManaged
virtual bool MischiefManaged()
Definition: ThreadPlan.cpp:71
lldb_private::ThreadPlanStepThrough::ClearBackstopBreakpoint
void ClearBackstopBreakpoint()
Definition: ThreadPlanStepThrough.cpp:221
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::Thread
Definition: Thread.h:62
lldb_private::StreamString::GetData
const char * GetData() const
Definition: StreamString.h:43
lldb_private::ThreadPlanStepThrough::m_start_address
lldb::addr_t m_start_address
Definition: ThreadPlanStepThrough.h:50
lldb_private::ThreadPlanStepThrough::GetDescription
void GetDescription(Stream *s, lldb::DescriptionLevel level) override
Print a description of this thread to the stream s.
Definition: ThreadPlanStepThrough.cpp:113
lldb::break_id_t
int32_t break_id_t
Definition: lldb-types.h:88
lldb_private::StreamString
Definition: StreamString.h:23
lldb::eDescriptionLevelFull
@ eDescriptionLevelFull
Definition: lldb-enumerations.h:209
lldb_private::BreakpointSiteList::FindByID
lldb::BreakpointSiteSP FindByID(lldb::break_id_t breakID)
Returns a shared pointer to the breakpoint site with id breakID.
Definition: BreakpointSiteList.cpp:111
lldb_private::GetLogIfAllCategoriesSet
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:58
lldb_private::DynamicLoader
Definition: DynamicLoader.h:52
lldb_private::LanguageRuntime
Definition: LanguageRuntime.h:60
lldb_private::ThreadPlanStepThrough::m_backstop_addr
lldb::addr_t m_backstop_addr
Definition: ThreadPlanStepThrough.h:52
lldb_private::Breakpoint::SetThreadID
void SetThreadID(lldb::tid_t thread_id)
Set the valid thread to be checked when the breakpoint is hit.
Definition: Breakpoint.cpp:340
lldb_private::ThreadPlanStepThrough::m_stop_others
bool m_stop_others
Definition: ThreadPlanStepThrough.h:54
lldb_private::Process::GetLanguageRuntimes
std::vector< LanguageRuntime * > GetLanguageRuntimes()
Definition: Process.cpp:1481
lldb_private::ThreadPlan::PushPlan
void PushPlan(lldb::ThreadPlanSP &thread_plan_sp)
Definition: ThreadPlan.h:495
lldb_private::DynamicLoader::GetStepThroughTrampolinePlan
virtual lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop_others)=0
Provides a plan to step through the dynamic loader trampoline for the current state of thread.
LLDB_INVALID_BREAK_ID
#define LLDB_INVALID_BREAK_ID
Definition: lldb-defines.h:49
lldb_private::ThreadPlan::SetPlanComplete
void SetPlanComplete(bool success=true)
Definition: ThreadPlan.cpp:65
lldb_private::Thread::GetStopInfo
lldb::StopInfoSP GetStopInfo()
Definition: Thread.cpp:333
lldb_private::ThreadPlan::m_could_not_resolve_hw_bp
bool m_could_not_resolve_hw_bp
Definition: ThreadPlan.h:528
lldb_private::Stream::AsRawOstream
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition: Stream.h:357
lldb::eStopReasonBreakpoint
@ eStopReasonBreakpoint
Definition: lldb-enumerations.h:243
lldb_private::Target::RemoveBreakpointByID
bool RemoveBreakpointByID(lldb::break_id_t break_id)
Definition: Target.cpp:934
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:86
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
LanguageRuntime.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::Breakpoint::IsHardware
bool IsHardware() const
Definition: Breakpoint.h:510
lldb_private::ThreadPlanStepThrough::~ThreadPlanStepThrough
~ThreadPlanStepThrough() override
Definition: ThreadPlanStepThrough.cpp:72
Breakpoint.h
lldb_private::ThreadPlanStepThrough::ValidatePlan
bool ValidatePlan(Stream *error) override
Returns whether this plan could be successfully created.
Definition: ThreadPlanStepThrough.cpp:129
LIBLLDB_LOG_STEP
#define LIBLLDB_LOG_STEP
Definition: Logging.h:21
lldb_private::ThreadPlan::m_tid
lldb::tid_t m_tid
Definition: ThreadPlan.h:524
lldb_private::StackID
Definition: StackID.h:17
lldb_private::ThreadPlanStepThrough::DoPlanExplainsStop
bool DoPlanExplainsStop(Event *event_ptr) override
Definition: ThreadPlanStepThrough.cpp:152
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::ThreadPlanStepThrough::WillStop
bool WillStop() override
Definition: ThreadPlanStepThrough.cpp:219
lldb_private::ThreadPlanStepThrough::GetPlanRunState
lldb::StateType GetPlanRunState() override
Definition: ThreadPlanStepThrough.cpp:212
lldb_private::Thread::GetStackFrameAtIndex
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:399
lldb_private::Thread::GetRegisterContext
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb_private::ThreadPlan::m_process
Process & m_process
Definition: ThreadPlan.h:523
DynamicLoader.h
lldb_private::ThreadPlanStepThrough::MischiefManaged
bool MischiefManaged() override
Definition: ThreadPlanStepThrough.cpp:229
lldb
Definition: SBAddress.h:15
lldb::eStateRunning
@ eStateRunning
Process or thread is running and can't be examined.
Definition: lldb-enumerations.h:85
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::Breakpoint
General Outline: A breakpoint has four main parts, a filter, a resolver, the list of breakpoint locat...
Definition: Breakpoint.h:79
lldb_private::Log::PutCString
void PutCString(const char *cstr)
Definition: Log.cpp:118
lldb_private::ThreadPlanStepThrough::StopOthers
bool StopOthers() override
Definition: ThreadPlanStepThrough.cpp:210