//===-- ThreadPlanStepOverBreakpoint.cpp ------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------
// ThreadPlanStepOverBreakpoint: Single steps over a breakpoint bp_site_sp at the pc.
//----------------------------------------------------------------------

ThreadPlanStepOverBreakpoint::ThreadPlanStepOverBreakpoint (Thread &thread) :
    ThreadPlan (ThreadPlan::eKindStepOverBreakpoint, "Step over breakpoint trap",
                thread,
                eVoteNo,
                eVoteNoOpinion),  // We need to report the run since this happens
                            // first in the thread plan stack when stepping
                            // over a breakpoint
    m_breakpoint_addr (LLDB_INVALID_ADDRESS),
    m_auto_continue(false),
    m_reenabled_breakpoint_site (false)

{
    m_breakpoint_addr = m_thread.GetRegisterContext()->GetPC();
    m_breakpoint_site_id =  m_thread.GetProcess()->GetBreakpointSiteList().FindIDByAddress (m_breakpoint_addr);
}

ThreadPlanStepOverBreakpoint::~ThreadPlanStepOverBreakpoint ()
{
}

void
ThreadPlanStepOverBreakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
    s->Printf("Single stepping past breakpoint site %" PRIu64 " at 0x%" PRIx64, m_breakpoint_site_id, (uint64_t)m_breakpoint_addr);
}

bool
ThreadPlanStepOverBreakpoint::ValidatePlan (Stream *error)
{
    return true;
}

bool
ThreadPlanStepOverBreakpoint::DoPlanExplainsStop (Event *event_ptr)
{
    StopInfoSP stop_info_sp = GetPrivateStopInfo ();
    if (stop_info_sp)
    {
        // It's a little surprising that we stop here for a breakpoint hit.  However, when you single step ONTO a breakpoint
        // we still want to call that a breakpoint hit, and trigger the actions, etc.  Otherwise you would see the
        // PC at the breakpoint without having triggered the actions, then you'd continue, the PC wouldn't change,
        // and you'd see the breakpoint hit, which would be odd.
        // So the lower levels fake "step onto breakpoint address" and return that as a breakpoint.  So our trace
        // step COULD appear as a breakpoint hit if the next instruction also contained a breakpoint.
        StopReason reason = stop_info_sp->GetStopReason();

        switch (reason)
        {
        case eStopReasonTrace:
        case eStopReasonNone:
            return true;
        case eStopReasonBreakpoint:
            // It's a little surprising that we stop here for a breakpoint hit.  However, when you single step ONTO a
            // breakpoint we still want to call that a breakpoint hit, and trigger the actions, etc.  Otherwise you
            // would see the PC at the breakpoint without having triggered the actions, then you'd continue, the PC
            // wouldn't change, and you'd see the breakpoint hit, which would be odd.
            // So the lower levels fake "step onto breakpoint address" and return that as a breakpoint hit.  So our trace
            // step COULD appear as a breakpoint hit if the next instruction also contained a breakpoint.  We don't want
            // to handle that, since we really don't know what to do with breakpoint hits.  But make sure we don't set
            // ourselves to auto-continue or we'll wrench control away from the plans that can deal with this.
            SetAutoContinue(false);
            return false;
        default:
            return false;
        }
    }
    return false;
}

bool
ThreadPlanStepOverBreakpoint::ShouldStop (Event *event_ptr)
{
    return !ShouldAutoContinue(event_ptr);
}

bool
ThreadPlanStepOverBreakpoint::StopOthers ()
{
    return true;
}

StateType
ThreadPlanStepOverBreakpoint::GetPlanRunState ()
{
    return eStateStepping;
}

bool
ThreadPlanStepOverBreakpoint::DoWillResume (StateType resume_state, bool current_plan)
{
    if (current_plan)
    {
        BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
        if (bp_site_sp  && bp_site_sp->IsEnabled())
            m_thread.GetProcess()->DisableBreakpointSite (bp_site_sp.get());
    }
    return true;
}

bool
ThreadPlanStepOverBreakpoint::WillStop ()
{
    ReenableBreakpointSite ();
    return true;
}

bool
ThreadPlanStepOverBreakpoint::MischiefManaged ()
{
    lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC();

    if (pc_addr == m_breakpoint_addr)
    {
        // If we are still at the PC of our breakpoint, then for some reason we didn't
        // get a chance to run.
        return false;
    }
    else
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
        if (log)
            log->Printf("Completed step over breakpoint plan.");
        // Otherwise, re-enable the breakpoint we were stepping over, and we're done.
        ReenableBreakpointSite ();
        ThreadPlan::MischiefManaged ();
        return true;
    }
}

void
ThreadPlanStepOverBreakpoint::ReenableBreakpointSite ()
{
    if (!m_reenabled_breakpoint_site)
    {
        m_reenabled_breakpoint_site = true;
        BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
        if (bp_site_sp)
        {
            m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get());
        }
    }
}
void
ThreadPlanStepOverBreakpoint::ThreadDestroyed ()
{
    ReenableBreakpointSite ();
}

void
ThreadPlanStepOverBreakpoint::SetAutoContinue (bool do_it)
{
    m_auto_continue = do_it;
}

bool
ThreadPlanStepOverBreakpoint::ShouldAutoContinue (Event *event_ptr)
{
    return m_auto_continue;
}

bool
ThreadPlanStepOverBreakpoint::IsPlanStale()
{
    return m_thread.GetRegisterContext()->GetPC() != m_breakpoint_addr;
}

