blob: 068d8e6584fdeb72b5aa166f475447d209e91ab1 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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#include "lldb/Target/ThreadPlanStepThrough.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016#include "lldb/Core/Log.h"
17#include "lldb/Core/Stream.h"
18#include "lldb/Target/DynamicLoader.h"
Jim Ingham5a369122010-09-28 01:25:32 +000019#include "lldb/Target/ObjCLanguageRuntime.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020#include "lldb/Target/Process.h"
21#include "lldb/Target/RegisterContext.h"
Jim Ingham25f66702011-12-03 01:52:59 +000022#include "lldb/Target/Target.h"
23#include "lldb/Breakpoint/Breakpoint.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000024
25using namespace lldb;
26using namespace lldb_private;
27
28//----------------------------------------------------------------------
29// ThreadPlanStepThrough: If the current instruction is a trampoline, step through it
30// If it is the beginning of the prologue of a function, step through that as well.
31// FIXME: At present only handles DYLD trampolines.
32//----------------------------------------------------------------------
33
Jim Ingham18de2fd2012-05-10 01:35:39 +000034ThreadPlanStepThrough::ThreadPlanStepThrough (Thread &thread, StackID &m_stack_id, bool stop_others) :
Jim Inghamb01e7422010-06-19 04:45:32 +000035 ThreadPlan (ThreadPlan::eKindStepThrough, "Step through trampolines and prologues", thread, eVoteNoOpinion, eVoteNoOpinion),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036 m_start_address (0),
Jim Ingham25f66702011-12-03 01:52:59 +000037 m_backstop_bkpt_id (LLDB_INVALID_BREAK_ID),
38 m_backstop_addr(LLDB_INVALID_ADDRESS),
Jim Ingham18de2fd2012-05-10 01:35:39 +000039 m_return_stack_id (m_stack_id),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040 m_stop_others (stop_others)
41{
Jim Ingham25f66702011-12-03 01:52:59 +000042
43 LookForPlanToStepThroughFromCurrentPC();
44
45 // If we don't get a valid step through plan, don't bother to set up a backstop.
46 if (m_sub_plan_sp)
47 {
48 m_start_address = GetThread().GetRegisterContext()->GetPC(0);
Jim Ingham6b35c862012-03-01 20:01:22 +000049
Jim Ingham25f66702011-12-03 01:52:59 +000050 // We are going to return back to the concrete frame 1, we might pass by some inlined code that we're in
51 // the middle of by doing this, but it's easier than trying to figure out where the inlined code might return to.
52
Jason Molendab57e4a12013-11-04 09:33:30 +000053 StackFrameSP return_frame_sp = m_thread.GetFrameWithStackID (m_stack_id);
Jim Ingham25f66702011-12-03 01:52:59 +000054
55 if (return_frame_sp)
56 {
Greg Clayton1ac04c32012-02-21 00:09:25 +000057 m_backstop_addr = return_frame_sp->GetFrameCodeAddress().GetLoadAddress(m_thread.CalculateTarget().get());
Greg Claytoneb023e72013-10-11 19:48:25 +000058 Breakpoint *return_bp = m_thread.GetProcess()->GetTarget().CreateBreakpoint (m_backstop_addr, true, false).get();
Jim Ingham25f66702011-12-03 01:52:59 +000059 if (return_bp != NULL)
60 {
61 return_bp->SetThreadID(m_thread.GetID());
62 m_backstop_bkpt_id = return_bp->GetID();
Jim Ingham29950772013-01-26 02:19:28 +000063 return_bp->SetBreakpointKind("step-through-backstop");
Jim Ingham25f66702011-12-03 01:52:59 +000064 }
Greg Clayton5160ce52013-03-27 23:08:40 +000065 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham25f66702011-12-03 01:52:59 +000066 if (log)
67 {
Daniel Malead01b2952012-11-29 21:49:15 +000068 log->Printf ("Setting backstop breakpoint %d at address: 0x%" PRIx64, m_backstop_bkpt_id, m_backstop_addr);
Jim Ingham25f66702011-12-03 01:52:59 +000069 }
70 }
71 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000072}
73
74ThreadPlanStepThrough::~ThreadPlanStepThrough ()
75{
Jim Ingham18de2fd2012-05-10 01:35:39 +000076 ClearBackstopBreakpoint ();
Jim Ingham25f66702011-12-03 01:52:59 +000077}
78
79void
80ThreadPlanStepThrough::DidPush ()
81{
82 if (m_sub_plan_sp)
83 PushPlan(m_sub_plan_sp);
84}
85
86void
87ThreadPlanStepThrough::LookForPlanToStepThroughFromCurrentPC()
88{
Jim Ingham89fd6682014-09-30 20:33:25 +000089 DynamicLoader *loader = m_thread.GetProcess()->GetDynamicLoader();
90 if (loader)
91 m_sub_plan_sp = loader->GetStepThroughTrampolinePlan (m_thread, m_stop_others);
92
Jim Ingham25f66702011-12-03 01:52:59 +000093 // If that didn't come up with anything, try the ObjC runtime plugin:
94 if (!m_sub_plan_sp.get())
95 {
Greg Clayton1ac04c32012-02-21 00:09:25 +000096 ObjCLanguageRuntime *objc_runtime = m_thread.GetProcess()->GetObjCLanguageRuntime();
Jim Ingham25f66702011-12-03 01:52:59 +000097 if (objc_runtime)
98 m_sub_plan_sp = objc_runtime->GetStepThroughTrampolinePlan (m_thread, m_stop_others);
99 }
100
Greg Clayton5160ce52013-03-27 23:08:40 +0000101 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham25f66702011-12-03 01:52:59 +0000102 if (log)
103 {
104 lldb::addr_t current_address = GetThread().GetRegisterContext()->GetPC(0);
105 if (m_sub_plan_sp)
106 {
107 StreamString s;
108 m_sub_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull);
Daniel Malead01b2952012-11-29 21:49:15 +0000109 log->Printf ("Found step through plan from 0x%" PRIx64 ": %s", current_address, s.GetData());
Jim Ingham25f66702011-12-03 01:52:59 +0000110 }
111 else
112 {
Daniel Malead01b2952012-11-29 21:49:15 +0000113 log->Printf ("Couldn't find step through plan from address 0x%" PRIx64 ".", current_address);
Jim Ingham25f66702011-12-03 01:52:59 +0000114 }
115 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116}
117
118void
119ThreadPlanStepThrough::GetDescription (Stream *s, lldb::DescriptionLevel level)
120{
121 if (level == lldb::eDescriptionLevelBrief)
122 s->Printf ("Step through");
123 else
124 {
Jim Ingham25f66702011-12-03 01:52:59 +0000125 s->PutCString ("Stepping through trampoline code from: ");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000126 s->Address(m_start_address, sizeof (addr_t));
Jim Ingham25f66702011-12-03 01:52:59 +0000127 if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID)
128 {
129 s->Printf (" with backstop breakpoint id: %d at address: ", m_backstop_bkpt_id);
130 s->Address (m_backstop_addr, sizeof (addr_t));
131 }
132 else
133 s->PutCString (" unable to set a backstop breakpoint.");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000134 }
135}
136
137bool
138ThreadPlanStepThrough::ValidatePlan (Stream *error)
139{
Jim Ingham25f66702011-12-03 01:52:59 +0000140 return m_sub_plan_sp.get() != NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000141}
142
143bool
Jim Ingham221d51c2013-05-08 00:35:16 +0000144ThreadPlanStepThrough::DoPlanExplainsStop (Event *event_ptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000145{
Jim Ingham25f66702011-12-03 01:52:59 +0000146 // If we have a sub-plan, it will have been asked first if we explain the stop, and
147 // we won't get asked. The only time we would be the one directly asked this question
148 // is if we hit our backstop breakpoint.
149
150 if (HitOurBackstopBreakpoint())
151 return true;
152 else
153 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000154}
155
156bool
157ThreadPlanStepThrough::ShouldStop (Event *event_ptr)
158{
Jim Ingham25f66702011-12-03 01:52:59 +0000159 // If we've already marked ourselves done, then we're done...
160 if (IsPlanComplete())
161 return true;
162
Jim Ingham18de2fd2012-05-10 01:35:39 +0000163 // First, did we hit the backstop breakpoint?
164 if (HitOurBackstopBreakpoint())
165 {
Greg Claytond30ed412013-12-10 19:44:41 +0000166 SetPlanComplete(true);
Jim Ingham18de2fd2012-05-10 01:35:39 +0000167 return true;
168 }
169
Jim Ingham25f66702011-12-03 01:52:59 +0000170 // If we don't have a sub-plan, then we're also done (can't see how we would ever get here
171 // without a plan, but just in case.
172
173 if (!m_sub_plan_sp)
174 {
175 SetPlanComplete();
176 return true;
177 }
178
Jim Ingham25f66702011-12-03 01:52:59 +0000179 // If the current sub plan is not done, we don't want to stop. Actually, we probably won't
180 // ever get here in this state, since we generally won't get asked any questions if out
181 // current sub-plan is not done...
182 if (!m_sub_plan_sp->IsPlanComplete())
Jim Ingham18de2fd2012-05-10 01:35:39 +0000183 return false;
184
185 // If our current sub plan failed, then let's just run to our backstop. If we can't do that then just stop.
186 if (!m_sub_plan_sp->PlanSucceeded())
187 {
188 if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID)
189 {
190 m_sub_plan_sp.reset();
Jim Ingham25f66702011-12-03 01:52:59 +0000191 return false;
Jim Ingham18de2fd2012-05-10 01:35:39 +0000192 }
193 else
194 {
195 SetPlanComplete(false);
196 return true;
197 }
198 }
199
Jim Ingham25f66702011-12-03 01:52:59 +0000200 // Next see if there is a specific step through plan at our current pc (these might
201 // chain, for instance stepping through a dylib trampoline to the objc dispatch function...)
202 LookForPlanToStepThroughFromCurrentPC();
203 if (m_sub_plan_sp)
204 {
205 PushPlan (m_sub_plan_sp);
206 return false;
207 }
208 else
209 {
210 SetPlanComplete();
211 return true;
212 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000213}
214
215bool
216ThreadPlanStepThrough::StopOthers ()
217{
218 return m_stop_others;
219}
220
221StateType
Jim Ingham06e827c2010-11-11 19:26:09 +0000222ThreadPlanStepThrough::GetPlanRunState ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000223{
Jim Ingham18de2fd2012-05-10 01:35:39 +0000224 return eStateRunning;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000225}
226
227bool
Jim Ingham221d51c2013-05-08 00:35:16 +0000228ThreadPlanStepThrough::DoWillResume (StateType resume_state, bool current_plan)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000229{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000230 return true;
231}
232
233bool
234ThreadPlanStepThrough::WillStop ()
235{
236 return true;
237}
238
Jim Ingham18de2fd2012-05-10 01:35:39 +0000239void
240ThreadPlanStepThrough::ClearBackstopBreakpoint ()
241{
242 if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID)
243 {
244 m_thread.GetProcess()->GetTarget().RemoveBreakpointByID (m_backstop_bkpt_id);
245 m_backstop_bkpt_id = LLDB_INVALID_BREAK_ID;
246 }
247}
248
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000249bool
250ThreadPlanStepThrough::MischiefManaged ()
251{
Greg Clayton5160ce52013-03-27 23:08:40 +0000252 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000253
Jim Ingham25f66702011-12-03 01:52:59 +0000254 if (!IsPlanComplete())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000255 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000256 return false;
257 }
258 else
259 {
260 if (log)
261 log->Printf("Completed step through step plan.");
Jim Ingham18de2fd2012-05-10 01:35:39 +0000262
263 ClearBackstopBreakpoint ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000264 ThreadPlan::MischiefManaged ();
265 return true;
266 }
267}
268
269bool
Jim Ingham25f66702011-12-03 01:52:59 +0000270ThreadPlanStepThrough::HitOurBackstopBreakpoint()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271{
Jim Ingham25f66702011-12-03 01:52:59 +0000272 StopInfoSP stop_info_sp(m_thread.GetStopInfo());
273 if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
274 {
275 break_id_t stop_value = (break_id_t) stop_info_sp->GetValue();
Greg Clayton1ac04c32012-02-21 00:09:25 +0000276 BreakpointSiteSP cur_site_sp = m_thread.GetProcess()->GetBreakpointSiteList().FindByID(stop_value);
Jim Ingham25f66702011-12-03 01:52:59 +0000277 if (cur_site_sp && cur_site_sp->IsBreakpointAtThisSite(m_backstop_bkpt_id))
278 {
Jim Ingham6b35c862012-03-01 20:01:22 +0000279 StackID cur_frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
280
Jim Ingham18de2fd2012-05-10 01:35:39 +0000281 if (cur_frame_zero_id == m_return_stack_id)
Jim Ingham25f66702011-12-03 01:52:59 +0000282 {
Greg Clayton5160ce52013-03-27 23:08:40 +0000283 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham25f66702011-12-03 01:52:59 +0000284 if (log)
285 log->PutCString ("ThreadPlanStepThrough hit backstop breakpoint.");
286 return true;
287 }
288 }
289 }
290 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000291}
292