blob: a59d928624c81e253e712749333a438e6ff08a14 [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"
20#include "lldb/Target/RegisterContext.h"
21#include "lldb/Target/Target.h"
22#include "lldb/Target/RegisterContext.h"
23#include "lldb/Target/Process.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28//----------------------------------------------------------------------
29// ThreadPlanStepInstruction: Step over the current instruction
30//----------------------------------------------------------------------
31
32ThreadPlanStepInstruction::ThreadPlanStepInstruction
33(
34 Thread &thread,
35 bool step_over,
36 bool stop_other_threads,
37 Vote stop_vote,
38 Vote run_vote
39) :
Jim Ingham5a47e8b2010-06-19 04:45:32 +000040 ThreadPlan (ThreadPlan::eKindStepInstruction, "Step over single instruction", thread, stop_vote, run_vote),
Chris Lattner24943d22010-06-08 16:52:24 +000041 m_instruction_addr (0),
Benjamin Kramer36a08102010-07-16 12:32:33 +000042 m_stop_other_threads (stop_other_threads),
Chris Lattner24943d22010-06-08 16:52:24 +000043 m_step_over (step_over),
Benjamin Kramer36a08102010-07-16 12:32:33 +000044 m_stack_depth (0)
45{
Chris Lattner24943d22010-06-08 16:52:24 +000046 m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0);
47 m_stack_depth = m_thread.GetStackFrameCount();
48}
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{
86 Thread::StopInfo info;
87 if (m_thread.GetStopInfo (&info))
88 {
89 StopReason reason = info.GetStopReason();
90 if (reason == eStopReasonTrace || reason ==eStopReasonNone)
91 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 {
103 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
104 if (m_thread.GetStackFrameCount() <= m_stack_depth)
105 {
106 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
107 {
108 SetPlanComplete();
109 return true;
110 }
111 else
112 return false;
113 }
114 else
115 {
116 // We've stepped in, step back out again:
117 StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get();
118 if (return_frame)
119 {
120 if (log)
121 {
122 StreamString s;
123 s.PutCString ("Stepped in to: ");
124 addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetPC().GetLoadAddress(&m_thread.GetProcess());
125 s.Address (stop_addr, m_thread.GetProcess().GetAddressByteSize());
126 s.PutCString (" stepping out to: ");
127 addr_t return_addr = return_frame->GetPC().GetLoadAddress(&m_thread.GetProcess());
128 s.Address (return_addr, m_thread.GetProcess().GetAddressByteSize());
129 log->Printf("%s.", s.GetData());
130 }
131 m_thread.QueueThreadPlanForStepOut(false, NULL, true, m_stop_other_threads, eVoteNo, eVoteNoOpinion);
132 return false;
133 }
134 else
135 {
136 if (log)
137 log->Printf("Could not find previous frame, stopping.");
138 SetPlanComplete();
139 return true;
140 }
141
142 }
143
144 }
145 else
146 {
147 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
148 {
149 SetPlanComplete();
150 return true;
151 }
152 else
153 return false;
154 }
155}
156
157bool
158ThreadPlanStepInstruction::StopOthers ()
159{
160 return m_stop_other_threads;
161}
162
163StateType
164ThreadPlanStepInstruction::RunState ()
165{
166 return eStateStepping;
167}
168
169bool
170ThreadPlanStepInstruction::WillStop ()
171{
172 return true;
173}
174
175bool
176ThreadPlanStepInstruction::MischiefManaged ()
177{
178 if (IsPlanComplete())
179 {
180 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
181 if (log)
182 log->Printf("Completed single instruction step plan.");
183 ThreadPlan::MischiefManaged ();
184 return true;
185 }
186 else
187 {
188 return false;
189 }
190}
191