]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInstruction.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / lldb / source / Target / ThreadPlanStepInstruction.cpp
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     StackFrameSP m_start_frame_sp(m_thread.GetStackFrameAtIndex(0));
48     m_stack_id = m_start_frame_sp->GetStackID();
49     
50     m_start_has_symbol = m_start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != NULL;
51     
52     StackFrameSP parent_frame_sp = m_thread.GetStackFrameAtIndex(1);
53     if (parent_frame_sp)
54         m_parent_frame_id = parent_frame_sp->GetStackID();
55 }
56
57 ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
58 {
59 }
60
61 void
62 ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level)
63 {
64     if (level == lldb::eDescriptionLevelBrief)
65     {
66         if (m_step_over)
67             s->Printf ("instruction step over");
68         else
69             s->Printf ("instruction step into");
70     }
71     else
72     {
73         s->Printf ("Stepping one instruction past ");
74         s->Address(m_instruction_addr, sizeof (addr_t));
75         if (!m_start_has_symbol)
76             s->Printf(" which has no symbol");
77         
78         if (m_step_over)
79             s->Printf(" stepping over calls");
80         else
81             s->Printf(" stepping into calls");
82     }
83 }
84
85 bool
86 ThreadPlanStepInstruction::ValidatePlan (Stream *error)
87 {
88     // Since we read the instruction we're stepping over from the thread,
89     // this plan will always work.
90     return true;
91 }
92
93 bool
94 ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr)
95 {
96     StopInfoSP stop_info_sp = GetPrivateStopInfo ();
97     if (stop_info_sp)
98     {
99         StopReason reason = stop_info_sp->GetStopReason();
100         if (reason == eStopReasonTrace || reason == eStopReasonNone)
101             return true;
102         else
103             return false;
104     }
105     return false;
106 }
107
108 bool
109 ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
110 {
111     if (m_step_over)
112     {
113         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
114         
115         StackID cur_frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
116         
117         if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id)
118         {
119             if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
120             {
121                 SetPlanComplete();
122                 return true;
123             }
124             else
125                 return false;
126         }
127         else
128         {
129             // We've stepped in, step back out again:
130             StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get();
131             if (return_frame)
132             {
133                 if (return_frame->GetStackID() != m_parent_frame_id || m_start_has_symbol)
134                 {
135                     if (log)
136                     {
137                         StreamString s;
138                         s.PutCString ("Stepped in to: ");
139                         addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
140                         s.Address (stop_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
141                         s.PutCString (" stepping out to: ");
142                         addr_t return_addr = return_frame->GetRegisterContext()->GetPC();
143                         s.Address (return_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
144                         log->Printf("%s.", s.GetData());
145                     }
146                     
147                     // StepInstruction should probably have the tri-state RunMode, but for now it is safer to
148                     // run others.
149                     const bool stop_others = false;
150                     m_thread.QueueThreadPlanForStepOut(false,
151                                                        NULL,
152                                                        true,
153                                                        stop_others,
154                                                        eVoteNo,
155                                                        eVoteNoOpinion,
156                                                        0);
157                     return false;
158                 }
159                 else
160                 {
161                     if (log)
162                     {
163                         log->PutCString("The stack id we are stepping in changed, but our parent frame did not when stepping from code with no symbols.  "
164                         "We are probably just confused about where we are, stopping.");
165                     }
166                     SetPlanComplete();
167                     return true;
168                 }
169             }
170             else
171             {
172                 if (log)
173                     log->Printf("Could not find previous frame, stopping.");
174                 SetPlanComplete();
175                 return true;
176             }
177
178         }
179
180     }
181     else
182     {
183         if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
184         {
185             SetPlanComplete();
186             return true;
187         }
188         else
189             return false;
190     }
191 }
192
193 bool
194 ThreadPlanStepInstruction::StopOthers ()
195 {
196     return m_stop_other_threads;
197 }
198
199 StateType
200 ThreadPlanStepInstruction::GetPlanRunState ()
201 {
202     return eStateStepping;
203 }
204
205 bool
206 ThreadPlanStepInstruction::WillStop ()
207 {
208     return true;
209 }
210
211 bool
212 ThreadPlanStepInstruction::MischiefManaged ()
213 {
214     if (IsPlanComplete())
215     {
216         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
217         if (log)
218             log->Printf("Completed single instruction step plan.");
219         ThreadPlan::MischiefManaged ();
220         return true;
221     }
222     else
223     {
224         return false;
225     }
226 }
227