blob: e67cf28d17a0627d5e4c93f07b27ac05bc7c8b7d [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),
Jim Ingham76e55f72011-10-15 00:24:48 +000044 m_address_ranges (),
Chris Lattner24943d22010-06-08 16:52:24 +000045 m_stop_others (stop_others),
Chris Lattner24943d22010-06-08 16:52:24 +000046 m_stack_id (),
Greg Clayton54e7afa2010-07-09 20:39:50 +000047 m_no_more_plans (false),
Chris Lattner24943d22010-06-08 16:52:24 +000048 m_first_run_event (true)
49{
Jim Ingham76e55f72011-10-15 00:24:48 +000050 AddRange(range);
Chris Lattner24943d22010-06-08 16:52:24 +000051 m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
52}
53
54ThreadPlanStepRange::~ThreadPlanStepRange ()
55{
56}
57
58bool
59ThreadPlanStepRange::ValidatePlan (Stream *error)
60{
61 return true;
62}
63
Chris Lattner24943d22010-06-08 16:52:24 +000064Vote
65ThreadPlanStepRange::ShouldReportStop (Event *event_ptr)
66{
Greg Claytone005f2c2010-11-06 01:53:30 +000067 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Greg Clayton5205f0b2010-09-03 17:10:42 +000068
69 const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo;
70 if (log)
Greg Clayton590cce32011-01-18 21:44:45 +000071 log->Printf ("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", vote);
Greg Clayton5205f0b2010-09-03 17:10:42 +000072 return vote;
Chris Lattner24943d22010-06-08 16:52:24 +000073}
74
Jim Ingham76e55f72011-10-15 00:24:48 +000075void
76ThreadPlanStepRange::AddRange(const AddressRange &new_range)
77{
78 // For now I'm just adding the ranges. At some point we may want to
79 // condense the ranges if they overlap, though I don't think it is likely
80 // to be very important.
81 m_address_ranges.push_back (new_range);
82}
83
84void
85ThreadPlanStepRange::DumpRanges(Stream *s)
86{
87 size_t num_ranges = m_address_ranges.size();
88 if (num_ranges == 1)
89 {
Greg Claytonf4124de2012-02-21 00:09:25 +000090 m_address_ranges[0].Dump (s, m_thread.CalculateTarget().get(), Address::DumpStyleLoadAddress);
Jim Ingham76e55f72011-10-15 00:24:48 +000091 }
92 else
93 {
94 for (size_t i = 0; i < num_ranges; i++)
95 {
96 s->PutCString("%d: ");
Greg Claytonf4124de2012-02-21 00:09:25 +000097 m_address_ranges[i].Dump (s, m_thread.CalculateTarget().get(), Address::DumpStyleLoadAddress);
Jim Ingham76e55f72011-10-15 00:24:48 +000098 }
99 }
100}
101
Chris Lattner24943d22010-06-08 16:52:24 +0000102bool
103ThreadPlanStepRange::InRange ()
104{
Greg Claytone005f2c2010-11-06 01:53:30 +0000105 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000106 bool ret_value = false;
107
108 lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC();
109
Jim Ingham76e55f72011-10-15 00:24:48 +0000110 size_t num_ranges = m_address_ranges.size();
111 for (size_t i = 0; i < num_ranges; i++)
112 {
Greg Claytonf4124de2012-02-21 00:09:25 +0000113 ret_value = m_address_ranges[i].ContainsLoadAddress(pc_load_addr, m_thread.CalculateTarget().get());
Jim Ingham76e55f72011-10-15 00:24:48 +0000114 if (ret_value)
115 break;
116 }
Chris Lattner24943d22010-06-08 16:52:24 +0000117
118 if (!ret_value)
119 {
120 // See if we've just stepped to another part of the same line number...
121 StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get();
122
123 SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything));
124 if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid())
125 {
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000126 if (m_addr_context.line_entry.file == new_context.line_entry.file)
Chris Lattner24943d22010-06-08 16:52:24 +0000127 {
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000128 if (m_addr_context.line_entry.line == new_context.line_entry.line)
Chris Lattner24943d22010-06-08 16:52:24 +0000129 {
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000130 m_addr_context = new_context;
Jim Ingham76e55f72011-10-15 00:24:48 +0000131 AddRange(m_addr_context.line_entry.range);
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000132 ret_value = true;
133 if (log)
134 {
135 StreamString s;
Jim Ingham76e55f72011-10-15 00:24:48 +0000136 m_addr_context.line_entry.range.Dump (&s,
Greg Claytonf4124de2012-02-21 00:09:25 +0000137 m_thread.CalculateTarget().get(),
Jim Ingham76e55f72011-10-15 00:24:48 +0000138 Address::DumpStyleLoadAddress);
Chris Lattner24943d22010-06-08 16:52:24 +0000139
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000140 log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData());
141 }
142 }
Greg Claytonf4124de2012-02-21 00:09:25 +0000143 else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(m_thread.CalculateTarget().get())
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000144 != pc_load_addr)
145 {
146 // Another thing that sometimes happens here is that we step out of one line into the MIDDLE of another
147 // line. So far I mostly see this due to bugs in the debug information.
148 // But we probably don't want to be in the middle of a line range, so in that case reset the stepping
149 // range to the line we've stepped into the middle of and continue.
150 m_addr_context = new_context;
Jim Ingham76e55f72011-10-15 00:24:48 +0000151 m_address_ranges.clear();
152 AddRange(m_addr_context.line_entry.range);
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000153 ret_value = true;
154 if (log)
155 {
156 StreamString s;
Jim Ingham76e55f72011-10-15 00:24:48 +0000157 m_addr_context.line_entry.range.Dump (&s,
Greg Claytonf4124de2012-02-21 00:09:25 +0000158 m_thread.CalculateTarget().get(),
Jim Ingham76e55f72011-10-15 00:24:48 +0000159 Address::DumpStyleLoadAddress);
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000160
161 log->Printf ("Step range plan stepped to the middle of new line(%d): %s, continuing to clear this line.",
162 new_context.line_entry.line,
163 s.GetData());
164 }
165
Chris Lattner24943d22010-06-08 16:52:24 +0000166 }
167 }
Jim Ingham0f4d0f32011-09-23 21:08:11 +0000168
Chris Lattner24943d22010-06-08 16:52:24 +0000169 }
170
171 }
172
173 if (!ret_value && log)
174 log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr);
175
176 return ret_value;
177}
178
179bool
180ThreadPlanStepRange::InSymbol()
181{
182 lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
Chris Lattner24943d22010-06-08 16:52:24 +0000183 if (m_addr_context.function != NULL)
184 {
Greg Claytonf4124de2012-02-21 00:09:25 +0000185 return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get());
Chris Lattner24943d22010-06-08 16:52:24 +0000186 }
187 else if (m_addr_context.symbol != NULL)
188 {
Greg Claytonf4124de2012-02-21 00:09:25 +0000189 return m_addr_context.symbol->GetAddressRangeRef().ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get());
Chris Lattner24943d22010-06-08 16:52:24 +0000190 }
191 return false;
192}
193
194// FIXME: This should also handle inlining if we aren't going to do inlining in the
195// main stack.
196//
197// Ideally we should remember the whole stack frame list, and then compare that
198// to the current list.
199
Jim Ingham441e3b92012-03-01 00:50:50 +0000200lldb::FrameComparison
201ThreadPlanStepRange::CompareCurrentFrameToStartFrame()
Chris Lattner24943d22010-06-08 16:52:24 +0000202{
Jim Ingham441e3b92012-03-01 00:50:50 +0000203 FrameComparison frame_order;
Jim Ingham0e81b642010-09-16 00:58:09 +0000204
Jim Ingham441e3b92012-03-01 00:50:50 +0000205 StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
Jim Ingham0e81b642010-09-16 00:58:09 +0000206
Jim Ingham441e3b92012-03-01 00:50:50 +0000207 if (cur_frame_id == m_stack_id)
Chris Lattner24943d22010-06-08 16:52:24 +0000208 {
Jim Ingham441e3b92012-03-01 00:50:50 +0000209 frame_order = eFrameCompareEqual;
Chris Lattner24943d22010-06-08 16:52:24 +0000210 }
Jim Ingham441e3b92012-03-01 00:50:50 +0000211 else if (cur_frame_id < m_stack_id)
Chris Lattner24943d22010-06-08 16:52:24 +0000212 {
Jim Ingham441e3b92012-03-01 00:50:50 +0000213 frame_order = eFrameCompareYounger;
Chris Lattner24943d22010-06-08 16:52:24 +0000214 }
215 else
216 {
Jim Ingham441e3b92012-03-01 00:50:50 +0000217 frame_order = eFrameCompareOlder;
Chris Lattner24943d22010-06-08 16:52:24 +0000218 }
Jim Ingham441e3b92012-03-01 00:50:50 +0000219 return frame_order;
Chris Lattner24943d22010-06-08 16:52:24 +0000220}
221
222bool
223ThreadPlanStepRange::StopOthers ()
224{
225 if (m_stop_others == lldb::eOnlyThisThread
226 || m_stop_others == lldb::eOnlyDuringStepping)
227 return true;
228 else
229 return false;
230}
231
232bool
233ThreadPlanStepRange::WillStop ()
234{
235 return true;
236}
237
238StateType
Jim Ingham745ac7a2010-11-11 19:26:09 +0000239ThreadPlanStepRange::GetPlanRunState ()
Chris Lattner24943d22010-06-08 16:52:24 +0000240{
241 return eStateStepping;
242}
243
244bool
245ThreadPlanStepRange::MischiefManaged ()
246{
247 bool done = true;
248 if (!IsPlanComplete())
249 {
250 if (InRange())
251 {
252 done = false;
253 }
Jim Ingham441e3b92012-03-01 00:50:50 +0000254 else
Chris Lattner24943d22010-06-08 16:52:24 +0000255 {
Jim Ingham441e3b92012-03-01 00:50:50 +0000256 FrameComparison frame_order = CompareCurrentFrameToStartFrame();
257 if (frame_order != eFrameCompareOlder)
258 {
259 if (m_no_more_plans)
260 done = true;
261 else
262 done = false;
263 }
Chris Lattner24943d22010-06-08 16:52:24 +0000264 else
Jim Ingham441e3b92012-03-01 00:50:50 +0000265 done = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000266 }
Chris Lattner24943d22010-06-08 16:52:24 +0000267 }
268
269 if (done)
270 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000271 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000272 if (log)
273 log->Printf("Completed step through range plan.");
274 ThreadPlan::MischiefManaged ();
275 return true;
276 }
277 else
278 {
279 return false;
280 }
281
282}