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