blob: b07b374e38a2c7ac8bf87064bfa297b33caaa39c [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020#include "lldb/Target/Process.h"
Greg Claytonf4b47e12010-08-04 01:40:35 +000021#include "lldb/Target/RegisterContext.h"
22#include "lldb/Target/RegisterContext.h"
23#include "lldb/Target/StopInfo.h"
24#include "lldb/Target/Target.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000025
26using namespace lldb;
27using namespace lldb_private;
28
29//----------------------------------------------------------------------
30// ThreadPlanStepInstruction: Step over the current instruction
31//----------------------------------------------------------------------
32
33ThreadPlanStepInstruction::ThreadPlanStepInstruction
34(
35 Thread &thread,
36 bool step_over,
37 bool stop_other_threads,
38 Vote stop_vote,
39 Vote run_vote
40) :
Jim Inghamb01e7422010-06-19 04:45:32 +000041 ThreadPlan (ThreadPlan::eKindStepInstruction, "Step over single instruction", thread, stop_vote, run_vote),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000042 m_instruction_addr (0),
Benjamin Kramer1ee0d4f2010-07-16 12:32:33 +000043 m_stop_other_threads (stop_other_threads),
Jim Ingham6b35c862012-03-01 20:01:22 +000044 m_step_over (step_over)
Benjamin Kramer1ee0d4f2010-07-16 12:32:33 +000045{
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046 m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0);
Jim Ingham6b35c862012-03-01 20:01:22 +000047 m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
Jim Ingham886a3e22013-07-25 00:59:01 +000048 StackFrameSP parent_frame_sp = m_thread.GetStackFrameAtIndex(1);
49 if (parent_frame_sp)
50 m_parent_frame_id = parent_frame_sp->GetStackID();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000051}
52
53ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
54{
55}
56
57void
58ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level)
59{
60 if (level == lldb::eDescriptionLevelBrief)
61 {
62 if (m_step_over)
63 s->Printf ("instruction step over");
64 else
65 s->Printf ("instruction step into");
66 }
67 else
68 {
69 s->Printf ("Stepping one instruction past ");
70 s->Address(m_instruction_addr, sizeof (addr_t));
71 if (m_step_over)
72 s->Printf(" stepping over calls");
73 else
74 s->Printf(" stepping into calls");
75 }
76}
77
78bool
79ThreadPlanStepInstruction::ValidatePlan (Stream *error)
80{
81 // Since we read the instruction we're stepping over from the thread,
82 // this plan will always work.
83 return true;
84}
85
86bool
Jim Ingham221d51c2013-05-08 00:35:16 +000087ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000088{
Jim Ingham60c41182013-06-04 01:40:51 +000089 StopInfoSP stop_info_sp = GetPrivateStopInfo ();
Jim Inghamb15bfc72010-10-20 00:39:53 +000090 if (stop_info_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000091 {
Jim Inghamb15bfc72010-10-20 00:39:53 +000092 StopReason reason = stop_info_sp->GetStopReason();
Greg Claytonf4b47e12010-08-04 01:40:35 +000093 if (reason == eStopReasonTrace || reason == eStopReasonNone)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094 return true;
95 else
96 return false;
97 }
98 return false;
99}
100
101bool
102ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
103{
104 if (m_step_over)
105 {
Greg Clayton5160ce52013-03-27 23:08:40 +0000106 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham6b35c862012-03-01 20:01:22 +0000107
108 StackID cur_frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
109
110 if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000111 {
112 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
113 {
114 SetPlanComplete();
115 return true;
116 }
117 else
118 return false;
119 }
120 else
121 {
122 // We've stepped in, step back out again:
123 StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get();
124 if (return_frame)
125 {
Jim Ingham886a3e22013-07-25 00:59:01 +0000126 if (return_frame->GetStackID() != m_parent_frame_id)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000127 {
Jim Ingham886a3e22013-07-25 00:59:01 +0000128 if (log)
129 {
130 StreamString s;
131 s.PutCString ("Stepped in to: ");
132 addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
133 s.Address (stop_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
134 s.PutCString (" stepping out to: ");
135 addr_t return_addr = return_frame->GetRegisterContext()->GetPC();
136 s.Address (return_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
137 log->Printf("%s.", s.GetData());
138 }
139
140 // StepInstruction should probably have the tri-state RunMode, but for now it is safer to
141 // run others.
142 const bool stop_others = false;
143 m_thread.QueueThreadPlanForStepOut(false,
144 NULL,
145 true,
146 stop_others,
147 eVoteNo,
148 eVoteNoOpinion,
149 0);
150 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151 }
Jim Ingham886a3e22013-07-25 00:59:01 +0000152 else
153 {
154 if (log)
155 {
156 log->PutCString("The stack id we are stepping in changed, but our parent frame did not. "
157 "We are probably just confused about where we are, stopping.");
158 }
159 SetPlanComplete();
160 return true;
161 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000162 }
163 else
164 {
165 if (log)
166 log->Printf("Could not find previous frame, stopping.");
167 SetPlanComplete();
168 return true;
169 }
170
171 }
172
173 }
174 else
175 {
176 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
177 {
178 SetPlanComplete();
179 return true;
180 }
181 else
182 return false;
183 }
184}
185
186bool
187ThreadPlanStepInstruction::StopOthers ()
188{
189 return m_stop_other_threads;
190}
191
192StateType
Jim Ingham06e827c2010-11-11 19:26:09 +0000193ThreadPlanStepInstruction::GetPlanRunState ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000194{
195 return eStateStepping;
196}
197
198bool
199ThreadPlanStepInstruction::WillStop ()
200{
201 return true;
202}
203
204bool
205ThreadPlanStepInstruction::MischiefManaged ()
206{
207 if (IsPlanComplete())
208 {
Greg Clayton5160ce52013-03-27 23:08:40 +0000209 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000210 if (log)
211 log->Printf("Completed single instruction step plan.");
212 ThreadPlan::MischiefManaged ();
213 return true;
214 }
215 else
216 {
217 return false;
218 }
219}
220