1//===-- ThreadPlanStepOverBreakpoint.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#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/lldb-private-log.h"
17#include "lldb/Core/Log.h"
18#include "lldb/Core/Stream.h"
19#include "lldb/Target/Process.h"
20#include "lldb/Target/RegisterContext.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
25//----------------------------------------------------------------------
26// ThreadPlanStepOverBreakpoint: Single steps over a breakpoint bp_site_sp at the pc.
27//----------------------------------------------------------------------
28
29ThreadPlanStepOverBreakpoint::ThreadPlanStepOverBreakpoint (Thread &thread) :
30    ThreadPlan (ThreadPlan::eKindStepOverBreakpoint, "Step over breakpoint trap",
31                thread,
32                eVoteNo,
33                eVoteNoOpinion),  // We need to report the run since this happens
34                            // first in the thread plan stack when stepping
35                            // over a breakpoint
36    m_breakpoint_addr (LLDB_INVALID_ADDRESS),
37    m_auto_continue(false),
38    m_reenabled_breakpoint_site (false)
39
40{
41    m_breakpoint_addr = m_thread.GetRegisterContext()->GetPC();
42    m_breakpoint_site_id =  m_thread.GetProcess()->GetBreakpointSiteList().FindIDByAddress (m_breakpoint_addr);
43}
44
45ThreadPlanStepOverBreakpoint::~ThreadPlanStepOverBreakpoint ()
46{
47}
48
49void
50ThreadPlanStepOverBreakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
51{
52    s->Printf("Single stepping past breakpoint site %" PRIu64 " at 0x%" PRIx64, m_breakpoint_site_id, (uint64_t)m_breakpoint_addr);
53}
54
55bool
56ThreadPlanStepOverBreakpoint::ValidatePlan (Stream *error)
57{
58    return true;
59}
60
61bool
62ThreadPlanStepOverBreakpoint::DoPlanExplainsStop (Event *event_ptr)
63{
64    StopInfoSP stop_info_sp = GetPrivateStopInfo ();
65    if (stop_info_sp)
66    {
67        StopReason reason = stop_info_sp->GetStopReason();
68        if (reason == eStopReasonTrace || reason == eStopReasonNone)
69            return true;
70        else
71            return false;
72    }
73    return false;
74}
75
76bool
77ThreadPlanStepOverBreakpoint::ShouldStop (Event *event_ptr)
78{
79    return false;
80}
81
82bool
83ThreadPlanStepOverBreakpoint::StopOthers ()
84{
85    return true;
86}
87
88StateType
89ThreadPlanStepOverBreakpoint::GetPlanRunState ()
90{
91    return eStateStepping;
92}
93
94bool
95ThreadPlanStepOverBreakpoint::DoWillResume (StateType resume_state, bool current_plan)
96{
97    if (current_plan)
98    {
99        BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
100        if (bp_site_sp  && bp_site_sp->IsEnabled())
101            m_thread.GetProcess()->DisableBreakpointSite (bp_site_sp.get());
102    }
103    return true;
104}
105
106bool
107ThreadPlanStepOverBreakpoint::WillStop ()
108{
109    ReenableBreakpointSite ();
110    return true;
111}
112
113bool
114ThreadPlanStepOverBreakpoint::MischiefManaged ()
115{
116    lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC();
117
118    if (pc_addr == m_breakpoint_addr)
119    {
120        // If we are still at the PC of our breakpoint, then for some reason we didn't
121        // get a chance to run.
122        return false;
123    }
124    else
125    {
126        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
127        if (log)
128            log->Printf("Completed step over breakpoint plan.");
129        // Otherwise, re-enable the breakpoint we were stepping over, and we're done.
130        ReenableBreakpointSite ();
131        ThreadPlan::MischiefManaged ();
132        return true;
133    }
134}
135
136void
137ThreadPlanStepOverBreakpoint::ReenableBreakpointSite ()
138{
139    if (!m_reenabled_breakpoint_site)
140    {
141        m_reenabled_breakpoint_site = true;
142        BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
143        if (bp_site_sp)
144        {
145            m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get());
146        }
147    }
148}
149void
150ThreadPlanStepOverBreakpoint::ThreadDestroyed ()
151{
152    ReenableBreakpointSite ();
153}
154
155void
156ThreadPlanStepOverBreakpoint::SetAutoContinue (bool do_it)
157{
158    m_auto_continue = do_it;
159}
160
161bool
162ThreadPlanStepOverBreakpoint::ShouldAutoContinue (Event *event_ptr)
163{
164    return m_auto_continue;
165}
166