blob: 8ce527ee89c76234be251ee90d2fee8a3dc3766a [file] [log] [blame]
Chris Lattner24943d22010-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 Lattner24943d22010-06-08 16:52:24 +000020#include "lldb/Target/Process.h"
Greg Clayton643ee732010-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 Lattner24943d22010-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 Ingham5a47e8b2010-06-19 04:45:32 +000041 ThreadPlan (ThreadPlan::eKindStepInstruction, "Step over single instruction", thread, stop_vote, run_vote),
Chris Lattner24943d22010-06-08 16:52:24 +000042 m_instruction_addr (0),
Benjamin Kramer36a08102010-07-16 12:32:33 +000043 m_stop_other_threads (stop_other_threads),
Jim Ingham41ce4f12012-03-01 20:01:22 +000044 m_step_over (step_over)
Benjamin Kramer36a08102010-07-16 12:32:33 +000045{
Chris Lattner24943d22010-06-08 16:52:24 +000046 m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0);
Jim Ingham41ce4f12012-03-01 20:01:22 +000047 m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
Chris Lattner24943d22010-06-08 16:52:24 +000048}
49
50ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
51{
52}
53
54void
55ThreadPlanStepInstruction::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
75bool
76ThreadPlanStepInstruction::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
83bool
84ThreadPlanStepInstruction::PlanExplainsStop ()
85{
Jim Ingham6297a3a2010-10-20 00:39:53 +000086 StopInfoSP stop_info_sp = GetPrivateStopReason();
87 if (stop_info_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000088 {
Jim Ingham6297a3a2010-10-20 00:39:53 +000089 StopReason reason = stop_info_sp->GetStopReason();
Greg Clayton643ee732010-08-04 01:40:35 +000090 if (reason == eStopReasonTrace || reason == eStopReasonNone)
Chris Lattner24943d22010-06-08 16:52:24 +000091 return true;
92 else
93 return false;
94 }
95 return false;
96}
97
98bool
99ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
100{
101 if (m_step_over)
102 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000103 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham41ce4f12012-03-01 20:01:22 +0000104
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)
Chris Lattner24943d22010-06-08 16:52:24 +0000108 {
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: ");
Greg Claytonb04e7a82010-08-24 21:05:24 +0000127 addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
Greg Claytonf4124de2012-02-21 00:09:25 +0000128 s.Address (stop_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
Chris Lattner24943d22010-06-08 16:52:24 +0000129 s.PutCString (" stepping out to: ");
Greg Claytonb04e7a82010-08-24 21:05:24 +0000130 addr_t return_addr = return_frame->GetRegisterContext()->GetPC();
Greg Claytonf4124de2012-02-21 00:09:25 +0000131 s.Address (return_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
Chris Lattner24943d22010-06-08 16:52:24 +0000132 log->Printf("%s.", s.GetData());
133 }
Jim Ingham23f21942012-10-25 22:30:09 +0000134
135 // StepInstruction should probably have the tri-state RunMode, but for now it is safer to
136 // run others.
137 const bool stop_others = false;
Jim Ingham88e3de22012-05-03 21:19:36 +0000138 m_thread.QueueThreadPlanForStepOut(false,
139 NULL,
140 true,
Jim Ingham23f21942012-10-25 22:30:09 +0000141 stop_others,
Jim Ingham88e3de22012-05-03 21:19:36 +0000142 eVoteNo,
143 eVoteNoOpinion,
144 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000145 return false;
146 }
147 else
148 {
149 if (log)
150 log->Printf("Could not find previous frame, stopping.");
151 SetPlanComplete();
152 return true;
153 }
154
155 }
156
157 }
158 else
159 {
160 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
161 {
162 SetPlanComplete();
163 return true;
164 }
165 else
166 return false;
167 }
168}
169
170bool
171ThreadPlanStepInstruction::StopOthers ()
172{
173 return m_stop_other_threads;
174}
175
176StateType
Jim Ingham745ac7a2010-11-11 19:26:09 +0000177ThreadPlanStepInstruction::GetPlanRunState ()
Chris Lattner24943d22010-06-08 16:52:24 +0000178{
179 return eStateStepping;
180}
181
182bool
183ThreadPlanStepInstruction::WillStop ()
184{
185 return true;
186}
187
188bool
189ThreadPlanStepInstruction::MischiefManaged ()
190{
191 if (IsPlanComplete())
192 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000193 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000194 if (log)
195 log->Printf("Completed single instruction step plan.");
196 ThreadPlan::MischiefManaged ();
197 return true;
198 }
199 else
200 {
201 return false;
202 }
203}
204