blob: b504e1f18db622218ebe452a039ea164da8b0313 [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 }
Greg Clayton0c31d3d2012-03-07 21:03:09 +0000187 else if (m_addr_context.symbol)
Chris Lattner24943d22010-06-08 16:52:24 +0000188 {
Greg Clayton0c31d3d2012-03-07 21:03:09 +0000189 AddressRange range(m_addr_context.symbol->GetAddress(), m_addr_context.symbol->GetByteSize());
190 return range.ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get());
Chris Lattner24943d22010-06-08 16:52:24 +0000191 }
192 return false;
193}
194
195// FIXME: This should also handle inlining if we aren't going to do inlining in the
196// main stack.
197//
198// Ideally we should remember the whole stack frame list, and then compare that
199// to the current list.
200
Jim Ingham441e3b92012-03-01 00:50:50 +0000201lldb::FrameComparison
202ThreadPlanStepRange::CompareCurrentFrameToStartFrame()
Chris Lattner24943d22010-06-08 16:52:24 +0000203{
Jim Ingham441e3b92012-03-01 00:50:50 +0000204 FrameComparison frame_order;
Jim Ingham0e81b642010-09-16 00:58:09 +0000205
Jim Ingham441e3b92012-03-01 00:50:50 +0000206 StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
Jim Ingham0e81b642010-09-16 00:58:09 +0000207
Jim Ingham441e3b92012-03-01 00:50:50 +0000208 if (cur_frame_id == m_stack_id)
Chris Lattner24943d22010-06-08 16:52:24 +0000209 {
Jim Ingham441e3b92012-03-01 00:50:50 +0000210 frame_order = eFrameCompareEqual;
Chris Lattner24943d22010-06-08 16:52:24 +0000211 }
Jim Ingham441e3b92012-03-01 00:50:50 +0000212 else if (cur_frame_id < m_stack_id)
Chris Lattner24943d22010-06-08 16:52:24 +0000213 {
Jim Ingham441e3b92012-03-01 00:50:50 +0000214 frame_order = eFrameCompareYounger;
Chris Lattner24943d22010-06-08 16:52:24 +0000215 }
216 else
217 {
Jim Ingham441e3b92012-03-01 00:50:50 +0000218 frame_order = eFrameCompareOlder;
Chris Lattner24943d22010-06-08 16:52:24 +0000219 }
Jim Ingham441e3b92012-03-01 00:50:50 +0000220 return frame_order;
Chris Lattner24943d22010-06-08 16:52:24 +0000221}
222
223bool
224ThreadPlanStepRange::StopOthers ()
225{
226 if (m_stop_others == lldb::eOnlyThisThread
227 || m_stop_others == lldb::eOnlyDuringStepping)
228 return true;
229 else
230 return false;
231}
232
233bool
234ThreadPlanStepRange::WillStop ()
235{
236 return true;
237}
238
239StateType
Jim Ingham745ac7a2010-11-11 19:26:09 +0000240ThreadPlanStepRange::GetPlanRunState ()
Chris Lattner24943d22010-06-08 16:52:24 +0000241{
242 return eStateStepping;
243}
244
245bool
246ThreadPlanStepRange::MischiefManaged ()
247{
248 bool done = true;
249 if (!IsPlanComplete())
250 {
251 if (InRange())
252 {
253 done = false;
254 }
Jim Ingham441e3b92012-03-01 00:50:50 +0000255 else
Chris Lattner24943d22010-06-08 16:52:24 +0000256 {
Jim Ingham441e3b92012-03-01 00:50:50 +0000257 FrameComparison frame_order = CompareCurrentFrameToStartFrame();
258 if (frame_order != eFrameCompareOlder)
259 {
260 if (m_no_more_plans)
261 done = true;
262 else
263 done = false;
264 }
Chris Lattner24943d22010-06-08 16:52:24 +0000265 else
Jim Ingham441e3b92012-03-01 00:50:50 +0000266 done = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000267 }
Chris Lattner24943d22010-06-08 16:52:24 +0000268 }
269
270 if (done)
271 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000272 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000273 if (log)
274 log->Printf("Completed step through range plan.");
275 ThreadPlan::MischiefManaged ();
276 return true;
277 }
278 else
279 {
280 return false;
281 }
282
283}