1 //===-- ThreadPlanStepInstruction.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 
11 #include "lldb/Target/ThreadPlanStepInstruction.h"
12 
13 // C Includes
14 // C++ Includes
15 // Other libraries and framework includes
16 // Project includes
17 #include "lldb/lldb-private-log.h"
18 #include "lldb/Core/Log.h"
19 #include "lldb/Core/Stream.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/RegisterContext.h"
22 #include "lldb/Target/RegisterContext.h"
23 #include "lldb/Target/StopInfo.h"
24 #include "lldb/Target/Target.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 //----------------------------------------------------------------------
30 // ThreadPlanStepInstruction: Step over the current instruction
31 //----------------------------------------------------------------------
32 
33 ThreadPlanStepInstruction::ThreadPlanStepInstruction
34 (
35     Thread &thread,
36     bool step_over,
37     bool stop_other_threads,
38     Vote stop_vote,
39     Vote run_vote
40 ) :
41     ThreadPlan (ThreadPlan::eKindStepInstruction, "Step over single instruction", thread, stop_vote, run_vote),
42     m_instruction_addr (0),
43     m_stop_other_threads (stop_other_threads),
44     m_step_over (step_over),
45     m_stack_depth (0)
46 {
47     m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0);
48     m_stack_depth = m_thread.GetStackFrameCount();
49 }
50 
51 ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
52 {
53 }
54 
55 void
56 ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level)
57 {
58     if (level == lldb::eDescriptionLevelBrief)
59     {
60         if (m_step_over)
61             s->Printf ("instruction step over");
62         else
63             s->Printf ("instruction step into");
64     }
65     else
66     {
67         s->Printf ("Stepping one instruction past ");
68         s->Address(m_instruction_addr, sizeof (addr_t));
69         if (m_step_over)
70             s->Printf(" stepping over calls");
71         else
72             s->Printf(" stepping into calls");
73     }
74 }
75 
76 bool
77 ThreadPlanStepInstruction::ValidatePlan (Stream *error)
78 {
79     // Since we read the instruction we're stepping over from the thread,
80     // this plan will always work.
81     return true;
82 }
83 
84 bool
85 ThreadPlanStepInstruction::PlanExplainsStop ()
86 {
87     StopInfoSP stop_info_sp = GetPrivateStopReason();
88     if (stop_info_sp)
89     {
90         StopReason reason = stop_info_sp->GetStopReason();
91         if (reason == eStopReasonTrace || reason == eStopReasonNone)
92             return true;
93         else
94             return false;
95     }
96     return false;
97 }
98 
99 bool
100 ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
101 {
102     if (m_step_over)
103     {
104         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
105         if (m_thread.GetStackFrameCount() <= m_stack_depth)
106         {
107             if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
108             {
109                 SetPlanComplete();
110                 return true;
111             }
112             else
113                 return false;
114         }
115         else
116         {
117             // We've stepped in, step back out again:
118             StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get();
119             if (return_frame)
120             {
121                 if (log)
122                 {
123                     StreamString s;
124                     s.PutCString ("Stepped in to: ");
125                     addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
126                     s.Address (stop_addr, m_thread.GetProcess().GetTarget().GetArchitecture().GetAddressByteSize());
127                     s.PutCString (" stepping out to: ");
128                     addr_t return_addr = return_frame->GetRegisterContext()->GetPC();
129                     s.Address (return_addr, m_thread.GetProcess().GetTarget().GetArchitecture().GetAddressByteSize());
130                     log->Printf("%s.", s.GetData());
131                 }
132                 m_thread.QueueThreadPlanForStepOut(false, NULL, true, m_stop_other_threads, eVoteNo, eVoteNoOpinion, 0);
133                 return false;
134             }
135             else
136             {
137                 if (log)
138                     log->Printf("Could not find previous frame, stopping.");
139                 SetPlanComplete();
140                 return true;
141             }
142 
143         }
144 
145     }
146     else
147     {
148         if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
149         {
150             SetPlanComplete();
151             return true;
152         }
153         else
154             return false;
155     }
156 }
157 
158 bool
159 ThreadPlanStepInstruction::StopOthers ()
160 {
161     return m_stop_other_threads;
162 }
163 
164 StateType
165 ThreadPlanStepInstruction::GetPlanRunState ()
166 {
167     return eStateStepping;
168 }
169 
170 bool
171 ThreadPlanStepInstruction::WillStop ()
172 {
173     return true;
174 }
175 
176 bool
177 ThreadPlanStepInstruction::MischiefManaged ()
178 {
179     if (IsPlanComplete())
180     {
181         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
182         if (log)
183             log->Printf("Completed single instruction step plan.");
184         ThreadPlan::MischiefManaged ();
185         return true;
186     }
187     else
188     {
189         return false;
190     }
191 }
192 
193