blob: 7dc1b7dd526e855211a03677db1080efdc20e7ab [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 Ingham8af1bb72011-02-08 04:27:50 +000036ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind,
37 const char *name,
38 Thread &thread,
39 const AddressRange &range,
40 const SymbolContext &addr_context,
41 lldb::RunMode stop_others) :
Jim Ingham5b668b52010-07-10 02:23:31 +000042 ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion),
Chris Lattner24943d22010-06-08 16:52:24 +000043 m_addr_context (addr_context),
Greg Clayton54e7afa2010-07-09 20:39:50 +000044 m_address_range (range),
Chris Lattner24943d22010-06-08 16:52:24 +000045 m_stop_others (stop_others),
46 m_stack_depth (0),
Chris Lattner24943d22010-06-08 16:52:24 +000047 m_stack_id (),
Greg Clayton54e7afa2010-07-09 20:39:50 +000048 m_no_more_plans (false),
Chris Lattner24943d22010-06-08 16:52:24 +000049 m_first_run_event (true)
50{
51 m_stack_depth = m_thread.GetStackFrameCount();
52 m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
53}
54
55ThreadPlanStepRange::~ThreadPlanStepRange ()
56{
57}
58
59bool
60ThreadPlanStepRange::ValidatePlan (Stream *error)
61{
62 return true;
63}
64
65bool
66ThreadPlanStepRange::PlanExplainsStop ()
67{
68 // We don't explain signals or breakpoints (breakpoints that handle stepping in or
69 // out will be handled by a child plan.
Jim Ingham6297a3a2010-10-20 00:39:53 +000070 StopInfoSP stop_info_sp = GetPrivateStopReason();
71 if (stop_info_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000072 {
Jim Ingham6297a3a2010-10-20 00:39:53 +000073 StopReason reason = stop_info_sp->GetStopReason();
Chris Lattner24943d22010-06-08 16:52:24 +000074
75 switch (reason)
76 {
Greg Clayton643ee732010-08-04 01:40:35 +000077 case eStopReasonBreakpoint:
78 case eStopReasonWatchpoint:
79 case eStopReasonSignal:
80 case eStopReasonException:
81 return false;
82 default:
83 return true;
Chris Lattner24943d22010-06-08 16:52:24 +000084 }
85 }
86 return true;
87}
88
89Vote
90ThreadPlanStepRange::ShouldReportStop (Event *event_ptr)
91{
Greg Claytone005f2c2010-11-06 01:53:30 +000092 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Greg Clayton5205f0b2010-09-03 17:10:42 +000093
94 const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo;
95 if (log)
Greg Clayton590cce32011-01-18 21:44:45 +000096 log->Printf ("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", vote);
Greg Clayton5205f0b2010-09-03 17:10:42 +000097 return vote;
Chris Lattner24943d22010-06-08 16:52:24 +000098}
99
100bool
101ThreadPlanStepRange::InRange ()
102{
Greg Claytone005f2c2010-11-06 01:53:30 +0000103 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000104 bool ret_value = false;
105
106 lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC();
107
Greg Claytoneea26402010-09-14 23:36:40 +0000108 ret_value = m_address_range.ContainsLoadAddress(pc_load_addr, &m_thread.GetProcess().GetTarget());
Chris Lattner24943d22010-06-08 16:52:24 +0000109
110 if (!ret_value)
111 {
112 // See if we've just stepped to another part of the same line number...
113 StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get();
114
115 SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything));
116 if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid())
117 {
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000118 if (m_addr_context.line_entry.file == new_context.line_entry.file)
Chris Lattner24943d22010-06-08 16:52:24 +0000119 {
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000120 if (m_addr_context.line_entry.line == new_context.line_entry.line)
Chris Lattner24943d22010-06-08 16:52:24 +0000121 {
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000122 m_addr_context = new_context;
123 m_address_range = m_addr_context.line_entry.range;
124 ret_value = true;
125 if (log)
126 {
127 StreamString s;
128 m_address_range.Dump (&s, &m_thread.GetProcess().GetTarget(), Address::DumpStyleLoadAddress);
Chris Lattner24943d22010-06-08 16:52:24 +0000129
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000130 log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData());
131 }
132 }
133 else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(&m_thread.GetProcess().GetTarget())
134 != pc_load_addr)
135 {
136 // Another thing that sometimes happens here is that we step out of one line into the MIDDLE of another
137 // line. So far I mostly see this due to bugs in the debug information.
138 // But we probably don't want to be in the middle of a line range, so in that case reset the stepping
139 // range to the line we've stepped into the middle of and continue.
140 m_addr_context = new_context;
141 m_address_range = m_addr_context.line_entry.range;
142 ret_value = true;
143 if (log)
144 {
145 StreamString s;
146 m_address_range.Dump (&s, &m_thread.GetProcess().GetTarget(), Address::DumpStyleLoadAddress);
147
148 log->Printf ("Step range plan stepped to the middle of new line(%d): %s, continuing to clear this line.",
149 new_context.line_entry.line,
150 s.GetData());
151 }
152
Chris Lattner24943d22010-06-08 16:52:24 +0000153 }
154 }
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000155
Chris Lattner24943d22010-06-08 16:52:24 +0000156 }
157
158 }
159
160 if (!ret_value && log)
161 log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr);
162
163 return ret_value;
164}
165
166bool
167ThreadPlanStepRange::InSymbol()
168{
169 lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
Chris Lattner24943d22010-06-08 16:52:24 +0000170 if (m_addr_context.function != NULL)
171 {
Greg Claytoneea26402010-09-14 23:36:40 +0000172 return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, &m_thread.GetProcess().GetTarget());
Chris Lattner24943d22010-06-08 16:52:24 +0000173 }
174 else if (m_addr_context.symbol != NULL)
175 {
Greg Claytoneea26402010-09-14 23:36:40 +0000176 return m_addr_context.symbol->GetAddressRangeRef().ContainsLoadAddress (cur_pc, &m_thread.GetProcess().GetTarget());
Chris Lattner24943d22010-06-08 16:52:24 +0000177 }
178 return false;
179}
180
181// FIXME: This should also handle inlining if we aren't going to do inlining in the
182// main stack.
183//
184// Ideally we should remember the whole stack frame list, and then compare that
185// to the current list.
186
187bool
188ThreadPlanStepRange::FrameIsYounger ()
189{
Greg Claytone005f2c2010-11-06 01:53:30 +0000190 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham0e81b642010-09-16 00:58:09 +0000191
192 // FIXME: Might be better to do this by storing the FrameID we started in and seeing if that is still above
193 // us on the stack. Counting the whole stack could be expensive.
194
Chris Lattner24943d22010-06-08 16:52:24 +0000195 uint32_t current_depth = m_thread.GetStackFrameCount();
196 if (current_depth == m_stack_depth)
197 {
198 if (log)
199 log->Printf ("Step range FrameIsYounger still in start function.");
200 return false;
201 }
202 else if (current_depth < m_stack_depth)
203 {
204 if (log)
205 log->Printf ("Step range FrameIsYounger stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth);
206 return false;
207 }
208 else
209 {
210 if (log)
211 log->Printf ("Step range FrameIsYounger stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth);
212 return true;
213 }
214}
215
216bool
217ThreadPlanStepRange::FrameIsOlder ()
218{
Greg Claytone005f2c2010-11-06 01:53:30 +0000219 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000220 uint32_t current_depth = m_thread.GetStackFrameCount();
221 if (current_depth == m_stack_depth)
222 {
223 if (log)
224 log->Printf ("Step range FrameIsOlder still in start function.");
225 return false;
226 }
227 else if (current_depth < m_stack_depth)
228 {
229 if (log)
230 log->Printf ("Step range FrameIsOlder stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth);
231 return true;
232 }
233 else
234 {
235 if (log)
236 log->Printf ("Step range FrameIsOlder stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth);
237 return false;
238 }
239}
240
241bool
242ThreadPlanStepRange::StopOthers ()
243{
244 if (m_stop_others == lldb::eOnlyThisThread
245 || m_stop_others == lldb::eOnlyDuringStepping)
246 return true;
247 else
248 return false;
249}
250
251bool
252ThreadPlanStepRange::WillStop ()
253{
254 return true;
255}
256
257StateType
Jim Ingham745ac7a2010-11-11 19:26:09 +0000258ThreadPlanStepRange::GetPlanRunState ()
Chris Lattner24943d22010-06-08 16:52:24 +0000259{
260 return eStateStepping;
261}
262
263bool
264ThreadPlanStepRange::MischiefManaged ()
265{
266 bool done = true;
267 if (!IsPlanComplete())
268 {
269 if (InRange())
270 {
271 done = false;
272 }
273 else if (!FrameIsOlder())
274 {
275 if (m_no_more_plans)
276 done = true;
277 else
278 done = false;
279 }
280 else
281 done = true;
282 }
283
284 if (done)
285 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000286 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000287 if (log)
288 log->Printf("Completed step through range plan.");
289 ThreadPlan::MischiefManaged ();
290 return true;
291 }
292 else
293 {
294 return false;
295 }
296
297}