LLDB  mainline
ThreadPlanStepThrough.cpp
Go to the documentation of this file.
1 //===-- ThreadPlanStepThrough.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 
14 #include "lldb/Target/Process.h"
16 #include "lldb/Target/Target.h"
17 #include "lldb/Utility/Log.h"
18 #include "lldb/Utility/Stream.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 
23 // ThreadPlanStepThrough: If the current instruction is a trampoline, step
24 // through it If it is the beginning of the prologue of a function, step
25 // through that as well.
26 // FIXME: At present only handles DYLD trampolines.
27 
28 ThreadPlanStepThrough::ThreadPlanStepThrough(Thread &thread,
29  StackID &m_stack_id,
30  bool stop_others)
31  : ThreadPlan(ThreadPlan::eKindStepThrough,
32  "Step through trampolines and prologues", thread,
34  m_start_address(0), m_backstop_bkpt_id(LLDB_INVALID_BREAK_ID),
35  m_backstop_addr(LLDB_INVALID_ADDRESS), m_return_stack_id(m_stack_id),
36  m_stop_others(stop_others) {
38 
39  // If we don't get a valid step through plan, don't bother to set up a
40  // backstop.
41  if (m_sub_plan_sp) {
42  m_start_address = GetThread().GetRegisterContext()->GetPC(0);
43 
44  // We are going to return back to the concrete frame 1, we might pass by
45  // some inlined code that we're in the middle of by doing this, but it's
46  // easier than trying to figure out where the inlined code might return to.
47 
48  StackFrameSP return_frame_sp = m_thread.GetFrameWithStackID(m_stack_id);
49 
50  if (return_frame_sp) {
51  m_backstop_addr = return_frame_sp->GetFrameCodeAddress().GetLoadAddress(
52  m_thread.CalculateTarget().get());
53  Breakpoint *return_bp =
55  ->GetTarget()
56  .CreateBreakpoint(m_backstop_addr, true, false)
57  .get();
58 
59  if (return_bp != nullptr) {
60  if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
62  return_bp->SetThreadID(m_thread.GetID());
63  m_backstop_bkpt_id = return_bp->GetID();
64  return_bp->SetBreakpointKind("step-through-backstop");
65  }
67  if (log) {
68  log->Printf("Setting backstop breakpoint %d at address: 0x%" PRIx64,
69  m_backstop_bkpt_id, m_backstop_addr);
70  }
71  }
72  }
73 }
74 
75 ThreadPlanStepThrough::~ThreadPlanStepThrough() { ClearBackstopBreakpoint(); }
76 
78  if (m_sub_plan_sp)
79  PushPlan(m_sub_plan_sp);
80 }
81 
83  DynamicLoader *loader = m_thread.GetProcess()->GetDynamicLoader();
84  if (loader)
85  m_sub_plan_sp =
86  loader->GetStepThroughTrampolinePlan(m_thread, m_stop_others);
87 
88  // If that didn't come up with anything, try the ObjC runtime plugin:
89  if (!m_sub_plan_sp.get()) {
90  ObjCLanguageRuntime *objc_runtime =
91  m_thread.GetProcess()->GetObjCLanguageRuntime();
92  if (objc_runtime)
93  m_sub_plan_sp =
94  objc_runtime->GetStepThroughTrampolinePlan(m_thread, m_stop_others);
95 
96  CPPLanguageRuntime *cpp_runtime =
97  m_thread.GetProcess()->GetCPPLanguageRuntime();
98 
99  // If the ObjC runtime did not provide us with a step though plan then if we
100  // have it check the C++ runtime for a step though plan.
101  if (!m_sub_plan_sp.get() && cpp_runtime)
102  m_sub_plan_sp =
103  cpp_runtime->GetStepThroughTrampolinePlan(m_thread, m_stop_others);
104  }
105 
107  if (log) {
108  lldb::addr_t current_address = GetThread().GetRegisterContext()->GetPC(0);
109  if (m_sub_plan_sp) {
110  StreamString s;
111  m_sub_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull);
112  log->Printf("Found step through plan from 0x%" PRIx64 ": %s",
113  current_address, s.GetData());
114  } else {
115  log->Printf("Couldn't find step through plan from address 0x%" PRIx64 ".",
116  current_address);
117  }
118  }
119 }
120 
122  lldb::DescriptionLevel level) {
123  if (level == lldb::eDescriptionLevelBrief)
124  s->Printf("Step through");
125  else {
126  s->PutCString("Stepping through trampoline code from: ");
127  s->Address(m_start_address, sizeof(addr_t));
128  if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) {
129  s->Printf(" with backstop breakpoint ID: %d at address: ",
130  m_backstop_bkpt_id);
131  s->Address(m_backstop_addr, sizeof(addr_t));
132  } else
133  s->PutCString(" unable to set a backstop breakpoint.");
134  }
135 }
136 
139  if (error)
140  error->PutCString(
141  "Could not create hardware breakpoint for thread plan.");
142  return false;
143  }
144 
145  if (m_backstop_bkpt_id == LLDB_INVALID_BREAK_ID) {
146  if (error)
147  error->PutCString("Could not create backstop breakpoint.");
148  return false;
149  }
150 
151  if (!m_sub_plan_sp.get()) {
152  if (error)
153  error->PutCString("Does not have a subplan.");
154  return false;
155  }
156 
157  return true;
158 }
159 
161  // If we have a sub-plan, it will have been asked first if we explain the
162  // stop, and we won't get asked. The only time we would be the one directly
163  // asked this question is if we hit our backstop breakpoint.
164 
165  return HitOurBackstopBreakpoint();
166 }
167 
169  // If we've already marked ourselves done, then we're done...
170  if (IsPlanComplete())
171  return true;
172 
173  // First, did we hit the backstop breakpoint?
174  if (HitOurBackstopBreakpoint()) {
175  SetPlanComplete(true);
176  return true;
177  }
178 
179  // If we don't have a sub-plan, then we're also done (can't see how we would
180  // ever get here without a plan, but just in case.
181 
182  if (!m_sub_plan_sp) {
183  SetPlanComplete();
184  return true;
185  }
186 
187  // If the current sub plan is not done, we don't want to stop. Actually, we
188  // probably won't ever get here in this state, since we generally won't get
189  // asked any questions if out current sub-plan is not done...
190  if (!m_sub_plan_sp->IsPlanComplete())
191  return false;
192 
193  // If our current sub plan failed, then let's just run to our backstop. If
194  // we can't do that then just stop.
195  if (!m_sub_plan_sp->PlanSucceeded()) {
196  if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) {
197  m_sub_plan_sp.reset();
198  return false;
199  } else {
200  SetPlanComplete(false);
201  return true;
202  }
203  }
204 
205  // Next see if there is a specific step through plan at our current pc (these
206  // might chain, for instance stepping through a dylib trampoline to the objc
207  // dispatch function...)
209  if (m_sub_plan_sp) {
210  PushPlan(m_sub_plan_sp);
211  return false;
212  } else {
213  SetPlanComplete();
214  return true;
215  }
216 }
217 
218 bool ThreadPlanStepThrough::StopOthers() { return m_stop_others; }
219 
221 
223  bool current_plan) {
224  return true;
225 }
226 
227 bool ThreadPlanStepThrough::WillStop() { return true; }
228 
229 void ThreadPlanStepThrough::ClearBackstopBreakpoint() {
230  if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) {
231  m_thread.GetProcess()->GetTarget().RemoveBreakpointByID(m_backstop_bkpt_id);
232  m_backstop_bkpt_id = LLDB_INVALID_BREAK_ID;
234  }
235 }
236 
239 
240  if (!IsPlanComplete()) {
241  return false;
242  } else {
243  if (log)
244  log->Printf("Completed step through step plan.");
245 
246  ClearBackstopBreakpoint();
248  return true;
249  }
250 }
251 
253  StopInfoSP stop_info_sp(m_thread.GetStopInfo());
254  if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
255  break_id_t stop_value = (break_id_t)stop_info_sp->GetValue();
256  BreakpointSiteSP cur_site_sp =
257  m_thread.GetProcess()->GetBreakpointSiteList().FindByID(stop_value);
258  if (cur_site_sp &&
259  cur_site_sp->IsBreakpointAtThisSite(m_backstop_bkpt_id)) {
260  StackID cur_frame_zero_id =
261  m_thread.GetStackFrameAtIndex(0)->GetStackID();
262 
263  if (cur_frame_zero_id == m_return_stack_id) {
265  if (log)
266  log->PutCString("ThreadPlanStepThrough hit backstop breakpoint.");
267  return true;
268  }
269  }
270  }
271  return false;
272 }
void Address(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:79
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
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
virtual lldb::StackFrameSP GetFrameWithStackID(const StackID &stack_id)
Definition: Thread.h:421
virtual lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop_others)=0
General Outline: A breakpoint has four main parts, a filter, a resolver, the list of breakpoint locat...
Definition: Breakpoint.h:78
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop_others)
Obtain a ThreadPlan to get us into C++ constructs such as std::function.
void GetDescription(Stream *s, lldb::DescriptionLevel level) override
Print a description of this thread to the stream s.
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:49
bool ValidatePlan(Stream *error) override
Returns whether this plan could be successfully created.
void SetBreakpointKind(const char *kind)
Set the "kind" description for a breakpoint.
Definition: Breakpoint.h:456
const char * GetData() const
Definition: StreamString.h:43
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...
bool DoWillResume(lldb::StateType resume_state, bool current_plan) override
#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
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
bool ShouldStop(Event *event_ptr) override
void SetPlanComplete(bool success=true)
Definition: ThreadPlan.cpp:51
lldb::ProcessSP GetProcess() const
Definition: Thread.h:154
A plug-in interface definition class for dynamic loaders.
Definition: DynamicLoader.h:64
bool HasResolvedLocations() const
Return whether this breakpoint has any resolved locations.
Definition: Breakpoint.cpp:849
uint64_t addr_t
Definition: lldb-types.h:83
bool DoPlanExplainsStop(Event *event_ptr) override
void PutCString(const char *cstr)
Definition: Log.cpp:109
Definition: SBAddress.h:15
void PushPlan(lldb::ThreadPlanSP &thread_plan_sp)
Definition: ThreadPlan.h:464
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
lldb::StateType GetPlanRunState() override
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
#define LIBLLDB_LOG_STEP
Definition: Logging.h:21
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
lldb::StopInfoSP GetStopInfo()
Definition: Thread.cpp:381
Process or thread is running and can't be examined.