blob: 8365d709ca8f7735a2e9f993c8e322f18abb2101 [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);
Jason Molendab57e4a12013-11-04 09:33:30 +000047 StackFrameSP m_start_frame_sp(m_thread.GetStackFrameAtIndex(0));
Jim Inghama7d48222013-07-26 00:27:57 +000048 m_stack_id = m_start_frame_sp->GetStackID();
49
50 m_start_has_symbol = m_start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != NULL;
51
Jason Molendab57e4a12013-11-04 09:33:30 +000052 StackFrameSP parent_frame_sp = m_thread.GetStackFrameAtIndex(1);
Jim Ingham886a3e22013-07-25 00:59:01 +000053 if (parent_frame_sp)
54 m_parent_frame_id = parent_frame_sp->GetStackID();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055}
56
57ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
58{
59}
60
61void
62ThreadPlanStepInstruction::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));
Jim Inghama7d48222013-07-26 00:27:57 +000075 if (!m_start_has_symbol)
76 s->Printf(" which has no symbol");
77
Chris Lattner30fdc8d2010-06-08 16:52:24 +000078 if (m_step_over)
79 s->Printf(" stepping over calls");
80 else
81 s->Printf(" stepping into calls");
82 }
83}
84
85bool
86ThreadPlanStepInstruction::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
93bool
Jim Ingham221d51c2013-05-08 00:35:16 +000094ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000095{
Jim Ingham60c41182013-06-04 01:40:51 +000096 StopInfoSP stop_info_sp = GetPrivateStopInfo ();
Jim Inghamb15bfc72010-10-20 00:39:53 +000097 if (stop_info_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000098 {
Jim Inghamb15bfc72010-10-20 00:39:53 +000099 StopReason reason = stop_info_sp->GetStopReason();
Greg Claytonf4b47e12010-08-04 01:40:35 +0000100 if (reason == eStopReasonTrace || reason == eStopReasonNone)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101 return true;
102 else
103 return false;
104 }
105 return false;
106}
107
108bool
109ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
110{
111 if (m_step_over)
112 {
Greg Clayton5160ce52013-03-27 23:08:40 +0000113 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham6b35c862012-03-01 20:01:22 +0000114
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)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000118 {
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:
Jason Molendab57e4a12013-11-04 09:33:30 +0000130 StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000131 if (return_frame)
132 {
Jim Inghama7d48222013-07-26 00:27:57 +0000133 if (return_frame->GetStackID() != m_parent_frame_id || m_start_has_symbol)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000134 {
Jim Ingham886a3e22013-07-25 00:59:01 +0000135 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;
Jim Ingham4b4b2472014-03-13 02:47:14 +0000150 m_thread.QueueThreadPlanForStepOutNoShouldStop(false,
151 NULL,
152 true,
153 stop_others,
154 eVoteNo,
155 eVoteNoOpinion,
156 0);
Jim Ingham886a3e22013-07-25 00:59:01 +0000157 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000158 }
Jim Ingham886a3e22013-07-25 00:59:01 +0000159 else
160 {
161 if (log)
162 {
Jim Inghama7d48222013-07-26 00:27:57 +0000163 log->PutCString("The stack id we are stepping in changed, but our parent frame did not when stepping from code with no symbols. "
Jim Ingham886a3e22013-07-25 00:59:01 +0000164 "We are probably just confused about where we are, stopping.");
165 }
166 SetPlanComplete();
167 return true;
168 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000169 }
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
193bool
194ThreadPlanStepInstruction::StopOthers ()
195{
196 return m_stop_other_threads;
197}
198
199StateType
Jim Ingham06e827c2010-11-11 19:26:09 +0000200ThreadPlanStepInstruction::GetPlanRunState ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000201{
202 return eStateStepping;
203}
204
205bool
206ThreadPlanStepInstruction::WillStop ()
207{
208 return true;
209}
210
211bool
212ThreadPlanStepInstruction::MischiefManaged ()
213{
214 if (IsPlanComplete())
215 {
Greg Clayton5160ce52013-03-27 23:08:40 +0000216 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000217 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