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 {
46     m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0);
47     m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
48 }
49 
50 ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
51 {
52 }
53 
54 void
55 ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level)
56 {
57     if (level == lldb::eDescriptionLevelBrief)
58     {
59         if (m_step_over)
60             s->Printf ("instruction step over");
61         else
62             s->Printf ("instruction step into");
63     }
64     else
65     {
66         s->Printf ("Stepping one instruction past ");
67         s->Address(m_instruction_addr, sizeof (addr_t));
68         if (m_step_over)
69             s->Printf(" stepping over calls");
70         else
71             s->Printf(" stepping into calls");
72     }
73 }
74 
75 bool
76 ThreadPlanStepInstruction::ValidatePlan (Stream *error)
77 {
78     // Since we read the instruction we're stepping over from the thread,
79     // this plan will always work.
80     return true;
81 }
82 
83 bool
84 ThreadPlanStepInstruction::PlanExplainsStop ()
85 {
86     StopInfoSP stop_info_sp = GetPrivateStopReason();
87     if (stop_info_sp)
88     {
89         StopReason reason = stop_info_sp->GetStopReason();
90         if (reason == eStopReasonTrace || reason == eStopReasonNone)
91             return true;
92         else
93             return false;
94     }
95     return false;
96 }
97 
98 bool
99 ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
100 {
101     if (m_step_over)
102     {
103         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
104 
105         StackID cur_frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
106 
107         if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id)
108         {
109             if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
110             {
111                 SetPlanComplete();
112                 return true;
113             }
114             else
115                 return false;
116         }
117         else
118         {
119             // We've stepped in, step back out again:
120             StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get();
121             if (return_frame)
122             {
123                 if (log)
124                 {
125                     StreamString s;
126                     s.PutCString ("Stepped in to: ");
127                     addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
128                     s.Address (stop_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
129                     s.PutCString (" stepping out to: ");
130                     addr_t return_addr = return_frame->GetRegisterContext()->GetPC();
131                     s.Address (return_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
132                     log->Printf("%s.", s.GetData());
133                 }
134                 m_thread.QueueThreadPlanForStepOut(false, NULL, true, m_stop_other_threads, eVoteNo, eVoteNoOpinion, 0);
135                 return false;
136             }
137             else
138             {
139                 if (log)
140                     log->Printf("Could not find previous frame, stopping.");
141                 SetPlanComplete();
142                 return true;
143             }
144 
145         }
146 
147     }
148     else
149     {
150         if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
151         {
152             SetPlanComplete();
153             return true;
154         }
155         else
156             return false;
157     }
158 }
159 
160 bool
161 ThreadPlanStepInstruction::StopOthers ()
162 {
163     return m_stop_other_threads;
164 }
165 
166 StateType
167 ThreadPlanStepInstruction::GetPlanRunState ()
168 {
169     return eStateStepping;
170 }
171 
172 bool
173 ThreadPlanStepInstruction::WillStop ()
174 {
175     return true;
176 }
177 
178 bool
179 ThreadPlanStepInstruction::MischiefManaged ()
180 {
181     if (IsPlanComplete())
182     {
183         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
184         if (log)
185             log->Printf("Completed single instruction step plan.");
186         ThreadPlan::MischiefManaged ();
187         return true;
188     }
189     else
190     {
191         return false;
192     }
193 }
194 
195