1*30fdc8d8SChris Lattner //===-- ThreadPlanStepRange.cpp ---------------------------------*- C++ -*-===//
2*30fdc8d8SChris Lattner //
3*30fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
4*30fdc8d8SChris Lattner //
5*30fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
6*30fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
7*30fdc8d8SChris Lattner //
8*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
9*30fdc8d8SChris Lattner 
10*30fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepRange.h"
11*30fdc8d8SChris Lattner 
12*30fdc8d8SChris Lattner // C Includes
13*30fdc8d8SChris Lattner // C++ Includes
14*30fdc8d8SChris Lattner // Other libraries and framework includes
15*30fdc8d8SChris Lattner // Project includes
16*30fdc8d8SChris Lattner 
17*30fdc8d8SChris Lattner #include "lldb/lldb-private-log.h"
18*30fdc8d8SChris Lattner #include "lldb/Core/Log.h"
19*30fdc8d8SChris Lattner #include "lldb/Core/Stream.h"
20*30fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
21*30fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
22*30fdc8d8SChris Lattner #include "lldb/Target/Process.h"
23*30fdc8d8SChris Lattner #include "lldb/Symbol/Function.h"
24*30fdc8d8SChris Lattner #include "lldb/Symbol/Symbol.h"
25*30fdc8d8SChris Lattner 
26*30fdc8d8SChris Lattner using namespace lldb;
27*30fdc8d8SChris Lattner using namespace lldb_private;
28*30fdc8d8SChris Lattner 
29*30fdc8d8SChris Lattner 
30*30fdc8d8SChris Lattner //----------------------------------------------------------------------
31*30fdc8d8SChris Lattner // ThreadPlanStepRange: Step through a stack range, either stepping over or into
32*30fdc8d8SChris Lattner // based on the value of \a type.
33*30fdc8d8SChris Lattner //----------------------------------------------------------------------
34*30fdc8d8SChris Lattner 
35*30fdc8d8SChris Lattner ThreadPlanStepRange::ThreadPlanStepRange (const char *name, Thread &thread, const AddressRange &range, const SymbolContext &addr_context, lldb::RunMode stop_others) :
36*30fdc8d8SChris Lattner     ThreadPlan (name, thread, eVoteNoOpinion, eVoteNoOpinion),
37*30fdc8d8SChris Lattner     m_address_range (range),
38*30fdc8d8SChris Lattner     m_addr_context (addr_context),
39*30fdc8d8SChris Lattner     m_stop_others (stop_others),
40*30fdc8d8SChris Lattner     m_stack_depth (0),
41*30fdc8d8SChris Lattner     m_no_more_plans (false),
42*30fdc8d8SChris Lattner     m_stack_id (),
43*30fdc8d8SChris Lattner     m_first_run_event (true)
44*30fdc8d8SChris Lattner {
45*30fdc8d8SChris Lattner     m_stack_depth = m_thread.GetStackFrameCount();
46*30fdc8d8SChris Lattner     m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
47*30fdc8d8SChris Lattner }
48*30fdc8d8SChris Lattner 
49*30fdc8d8SChris Lattner ThreadPlanStepRange::~ThreadPlanStepRange ()
50*30fdc8d8SChris Lattner {
51*30fdc8d8SChris Lattner }
52*30fdc8d8SChris Lattner 
53*30fdc8d8SChris Lattner bool
54*30fdc8d8SChris Lattner ThreadPlanStepRange::ValidatePlan (Stream *error)
55*30fdc8d8SChris Lattner {
56*30fdc8d8SChris Lattner     return true;
57*30fdc8d8SChris Lattner }
58*30fdc8d8SChris Lattner 
59*30fdc8d8SChris Lattner bool
60*30fdc8d8SChris Lattner ThreadPlanStepRange::PlanExplainsStop ()
61*30fdc8d8SChris Lattner {
62*30fdc8d8SChris Lattner     // We don't explain signals or breakpoints (breakpoints that handle stepping in or
63*30fdc8d8SChris Lattner     // out will be handled by a child plan.
64*30fdc8d8SChris Lattner     Thread::StopInfo info;
65*30fdc8d8SChris Lattner     if (m_thread.GetStopInfo (&info))
66*30fdc8d8SChris Lattner     {
67*30fdc8d8SChris Lattner         StopReason reason = info.GetStopReason();
68*30fdc8d8SChris Lattner 
69*30fdc8d8SChris Lattner         switch (reason)
70*30fdc8d8SChris Lattner         {
71*30fdc8d8SChris Lattner             case eStopReasonBreakpoint:
72*30fdc8d8SChris Lattner             case eStopReasonWatchpoint:
73*30fdc8d8SChris Lattner             case eStopReasonSignal:
74*30fdc8d8SChris Lattner             case eStopReasonException:
75*30fdc8d8SChris Lattner                 return false;
76*30fdc8d8SChris Lattner             default:
77*30fdc8d8SChris Lattner                 return true;
78*30fdc8d8SChris Lattner         }
79*30fdc8d8SChris Lattner     }
80*30fdc8d8SChris Lattner     return true;
81*30fdc8d8SChris Lattner }
82*30fdc8d8SChris Lattner 
83*30fdc8d8SChris Lattner Vote
84*30fdc8d8SChris Lattner ThreadPlanStepRange::ShouldReportStop (Event *event_ptr)
85*30fdc8d8SChris Lattner {
86*30fdc8d8SChris Lattner     if (IsPlanComplete())
87*30fdc8d8SChris Lattner         return eVoteYes;
88*30fdc8d8SChris Lattner     else
89*30fdc8d8SChris Lattner         return eVoteNo;
90*30fdc8d8SChris Lattner }
91*30fdc8d8SChris Lattner 
92*30fdc8d8SChris Lattner bool
93*30fdc8d8SChris Lattner ThreadPlanStepRange::InRange ()
94*30fdc8d8SChris Lattner {
95*30fdc8d8SChris Lattner     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
96*30fdc8d8SChris Lattner     bool ret_value = false;
97*30fdc8d8SChris Lattner 
98*30fdc8d8SChris Lattner     lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC();
99*30fdc8d8SChris Lattner 
100*30fdc8d8SChris Lattner     ret_value = m_address_range.ContainsLoadAddress(pc_load_addr, &m_thread.GetProcess());
101*30fdc8d8SChris Lattner 
102*30fdc8d8SChris Lattner     if (!ret_value)
103*30fdc8d8SChris Lattner     {
104*30fdc8d8SChris Lattner         // See if we've just stepped to another part of the same line number...
105*30fdc8d8SChris Lattner         StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get();
106*30fdc8d8SChris Lattner 
107*30fdc8d8SChris Lattner         SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything));
108*30fdc8d8SChris Lattner         if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid())
109*30fdc8d8SChris Lattner         {
110*30fdc8d8SChris Lattner            if ((m_addr_context.line_entry.file == new_context.line_entry.file)
111*30fdc8d8SChris Lattner                && (m_addr_context.line_entry.line == new_context.line_entry.line))
112*30fdc8d8SChris Lattner             {
113*30fdc8d8SChris Lattner                 m_addr_context = new_context;
114*30fdc8d8SChris Lattner                 m_address_range = m_addr_context.line_entry.range;
115*30fdc8d8SChris Lattner                 ret_value = true;
116*30fdc8d8SChris Lattner                 if (log)
117*30fdc8d8SChris Lattner                 {
118*30fdc8d8SChris Lattner                     StreamString s;
119*30fdc8d8SChris Lattner                     m_address_range.Dump (&s, &m_thread.GetProcess(), Address::DumpStyleLoadAddress);
120*30fdc8d8SChris Lattner 
121*30fdc8d8SChris Lattner                     log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData());
122*30fdc8d8SChris Lattner                 }
123*30fdc8d8SChris Lattner             }
124*30fdc8d8SChris Lattner         }
125*30fdc8d8SChris Lattner 
126*30fdc8d8SChris Lattner     }
127*30fdc8d8SChris Lattner 
128*30fdc8d8SChris Lattner     if (!ret_value && log)
129*30fdc8d8SChris Lattner         log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr);
130*30fdc8d8SChris Lattner 
131*30fdc8d8SChris Lattner     return ret_value;
132*30fdc8d8SChris Lattner }
133*30fdc8d8SChris Lattner 
134*30fdc8d8SChris Lattner bool
135*30fdc8d8SChris Lattner ThreadPlanStepRange::InSymbol()
136*30fdc8d8SChris Lattner {
137*30fdc8d8SChris Lattner     lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
138*30fdc8d8SChris Lattner     Process *process = m_thread.CalculateProcess();
139*30fdc8d8SChris Lattner 
140*30fdc8d8SChris Lattner     if (m_addr_context.function != NULL)
141*30fdc8d8SChris Lattner     {
142*30fdc8d8SChris Lattner         return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, process);
143*30fdc8d8SChris Lattner     }
144*30fdc8d8SChris Lattner     else if (m_addr_context.symbol != NULL)
145*30fdc8d8SChris Lattner     {
146*30fdc8d8SChris Lattner         return m_addr_context.symbol->GetAddressRangeRef().ContainsLoadAddress (cur_pc, process);
147*30fdc8d8SChris Lattner     }
148*30fdc8d8SChris Lattner     return false;
149*30fdc8d8SChris Lattner }
150*30fdc8d8SChris Lattner 
151*30fdc8d8SChris Lattner // FIXME: This should also handle inlining if we aren't going to do inlining in the
152*30fdc8d8SChris Lattner // main stack.
153*30fdc8d8SChris Lattner //
154*30fdc8d8SChris Lattner // Ideally we should remember the whole stack frame list, and then compare that
155*30fdc8d8SChris Lattner // to the current list.
156*30fdc8d8SChris Lattner 
157*30fdc8d8SChris Lattner bool
158*30fdc8d8SChris Lattner ThreadPlanStepRange::FrameIsYounger ()
159*30fdc8d8SChris Lattner {
160*30fdc8d8SChris Lattner     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
161*30fdc8d8SChris Lattner     uint32_t current_depth = m_thread.GetStackFrameCount();
162*30fdc8d8SChris Lattner     if (current_depth == m_stack_depth)
163*30fdc8d8SChris Lattner     {
164*30fdc8d8SChris Lattner         if (log)
165*30fdc8d8SChris Lattner             log->Printf ("Step range FrameIsYounger still in start function.");
166*30fdc8d8SChris Lattner         return false;
167*30fdc8d8SChris Lattner     }
168*30fdc8d8SChris Lattner     else if (current_depth < m_stack_depth)
169*30fdc8d8SChris Lattner     {
170*30fdc8d8SChris Lattner         if (log)
171*30fdc8d8SChris Lattner             log->Printf ("Step range FrameIsYounger stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth);
172*30fdc8d8SChris Lattner         return false;
173*30fdc8d8SChris Lattner     }
174*30fdc8d8SChris Lattner     else
175*30fdc8d8SChris Lattner     {
176*30fdc8d8SChris Lattner         if (log)
177*30fdc8d8SChris Lattner             log->Printf ("Step range FrameIsYounger stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth);
178*30fdc8d8SChris Lattner         return true;
179*30fdc8d8SChris Lattner     }
180*30fdc8d8SChris Lattner }
181*30fdc8d8SChris Lattner 
182*30fdc8d8SChris Lattner bool
183*30fdc8d8SChris Lattner ThreadPlanStepRange::FrameIsOlder ()
184*30fdc8d8SChris Lattner {
185*30fdc8d8SChris Lattner     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
186*30fdc8d8SChris Lattner     uint32_t current_depth = m_thread.GetStackFrameCount();
187*30fdc8d8SChris Lattner     if (current_depth == m_stack_depth)
188*30fdc8d8SChris Lattner     {
189*30fdc8d8SChris Lattner         if (log)
190*30fdc8d8SChris Lattner             log->Printf ("Step range FrameIsOlder still in start function.");
191*30fdc8d8SChris Lattner         return false;
192*30fdc8d8SChris Lattner     }
193*30fdc8d8SChris Lattner     else if (current_depth < m_stack_depth)
194*30fdc8d8SChris Lattner     {
195*30fdc8d8SChris Lattner         if (log)
196*30fdc8d8SChris Lattner             log->Printf ("Step range FrameIsOlder stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth);
197*30fdc8d8SChris Lattner         return true;
198*30fdc8d8SChris Lattner     }
199*30fdc8d8SChris Lattner     else
200*30fdc8d8SChris Lattner     {
201*30fdc8d8SChris Lattner         if (log)
202*30fdc8d8SChris Lattner             log->Printf ("Step range FrameIsOlder stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth);
203*30fdc8d8SChris Lattner         return false;
204*30fdc8d8SChris Lattner     }
205*30fdc8d8SChris Lattner }
206*30fdc8d8SChris Lattner 
207*30fdc8d8SChris Lattner bool
208*30fdc8d8SChris Lattner ThreadPlanStepRange::StopOthers ()
209*30fdc8d8SChris Lattner {
210*30fdc8d8SChris Lattner     if (m_stop_others == lldb::eOnlyThisThread
211*30fdc8d8SChris Lattner         || m_stop_others == lldb::eOnlyDuringStepping)
212*30fdc8d8SChris Lattner         return true;
213*30fdc8d8SChris Lattner     else
214*30fdc8d8SChris Lattner         return false;
215*30fdc8d8SChris Lattner }
216*30fdc8d8SChris Lattner 
217*30fdc8d8SChris Lattner bool
218*30fdc8d8SChris Lattner ThreadPlanStepRange::WillStop ()
219*30fdc8d8SChris Lattner {
220*30fdc8d8SChris Lattner     return true;
221*30fdc8d8SChris Lattner }
222*30fdc8d8SChris Lattner 
223*30fdc8d8SChris Lattner StateType
224*30fdc8d8SChris Lattner ThreadPlanStepRange::RunState ()
225*30fdc8d8SChris Lattner {
226*30fdc8d8SChris Lattner     return eStateStepping;
227*30fdc8d8SChris Lattner }
228*30fdc8d8SChris Lattner 
229*30fdc8d8SChris Lattner bool
230*30fdc8d8SChris Lattner ThreadPlanStepRange::MischiefManaged ()
231*30fdc8d8SChris Lattner {
232*30fdc8d8SChris Lattner     bool done = true;
233*30fdc8d8SChris Lattner     if (!IsPlanComplete())
234*30fdc8d8SChris Lattner     {
235*30fdc8d8SChris Lattner         if (InRange())
236*30fdc8d8SChris Lattner         {
237*30fdc8d8SChris Lattner             done = false;
238*30fdc8d8SChris Lattner         }
239*30fdc8d8SChris Lattner         else if (!FrameIsOlder())
240*30fdc8d8SChris Lattner         {
241*30fdc8d8SChris Lattner             if (m_no_more_plans)
242*30fdc8d8SChris Lattner                 done = true;
243*30fdc8d8SChris Lattner             else
244*30fdc8d8SChris Lattner                 done = false;
245*30fdc8d8SChris Lattner         }
246*30fdc8d8SChris Lattner         else
247*30fdc8d8SChris Lattner             done = true;
248*30fdc8d8SChris Lattner     }
249*30fdc8d8SChris Lattner 
250*30fdc8d8SChris Lattner     if (done)
251*30fdc8d8SChris Lattner     {
252*30fdc8d8SChris Lattner         Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
253*30fdc8d8SChris Lattner         if (log)
254*30fdc8d8SChris Lattner             log->Printf("Completed step through range plan.");
255*30fdc8d8SChris Lattner         ThreadPlan::MischiefManaged ();
256*30fdc8d8SChris Lattner         return true;
257*30fdc8d8SChris Lattner     }
258*30fdc8d8SChris Lattner     else
259*30fdc8d8SChris Lattner     {
260*30fdc8d8SChris Lattner         return false;
261*30fdc8d8SChris Lattner     }
262*30fdc8d8SChris Lattner 
263*30fdc8d8SChris Lattner }
264