blob: 7646dc359c278bf058574d78b136216e85ed6914 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- ThreadPlanStepRange.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/ThreadPlanStepRange.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16
17#include "lldb/lldb-private-log.h"
18#include "lldb/Core/Log.h"
19#include "lldb/Core/Stream.h"
Chris Lattner24943d22010-06-08 16:52:24 +000020#include "lldb/Symbol/Function.h"
21#include "lldb/Symbol/Symbol.h"
Greg Clayton643ee732010-08-04 01:40:35 +000022#include "lldb/Target/Process.h"
23#include "lldb/Target/RegisterContext.h"
24#include "lldb/Target/StopInfo.h"
25#include "lldb/Target/Thread.h"
Chris Lattner24943d22010-06-08 16:52:24 +000026
27using namespace lldb;
28using namespace lldb_private;
29
30
31//----------------------------------------------------------------------
32// ThreadPlanStepRange: Step through a stack range, either stepping over or into
33// based on the value of \a type.
34//----------------------------------------------------------------------
35
Jim Ingham5a47e8b2010-06-19 04:45:32 +000036ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind, const char *name, Thread &thread, const AddressRange &range, const SymbolContext &addr_context, lldb::RunMode stop_others) :
Jim Ingham5b668b52010-07-10 02:23:31 +000037 ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion),
Chris Lattner24943d22010-06-08 16:52:24 +000038 m_addr_context (addr_context),
Greg Clayton54e7afa2010-07-09 20:39:50 +000039 m_address_range (range),
Chris Lattner24943d22010-06-08 16:52:24 +000040 m_stop_others (stop_others),
41 m_stack_depth (0),
Chris Lattner24943d22010-06-08 16:52:24 +000042 m_stack_id (),
Greg Clayton54e7afa2010-07-09 20:39:50 +000043 m_no_more_plans (false),
Chris Lattner24943d22010-06-08 16:52:24 +000044 m_first_run_event (true)
45{
46 m_stack_depth = m_thread.GetStackFrameCount();
47 m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
48}
49
50ThreadPlanStepRange::~ThreadPlanStepRange ()
51{
52}
53
54bool
55ThreadPlanStepRange::ValidatePlan (Stream *error)
56{
57 return true;
58}
59
60bool
61ThreadPlanStepRange::PlanExplainsStop ()
62{
63 // We don't explain signals or breakpoints (breakpoints that handle stepping in or
64 // out will be handled by a child plan.
Jim Ingham6297a3a2010-10-20 00:39:53 +000065 StopInfoSP stop_info_sp = GetPrivateStopReason();
66 if (stop_info_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000067 {
Jim Ingham6297a3a2010-10-20 00:39:53 +000068 StopReason reason = stop_info_sp->GetStopReason();
Chris Lattner24943d22010-06-08 16:52:24 +000069
70 switch (reason)
71 {
Greg Clayton643ee732010-08-04 01:40:35 +000072 case eStopReasonBreakpoint:
73 case eStopReasonWatchpoint:
74 case eStopReasonSignal:
75 case eStopReasonException:
76 return false;
77 default:
78 return true;
Chris Lattner24943d22010-06-08 16:52:24 +000079 }
80 }
81 return true;
82}
83
84Vote
85ThreadPlanStepRange::ShouldReportStop (Event *event_ptr)
86{
Greg Claytone005f2c2010-11-06 01:53:30 +000087 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Greg Clayton5205f0b2010-09-03 17:10:42 +000088
89 const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo;
90 if (log)
Greg Clayton590cce32011-01-18 21:44:45 +000091 log->Printf ("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", vote);
Greg Clayton5205f0b2010-09-03 17:10:42 +000092 return vote;
Chris Lattner24943d22010-06-08 16:52:24 +000093}
94
95bool
96ThreadPlanStepRange::InRange ()
97{
Greg Claytone005f2c2010-11-06 01:53:30 +000098 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +000099 bool ret_value = false;
100
101 lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC();
102
Greg Claytoneea26402010-09-14 23:36:40 +0000103 ret_value = m_address_range.ContainsLoadAddress(pc_load_addr, &m_thread.GetProcess().GetTarget());
Chris Lattner24943d22010-06-08 16:52:24 +0000104
105 if (!ret_value)
106 {
107 // See if we've just stepped to another part of the same line number...
108 StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get();
109
110 SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything));
111 if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid())
112 {
113 if ((m_addr_context.line_entry.file == new_context.line_entry.file)
114 && (m_addr_context.line_entry.line == new_context.line_entry.line))
115 {
116 m_addr_context = new_context;
117 m_address_range = m_addr_context.line_entry.range;
118 ret_value = true;
119 if (log)
120 {
121 StreamString s;
Greg Claytoneea26402010-09-14 23:36:40 +0000122 m_address_range.Dump (&s, &m_thread.GetProcess().GetTarget(), Address::DumpStyleLoadAddress);
Chris Lattner24943d22010-06-08 16:52:24 +0000123
124 log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData());
125 }
126 }
127 }
128
129 }
130
131 if (!ret_value && log)
132 log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr);
133
134 return ret_value;
135}
136
137bool
138ThreadPlanStepRange::InSymbol()
139{
140 lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
Chris Lattner24943d22010-06-08 16:52:24 +0000141 if (m_addr_context.function != NULL)
142 {
Greg Claytoneea26402010-09-14 23:36:40 +0000143 return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, &m_thread.GetProcess().GetTarget());
Chris Lattner24943d22010-06-08 16:52:24 +0000144 }
145 else if (m_addr_context.symbol != NULL)
146 {
Greg Claytoneea26402010-09-14 23:36:40 +0000147 return m_addr_context.symbol->GetAddressRangeRef().ContainsLoadAddress (cur_pc, &m_thread.GetProcess().GetTarget());
Chris Lattner24943d22010-06-08 16:52:24 +0000148 }
149 return false;
150}
151
152// FIXME: This should also handle inlining if we aren't going to do inlining in the
153// main stack.
154//
155// Ideally we should remember the whole stack frame list, and then compare that
156// to the current list.
157
158bool
159ThreadPlanStepRange::FrameIsYounger ()
160{
Greg Claytone005f2c2010-11-06 01:53:30 +0000161 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham0e81b642010-09-16 00:58:09 +0000162
163 // FIXME: Might be better to do this by storing the FrameID we started in and seeing if that is still above
164 // us on the stack. Counting the whole stack could be expensive.
165
Chris Lattner24943d22010-06-08 16:52:24 +0000166 uint32_t current_depth = m_thread.GetStackFrameCount();
167 if (current_depth == m_stack_depth)
168 {
169 if (log)
170 log->Printf ("Step range FrameIsYounger still in start function.");
171 return false;
172 }
173 else if (current_depth < m_stack_depth)
174 {
175 if (log)
176 log->Printf ("Step range FrameIsYounger stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth);
177 return false;
178 }
179 else
180 {
181 if (log)
182 log->Printf ("Step range FrameIsYounger stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth);
183 return true;
184 }
185}
186
187bool
188ThreadPlanStepRange::FrameIsOlder ()
189{
Greg Claytone005f2c2010-11-06 01:53:30 +0000190 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000191 uint32_t current_depth = m_thread.GetStackFrameCount();
192 if (current_depth == m_stack_depth)
193 {
194 if (log)
195 log->Printf ("Step range FrameIsOlder still in start function.");
196 return false;
197 }
198 else if (current_depth < m_stack_depth)
199 {
200 if (log)
201 log->Printf ("Step range FrameIsOlder stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth);
202 return true;
203 }
204 else
205 {
206 if (log)
207 log->Printf ("Step range FrameIsOlder stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth);
208 return false;
209 }
210}
211
212bool
213ThreadPlanStepRange::StopOthers ()
214{
215 if (m_stop_others == lldb::eOnlyThisThread
216 || m_stop_others == lldb::eOnlyDuringStepping)
217 return true;
218 else
219 return false;
220}
221
222bool
223ThreadPlanStepRange::WillStop ()
224{
225 return true;
226}
227
228StateType
Jim Ingham745ac7a2010-11-11 19:26:09 +0000229ThreadPlanStepRange::GetPlanRunState ()
Chris Lattner24943d22010-06-08 16:52:24 +0000230{
231 return eStateStepping;
232}
233
234bool
235ThreadPlanStepRange::MischiefManaged ()
236{
237 bool done = true;
238 if (!IsPlanComplete())
239 {
240 if (InRange())
241 {
242 done = false;
243 }
244 else if (!FrameIsOlder())
245 {
246 if (m_no_more_plans)
247 done = true;
248 else
249 done = false;
250 }
251 else
252 done = true;
253 }
254
255 if (done)
256 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000257 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000258 if (log)
259 log->Printf("Completed step through range plan.");
260 ThreadPlan::MischiefManaged ();
261 return true;
262 }
263 else
264 {
265 return false;
266 }
267
268}