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