blob: 644c768eaa7697405773a013a631d75d75e43973 [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),
42 m_step_over (step_over),
43 m_stack_depth(0),
Jim Ingham5a47e8b2010-06-19 04:45:32 +000044 m_stop_other_threads (stop_other_threads){
Chris Lattner24943d22010-06-08 16:52:24 +000045 m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0);
46 m_stack_depth = m_thread.GetStackFrameCount();
47}
48
49ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
50{
51}
52
53void
54ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level)
55{
56 if (level == lldb::eDescriptionLevelBrief)
57 {
58 if (m_step_over)
59 s->Printf ("instruction step over");
60 else
61 s->Printf ("instruction step into");
62 }
63 else
64 {
65 s->Printf ("Stepping one instruction past ");
66 s->Address(m_instruction_addr, sizeof (addr_t));
67 if (m_step_over)
68 s->Printf(" stepping over calls");
69 else
70 s->Printf(" stepping into calls");
71 }
72}
73
74bool
75ThreadPlanStepInstruction::ValidatePlan (Stream *error)
76{
77 // Since we read the instruction we're stepping over from the thread,
78 // this plan will always work.
79 return true;
80}
81
82bool
83ThreadPlanStepInstruction::PlanExplainsStop ()
84{
85 Thread::StopInfo info;
86 if (m_thread.GetStopInfo (&info))
87 {
88 StopReason reason = info.GetStopReason();
89 if (reason == eStopReasonTrace || reason ==eStopReasonNone)
90 return true;
91 else
92 return false;
93 }
94 return false;
95}
96
97bool
98ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
99{
100 if (m_step_over)
101 {
102 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
103 if (m_thread.GetStackFrameCount() <= m_stack_depth)
104 {
105 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
106 {
107 SetPlanComplete();
108 return true;
109 }
110 else
111 return false;
112 }
113 else
114 {
115 // We've stepped in, step back out again:
116 StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get();
117 if (return_frame)
118 {
119 if (log)
120 {
121 StreamString s;
122 s.PutCString ("Stepped in to: ");
123 addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetPC().GetLoadAddress(&m_thread.GetProcess());
124 s.Address (stop_addr, m_thread.GetProcess().GetAddressByteSize());
125 s.PutCString (" stepping out to: ");
126 addr_t return_addr = return_frame->GetPC().GetLoadAddress(&m_thread.GetProcess());
127 s.Address (return_addr, m_thread.GetProcess().GetAddressByteSize());
128 log->Printf("%s.", s.GetData());
129 }
130 m_thread.QueueThreadPlanForStepOut(false, NULL, true, m_stop_other_threads, eVoteNo, eVoteNoOpinion);
131 return false;
132 }
133 else
134 {
135 if (log)
136 log->Printf("Could not find previous frame, stopping.");
137 SetPlanComplete();
138 return true;
139 }
140
141 }
142
143 }
144 else
145 {
146 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
147 {
148 SetPlanComplete();
149 return true;
150 }
151 else
152 return false;
153 }
154}
155
156bool
157ThreadPlanStepInstruction::StopOthers ()
158{
159 return m_stop_other_threads;
160}
161
162StateType
163ThreadPlanStepInstruction::RunState ()
164{
165 return eStateStepping;
166}
167
168bool
169ThreadPlanStepInstruction::WillStop ()
170{
171 return true;
172}
173
174bool
175ThreadPlanStepInstruction::MischiefManaged ()
176{
177 if (IsPlanComplete())
178 {
179 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
180 if (log)
181 log->Printf("Completed single instruction step plan.");
182 ThreadPlan::MischiefManaged ();
183 return true;
184 }
185 else
186 {
187 return false;
188 }
189}
190