]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp
Upgrade Unbound to 1.7.0. More to follow.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Target / ThreadPlanStepThrough.cpp
1 //===-- ThreadPlanStepThrough.cpp -------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Target/ThreadPlanStepThrough.h"
15 #include "lldb/Breakpoint/Breakpoint.h"
16 #include "lldb/Target/DynamicLoader.h"
17 #include "lldb/Target/ObjCLanguageRuntime.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/RegisterContext.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Utility/Log.h"
22 #include "lldb/Utility/Stream.h"
23
24 using namespace lldb;
25 using namespace lldb_private;
26
27 //----------------------------------------------------------------------
28 // ThreadPlanStepThrough: If the current instruction is a trampoline, step
29 // through it
30 // If it is the beginning of the prologue of a function, step through that as
31 // well.
32 // FIXME: At present only handles DYLD trampolines.
33 //----------------------------------------------------------------------
34
35 ThreadPlanStepThrough::ThreadPlanStepThrough(Thread &thread,
36                                              StackID &m_stack_id,
37                                              bool stop_others)
38     : ThreadPlan(ThreadPlan::eKindStepThrough,
39                  "Step through trampolines and prologues", thread,
40                  eVoteNoOpinion, eVoteNoOpinion),
41       m_start_address(0), m_backstop_bkpt_id(LLDB_INVALID_BREAK_ID),
42       m_backstop_addr(LLDB_INVALID_ADDRESS), m_return_stack_id(m_stack_id),
43       m_stop_others(stop_others) {
44   LookForPlanToStepThroughFromCurrentPC();
45
46   // If we don't get a valid step through plan, don't bother to set up a
47   // backstop.
48   if (m_sub_plan_sp) {
49     m_start_address = GetThread().GetRegisterContext()->GetPC(0);
50
51     // We are going to return back to the concrete frame 1, we might pass by
52     // some inlined code that we're in
53     // the middle of by doing this, but it's easier than trying to figure out
54     // where the inlined code might return to.
55
56     StackFrameSP return_frame_sp = m_thread.GetFrameWithStackID(m_stack_id);
57
58     if (return_frame_sp) {
59       m_backstop_addr = return_frame_sp->GetFrameCodeAddress().GetLoadAddress(
60           m_thread.CalculateTarget().get());
61       Breakpoint *return_bp =
62           m_thread.GetProcess()
63               ->GetTarget()
64               .CreateBreakpoint(m_backstop_addr, true, false)
65               .get();
66       if (return_bp != nullptr) {
67         return_bp->SetThreadID(m_thread.GetID());
68         m_backstop_bkpt_id = return_bp->GetID();
69         return_bp->SetBreakpointKind("step-through-backstop");
70       }
71       Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
72       if (log) {
73         log->Printf("Setting backstop breakpoint %d at address: 0x%" PRIx64,
74                     m_backstop_bkpt_id, m_backstop_addr);
75       }
76     }
77   }
78 }
79
80 ThreadPlanStepThrough::~ThreadPlanStepThrough() { ClearBackstopBreakpoint(); }
81
82 void ThreadPlanStepThrough::DidPush() {
83   if (m_sub_plan_sp)
84     PushPlan(m_sub_plan_sp);
85 }
86
87 void ThreadPlanStepThrough::LookForPlanToStepThroughFromCurrentPC() {
88   DynamicLoader *loader = m_thread.GetProcess()->GetDynamicLoader();
89   if (loader)
90     m_sub_plan_sp =
91         loader->GetStepThroughTrampolinePlan(m_thread, m_stop_others);
92
93   // If that didn't come up with anything, try the ObjC runtime plugin:
94   if (!m_sub_plan_sp.get()) {
95     ObjCLanguageRuntime *objc_runtime =
96         m_thread.GetProcess()->GetObjCLanguageRuntime();
97     if (objc_runtime)
98       m_sub_plan_sp =
99           objc_runtime->GetStepThroughTrampolinePlan(m_thread, m_stop_others);
100   }
101
102   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
103   if (log) {
104     lldb::addr_t current_address = GetThread().GetRegisterContext()->GetPC(0);
105     if (m_sub_plan_sp) {
106       StreamString s;
107       m_sub_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull);
108       log->Printf("Found step through plan from 0x%" PRIx64 ": %s",
109                   current_address, s.GetData());
110     } else {
111       log->Printf("Couldn't find step through plan from address 0x%" PRIx64 ".",
112                   current_address);
113     }
114   }
115 }
116
117 void ThreadPlanStepThrough::GetDescription(Stream *s,
118                                            lldb::DescriptionLevel level) {
119   if (level == lldb::eDescriptionLevelBrief)
120     s->Printf("Step through");
121   else {
122     s->PutCString("Stepping through trampoline code from: ");
123     s->Address(m_start_address, sizeof(addr_t));
124     if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) {
125       s->Printf(" with backstop breakpoint ID: %d at address: ",
126                 m_backstop_bkpt_id);
127       s->Address(m_backstop_addr, sizeof(addr_t));
128     } else
129       s->PutCString(" unable to set a backstop breakpoint.");
130   }
131 }
132
133 bool ThreadPlanStepThrough::ValidatePlan(Stream *error) {
134   return m_sub_plan_sp.get() != nullptr;
135 }
136
137 bool ThreadPlanStepThrough::DoPlanExplainsStop(Event *event_ptr) {
138   // If we have a sub-plan, it will have been asked first if we explain the
139   // stop, and
140   // we won't get asked.  The only time we would be the one directly asked this
141   // question
142   // is if we hit our backstop breakpoint.
143
144   return HitOurBackstopBreakpoint();
145 }
146
147 bool ThreadPlanStepThrough::ShouldStop(Event *event_ptr) {
148   // If we've already marked ourselves done, then we're done...
149   if (IsPlanComplete())
150     return true;
151
152   // First, did we hit the backstop breakpoint?
153   if (HitOurBackstopBreakpoint()) {
154     SetPlanComplete(true);
155     return true;
156   }
157
158   // If we don't have a sub-plan, then we're also done (can't see how we would
159   // ever get here
160   // without a plan, but just in case.
161
162   if (!m_sub_plan_sp) {
163     SetPlanComplete();
164     return true;
165   }
166
167   // If the current sub plan is not done, we don't want to stop.  Actually, we
168   // probably won't
169   // ever get here in this state, since we generally won't get asked any
170   // questions if out
171   // current sub-plan is not done...
172   if (!m_sub_plan_sp->IsPlanComplete())
173     return false;
174
175   // If our current sub plan failed, then let's just run to our backstop.  If we
176   // can't do that then just stop.
177   if (!m_sub_plan_sp->PlanSucceeded()) {
178     if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) {
179       m_sub_plan_sp.reset();
180       return false;
181     } else {
182       SetPlanComplete(false);
183       return true;
184     }
185   }
186
187   // Next see if there is a specific step through plan at our current pc (these
188   // might
189   // chain, for instance stepping through a dylib trampoline to the objc
190   // dispatch function...)
191   LookForPlanToStepThroughFromCurrentPC();
192   if (m_sub_plan_sp) {
193     PushPlan(m_sub_plan_sp);
194     return false;
195   } else {
196     SetPlanComplete();
197     return true;
198   }
199 }
200
201 bool ThreadPlanStepThrough::StopOthers() { return m_stop_others; }
202
203 StateType ThreadPlanStepThrough::GetPlanRunState() { return eStateRunning; }
204
205 bool ThreadPlanStepThrough::DoWillResume(StateType resume_state,
206                                          bool current_plan) {
207   return true;
208 }
209
210 bool ThreadPlanStepThrough::WillStop() { return true; }
211
212 void ThreadPlanStepThrough::ClearBackstopBreakpoint() {
213   if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) {
214     m_thread.GetProcess()->GetTarget().RemoveBreakpointByID(m_backstop_bkpt_id);
215     m_backstop_bkpt_id = LLDB_INVALID_BREAK_ID;
216   }
217 }
218
219 bool ThreadPlanStepThrough::MischiefManaged() {
220   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
221
222   if (!IsPlanComplete()) {
223     return false;
224   } else {
225     if (log)
226       log->Printf("Completed step through step plan.");
227
228     ClearBackstopBreakpoint();
229     ThreadPlan::MischiefManaged();
230     return true;
231   }
232 }
233
234 bool ThreadPlanStepThrough::HitOurBackstopBreakpoint() {
235   StopInfoSP stop_info_sp(m_thread.GetStopInfo());
236   if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
237     break_id_t stop_value = (break_id_t)stop_info_sp->GetValue();
238     BreakpointSiteSP cur_site_sp =
239         m_thread.GetProcess()->GetBreakpointSiteList().FindByID(stop_value);
240     if (cur_site_sp &&
241         cur_site_sp->IsBreakpointAtThisSite(m_backstop_bkpt_id)) {
242       StackID cur_frame_zero_id =
243           m_thread.GetStackFrameAtIndex(0)->GetStackID();
244
245       if (cur_frame_zero_id == m_return_stack_id) {
246         Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
247         if (log)
248           log->PutCString("ThreadPlanStepThrough hit backstop breakpoint.");
249         return true;
250       }
251     }
252   }
253   return false;
254 }