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

// C Includes
// C++ Includes
#include <string>

// Other libraries and framework includes
// Project includes
#include "lldb/Target/StopInfo.h"
#include "lldb/Core/Log.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/UnixSignals.h"

using namespace lldb;
using namespace lldb_private;

StopInfo::StopInfo (Thread &thread, uint64_t value) :
    m_thread_wp (thread.shared_from_this()),
    m_stop_id (thread.GetProcess()->GetStopID()),
    m_resume_id (thread.GetProcess()->GetResumeID()),
    m_value (value),
    m_description (),
    m_override_should_notify (eLazyBoolCalculate),
    m_override_should_stop (eLazyBoolCalculate),
    m_extended_info()
{
}

bool
StopInfo::IsValid () const
{
    ThreadSP thread_sp (m_thread_wp.lock());
    if (thread_sp)
        return thread_sp->GetProcess()->GetStopID() == m_stop_id;
    return false;
}

void
StopInfo::MakeStopInfoValid ()
{
    ThreadSP thread_sp (m_thread_wp.lock());
    if (thread_sp)
    {
        m_stop_id = thread_sp->GetProcess()->GetStopID();
        m_resume_id = thread_sp->GetProcess()->GetResumeID();
    }
}

bool
StopInfo::HasTargetRunSinceMe ()
{
    ThreadSP thread_sp (m_thread_wp.lock());

    if (thread_sp)
    {
        lldb::StateType ret_type = thread_sp->GetProcess()->GetPrivateState();
        if (ret_type == eStateRunning)
        {
            return true;
        }
        else if (ret_type == eStateStopped)
        {
            // This is a little tricky.  We want to count "run and stopped again before you could
            // ask this question as a "TRUE" answer to HasTargetRunSinceMe.  But we don't want to 
            // include any running of the target done for expressions.  So we track both resumes,
            // and resumes caused by expressions, and check if there are any resumes NOT caused
            // by expressions.
            
            uint32_t curr_resume_id = thread_sp->GetProcess()->GetResumeID();
            uint32_t last_user_expression_id = thread_sp->GetProcess()->GetLastUserExpressionResumeID ();
            if (curr_resume_id == m_resume_id)
            {
                return false;
            }
            else if (curr_resume_id > last_user_expression_id)
            {
                return true;
            }
        }
    }
    return false;
}

//----------------------------------------------------------------------
// StopInfoBreakpoint
//----------------------------------------------------------------------

namespace lldb_private
{
class StopInfoBreakpoint : public StopInfo
{
public:
    StopInfoBreakpoint (Thread &thread, break_id_t break_id) :
        StopInfo (thread, break_id),
        m_should_stop (false),
        m_should_stop_is_valid (false),
        m_should_perform_action (true),
        m_address (LLDB_INVALID_ADDRESS),
        m_break_id(LLDB_INVALID_BREAK_ID),
        m_was_one_shot (false)
    {
        StoreBPInfo();
    }

    StopInfoBreakpoint (Thread &thread, break_id_t break_id, bool should_stop) :
        StopInfo (thread, break_id),
        m_should_stop (should_stop),
        m_should_stop_is_valid (true),
        m_should_perform_action (true),
        m_address (LLDB_INVALID_ADDRESS),
        m_break_id(LLDB_INVALID_BREAK_ID),
        m_was_one_shot (false)
    {
        StoreBPInfo();
    }

    ~StopInfoBreakpoint() override = default;

    void
    StoreBPInfo ()
    {
        ThreadSP thread_sp (m_thread_wp.lock());
        if (thread_sp)
        {
            BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value));
            if (bp_site_sp)
            {
                if (bp_site_sp->GetNumberOfOwners() == 1)
                {
                    BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(0);
                    if (bp_loc_sp)
                    {
                        m_break_id = bp_loc_sp->GetBreakpoint().GetID();
                        m_was_one_shot = bp_loc_sp->GetBreakpoint().IsOneShot();
                    }
                }
                m_address = bp_site_sp->GetLoadAddress();
            }
        }
    }

    bool
    IsValidForOperatingSystemThread(Thread &thread) override
    {
        ProcessSP process_sp (thread.GetProcess());
        if (process_sp)
        {
            BreakpointSiteSP bp_site_sp (process_sp->GetBreakpointSiteList().FindByID (m_value));
            if (bp_site_sp)
                return bp_site_sp->ValidForThisThread (&thread);
        }
        return false;
    }

    StopReason
    GetStopReason() const override
    {
        return eStopReasonBreakpoint;
    }

    bool
    ShouldStopSynchronous(Event *event_ptr) override
    {
        ThreadSP thread_sp (m_thread_wp.lock());
        if (thread_sp)
        {
            if (!m_should_stop_is_valid)
            {
                // Only check once if we should stop at a breakpoint
                BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value));
                if (bp_site_sp)
                {
                    ExecutionContext exe_ctx (thread_sp->GetStackFrameAtIndex(0));
                    StoppointCallbackContext context (event_ptr, exe_ctx, true);
                    bp_site_sp->BumpHitCounts();
                    m_should_stop = bp_site_sp->ShouldStop (&context);
                }
                else
                {
                    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

                    if (log)
                        log->Printf ("Process::%s could not find breakpoint site id: %" PRId64 "...", __FUNCTION__, m_value);

                    m_should_stop = true;
                }
                m_should_stop_is_valid = true;
            }
            return m_should_stop;
        }
        return false;
    }

    bool
    DoShouldNotify(Event *event_ptr) override
    {
        ThreadSP thread_sp (m_thread_wp.lock());
        if (thread_sp)
        {
            BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value));
            if (bp_site_sp)
            {
                bool all_internal = true;

                for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++)
                {
                    if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
                    {
                        all_internal = false;
                        break;
                    }
                }
                return !all_internal;
            }
        }
        return true;
    }

    const char *
    GetDescription() override
    {
        if (m_description.empty())
        {
            ThreadSP thread_sp (m_thread_wp.lock());
            if (thread_sp)
            {
                BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value));
                if (bp_site_sp)
                {
                    StreamString strm;
                    // If we have just hit an internal breakpoint, and it has a kind description, print that instead of the
                    // full breakpoint printing:
                    if (bp_site_sp->IsInternal())
                    {
                        size_t num_owners = bp_site_sp->GetNumberOfOwners();
                        for (size_t idx = 0; idx < num_owners; idx++)
                        {
                            const char *kind = bp_site_sp->GetOwnerAtIndex(idx)->GetBreakpoint().GetBreakpointKind();
                            if (kind != nullptr)
                            {
                                m_description.assign (kind);
                                return kind;
                            }
                        }
                    }

                    strm.Printf("breakpoint ");
                    bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief);
                    m_description.swap (strm.GetString());
                }
                else
                {
                    StreamString strm;
                    if (m_break_id != LLDB_INVALID_BREAK_ID)
                    {
                        BreakpointSP break_sp = thread_sp->GetProcess()->GetTarget().GetBreakpointByID(m_break_id);
                        if (break_sp)
                        {
                            if (break_sp->IsInternal())
                            {
                                const char *kind = break_sp->GetBreakpointKind();
                                if (kind)
                                    strm.Printf ("internal %s breakpoint(%d).", kind, m_break_id);
                                else
                                    strm.Printf ("internal breakpoint(%d).", m_break_id);
                            }
                            else
                            {
                                strm.Printf ("breakpoint %d.", m_break_id);
                            }
                        } 
                        else
                        {
                            if (m_was_one_shot)
                                strm.Printf ("one-shot breakpoint %d", m_break_id);
                            else
                                strm.Printf ("breakpoint %d which has been deleted.", m_break_id);
                        }
                    }
                    else if (m_address == LLDB_INVALID_ADDRESS)
                        strm.Printf("breakpoint site %" PRIi64 " which has been deleted - unknown address", m_value);
                    else
                        strm.Printf("breakpoint site %" PRIi64 " which has been deleted - was at 0x%" PRIx64, m_value, m_address);

                    m_description.swap (strm.GetString());
                }
            }
        }
        return m_description.c_str();
    }

protected:
    bool
    ShouldStop(Event *event_ptr) override
    {
        // This just reports the work done by PerformAction or the synchronous stop.  It should
        // only ever get called after they have had a chance to run.
        assert (m_should_stop_is_valid);
        return m_should_stop;
    }

    void
    PerformAction(Event *event_ptr) override
    {
        if (!m_should_perform_action)
            return;
        m_should_perform_action = false;

        ThreadSP thread_sp (m_thread_wp.lock());

        if (thread_sp)
        {
            Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS | LIBLLDB_LOG_STEP);

            if (!thread_sp->IsValid())
            {
                // This shouldn't ever happen, but just in case, don't do more harm.
                if (log)
                {
                    log->Printf ("PerformAction got called with an invalid thread.");
                }
                m_should_stop = true;
                m_should_stop_is_valid = true;
                return;
            }

            BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value));
            std::unordered_set<break_id_t> precondition_breakpoints;

            if (bp_site_sp)
            {
                // Let's copy the owners list out of the site and store them in a local list.  That way if
                // one of the breakpoint actions changes the site, then we won't be operating on a bad list.
                BreakpointLocationCollection site_locations;
                size_t num_owners = bp_site_sp->CopyOwnersList(site_locations);

                if (num_owners == 0)
                {
                    m_should_stop = true;
                }
                else
                {
                    // We go through each location, and test first its precondition - this overrides everything.  Note,
                    // we only do this once per breakpoint - not once per location...
                    // Then check the condition.  If the condition says to stop,
                    // then we run the callback for that location.  If that callback says to stop as well, then 
                    // we set m_should_stop to true; we are going to stop.
                    // But we still want to give all the breakpoints whose conditions say we are going to stop a
                    // chance to run their callbacks.
                    // Of course if any callback restarts the target by putting "continue" in the callback, then 
                    // we're going to restart, without running the rest of the callbacks.  And in this case we will
                    // end up not stopping even if another location said we should stop.  But that's better than not
                    // running all the callbacks.

                    m_should_stop = false;
                    
                    // We don't select threads as we go through them testing breakpoint conditions and running commands.
                    // So we need to set the thread for expression evaluation here:
                    ThreadList::ExpressionExecutionThreadPusher thread_pusher(thread_sp);

                    ExecutionContext exe_ctx (thread_sp->GetStackFrameAtIndex(0));
                    Process *process  = exe_ctx.GetProcessPtr();
                    if (process->GetModIDRef().IsLastResumeForUserExpression())
                    {
                        // If we are in the middle of evaluating an expression, don't run asynchronous breakpoint commands or
                        // expressions.  That could lead to infinite recursion if the command or condition re-calls the function
                        // with this breakpoint.
                        // TODO: We can keep a list of the breakpoints we've seen while running expressions in the nested
                        // PerformAction calls that can arise when the action runs a function that hits another breakpoint,
                        // and only stop running commands when we see the same breakpoint hit a second time.

                        m_should_stop_is_valid = true;
                        if (log)
                            log->Printf ("StopInfoBreakpoint::PerformAction - Hit a breakpoint while running an expression,"
                                         " not running commands to avoid recursion.");
                        bool ignoring_breakpoints = process->GetIgnoreBreakpointsInExpressions();
                        if (ignoring_breakpoints)
                        {
                            m_should_stop = false;
                            // Internal breakpoints will always stop.  
                            for (size_t j = 0; j < num_owners; j++)
                            {
                                lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j);
                                if (bp_loc_sp->GetBreakpoint().IsInternal())
                                {
                                    m_should_stop = true;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            m_should_stop = true;
                        }
                        if (log)
                            log->Printf ("StopInfoBreakpoint::PerformAction - in expression, continuing: %s.",
                                         m_should_stop ? "true" : "false");
                        process->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf("Warning: hit breakpoint while "
                                               "running function, skipping commands and conditions to prevent recursion.");
                        return;
                    }

                    StoppointCallbackContext context (event_ptr, exe_ctx, false);

                    // For safety's sake let's also grab an extra reference to the breakpoint owners of the locations we're
                    // going to examine, since the locations are going to have to get back to their breakpoints, and the
                    // locations don't keep their owners alive.  I'm just sticking the BreakpointSP's in a vector since
                    // I'm only using it to locally increment their retain counts.

                    std::vector<lldb::BreakpointSP> location_owners;

                    for (size_t j = 0; j < num_owners; j++)
                    {
                        BreakpointLocationSP loc(site_locations.GetByIndex(j));
                        location_owners.push_back(loc->GetBreakpoint().shared_from_this());

                    }

                    for (size_t j = 0; j < num_owners; j++)
                    {
                        lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j);

                        // If another action disabled this breakpoint or its location, then don't run the actions.
                        if (!bp_loc_sp->IsEnabled() || !bp_loc_sp->GetBreakpoint().IsEnabled())
                            continue;

                        // The breakpoint site may have many locations associated with it, not all of them valid for
                        // this thread.  Skip the ones that aren't:
                        if (!bp_loc_sp->ValidForThisThread(thread_sp.get()))
                        {
                            if (log)
                            {
                                StreamString s;
                                bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief);
                                log->Printf ("Breakpoint %s hit on thread 0x%llx but it was not for this thread, continuing.",
                                             s.GetData(),
                                             static_cast<unsigned long long>(thread_sp->GetID()));
                            }
                            continue;
                        }

                        // First run the precondition, but since the precondition is per breakpoint, only run it once
                        // per breakpoint.
                        std::pair<std::unordered_set<break_id_t>::iterator, bool> result
                                = precondition_breakpoints.insert(bp_loc_sp->GetBreakpoint().GetID());
                        if (!result.second)
                            continue;

                        bool precondition_result = bp_loc_sp->GetBreakpoint().EvaluatePrecondition(context);
                        if (!precondition_result)
                            continue;

                        // Next run the condition for the breakpoint.  If that says we should stop, then we'll run
                        // the callback for the breakpoint.  If the callback says we shouldn't stop that will win.                    

                        if (bp_loc_sp->GetConditionText() != nullptr)
                        {
                            Error condition_error;
                            bool condition_says_stop = bp_loc_sp->ConditionSaysStop(exe_ctx, condition_error);

                            if (!condition_error.Success())
                            {
                                Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
                                StreamSP error_sp = debugger.GetAsyncErrorStream ();
                                error_sp->Printf ("Stopped due to an error evaluating condition of breakpoint ");
                                bp_loc_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief);
                                error_sp->Printf (": \"%s\"",
                                                  bp_loc_sp->GetConditionText());
                                error_sp->EOL();
                                const char *err_str = condition_error.AsCString("<Unknown Error>");
                                if (log)
                                    log->Printf("Error evaluating condition: \"%s\"\n", err_str);

                                error_sp->PutCString (err_str);
                                error_sp->EOL();
                                error_sp->Flush();
                            }
                            else
                            {
                                if (log)
                                {
                                    StreamString s;
                                    bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief);
                                    log->Printf ("Condition evaluated for breakpoint %s on thread 0x%llx conditon_says_stop: %i.",
                                                 s.GetData(),
                                                 static_cast<unsigned long long>(thread_sp->GetID()),
                                                 condition_says_stop);
                                }
                                if (!condition_says_stop)
                                {
                                    // We don't want to increment the hit count of breakpoints if the condition fails.
                                    // We've already bumped it by the time we get here, so undo the bump:
                                    bp_loc_sp->UndoBumpHitCount();
                                    continue;
                                }
                            }
                        }

                        bool callback_says_stop;

                        // FIXME: For now the callbacks have to run in async mode - the first time we restart we need
                        // to get out of there.  So set it here.
                        // When we figure out how to nest breakpoint hits then this will change.

                        Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger();
                        bool old_async = debugger.GetAsyncExecution();
                        debugger.SetAsyncExecution (true);

                        callback_says_stop = bp_loc_sp->InvokeCallback (&context);

                        debugger.SetAsyncExecution (old_async);

                        if (callback_says_stop)
                            m_should_stop = true;

                        // If we are going to stop for this breakpoint, then remove the breakpoint.
                        if (callback_says_stop && bp_loc_sp && bp_loc_sp->GetBreakpoint().IsOneShot())
                        {
                            thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID (bp_loc_sp->GetBreakpoint().GetID());
                        }

                        // Also make sure that the callback hasn't continued the target.  
                        // If it did, when we'll set m_should_start to false and get out of here.
                        if (HasTargetRunSinceMe ())
                        {
                            m_should_stop = false;
                            break;
                        }
                    }
                }
                // We've figured out what this stop wants to do, so mark it as valid so we don't compute it again.
                m_should_stop_is_valid = true;
            }
            else
            {
                m_should_stop = true;
                m_should_stop_is_valid = true;
                Log * log_process(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

                if (log_process)
                    log_process->Printf ("Process::%s could not find breakpoint site id: %" PRId64 "...", __FUNCTION__, m_value);
            }
            if (log)
                log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop);
        }
    }

private:
    bool m_should_stop;
    bool m_should_stop_is_valid;
    bool m_should_perform_action; // Since we are trying to preserve the "state" of the system even if we run functions
                                  // etc. behind the users backs, we need to make sure we only REALLY perform the action once.
    lldb::addr_t m_address;       // We use this to capture the breakpoint site address when we create the StopInfo,
                                  // in case somebody deletes it between the time the StopInfo is made and the
                                  // description is asked for.
    lldb::break_id_t m_break_id;
    bool m_was_one_shot;
};

//----------------------------------------------------------------------
// StopInfoWatchpoint
//----------------------------------------------------------------------

class StopInfoWatchpoint : public StopInfo
{
public:
    // Make sure watchpoint is properly disabled and subsequently enabled while performing watchpoint actions.
    class WatchpointSentry {
    public:
        WatchpointSentry(Process *p, Watchpoint *w):
            process(p),
            watchpoint(w)
        {
            if (process && watchpoint)
            {
                const bool notify = false;
                watchpoint->TurnOnEphemeralMode();
                process->DisableWatchpoint(watchpoint, notify);
            }
        }

        ~WatchpointSentry()
        {
            if (process && watchpoint)
            {
                if (!watchpoint->IsDisabledDuringEphemeralMode())
                {
                    const bool notify = false;
                    process->EnableWatchpoint(watchpoint, notify);
                }
                watchpoint->TurnOffEphemeralMode();
            }
        }

    private:
        Process *process;
        Watchpoint *watchpoint;
    };

    StopInfoWatchpoint (Thread &thread, break_id_t watch_id, lldb::addr_t watch_hit_addr) :
        StopInfo(thread, watch_id),
        m_should_stop(false),
        m_should_stop_is_valid(false),
        m_watch_hit_addr(watch_hit_addr)
    {
    }

    ~StopInfoWatchpoint() override = default;

    StopReason
    GetStopReason() const override
    {
        return eStopReasonWatchpoint;
    }

    const char *
    GetDescription() override
    {
        if (m_description.empty())
        {
            StreamString strm;
            strm.Printf("watchpoint %" PRIi64, m_value);
            m_description.swap (strm.GetString());
        }
        return m_description.c_str();
    }

protected:
    bool
    ShouldStopSynchronous(Event *event_ptr) override
    {
        // ShouldStop() method is idempotent and should not affect hit count.
        // See Process::RunPrivateStateThread()->Process()->HandlePrivateEvent()
        // -->Process()::ShouldBroadcastEvent()->ThreadList::ShouldStop()->
        // Thread::ShouldStop()->ThreadPlanBase::ShouldStop()->
        // StopInfoWatchpoint::ShouldStop() and
        // Event::DoOnRemoval()->Process::ProcessEventData::DoOnRemoval()->
        // StopInfoWatchpoint::PerformAction().
        if (m_should_stop_is_valid)
            return m_should_stop;

        ThreadSP thread_sp (m_thread_wp.lock());
        if (thread_sp)
        {
            WatchpointSP wp_sp (thread_sp->CalculateTarget()->GetWatchpointList().FindByID(GetValue()));
            if (wp_sp)
            {
                // Check if we should stop at a watchpoint.
                ExecutionContext exe_ctx (thread_sp->GetStackFrameAtIndex(0));
                StoppointCallbackContext context (event_ptr, exe_ctx, true);
                m_should_stop = wp_sp->ShouldStop (&context);
            }
            else
            {
                Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

                if (log)
                    log->Printf ("Process::%s could not find watchpoint location id: %" PRId64 "...",
                                 __FUNCTION__, GetValue());

                m_should_stop = true;
            }
        }
        m_should_stop_is_valid = true;
        return m_should_stop;
    }
    
    bool
    ShouldStop(Event *event_ptr) override
    {
        // This just reports the work done by PerformAction or the synchronous stop.  It should
        // only ever get called after they have had a chance to run.
        assert (m_should_stop_is_valid);
        return m_should_stop;
    }
    
    void
    PerformAction(Event *event_ptr) override
    {
        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS);
        // We're going to calculate if we should stop or not in some way during the course of
        // this code.  Also by default we're going to stop, so set that here.
        m_should_stop = true;
        
        ThreadSP thread_sp (m_thread_wp.lock());
        if (thread_sp)
        {

            WatchpointSP wp_sp (thread_sp->CalculateTarget()->GetWatchpointList().FindByID(GetValue()));
            if (wp_sp)
            {
                ExecutionContext exe_ctx (thread_sp->GetStackFrameAtIndex(0));
                Process* process = exe_ctx.GetProcessPtr();

                // This sentry object makes sure the current watchpoint is disabled while performing watchpoint actions,
                // and it is then enabled after we are finished.
                WatchpointSentry sentry(process, wp_sp.get());

                {
                    // check if this process is running on an architecture where watchpoints trigger
                    // before the associated instruction runs. if so, disable the WP, single-step and then
                    // re-enable the watchpoint
                    if (process)
                    {
                        uint32_t num;
                        bool wp_triggers_after;
                        if (process->GetWatchpointSupportInfo(num, wp_triggers_after).Success())
                        {
                            if (!wp_triggers_after)
                            {
                                StopInfoSP stored_stop_info_sp = thread_sp->GetStopInfo();
                                assert (stored_stop_info_sp.get() == this);
                                
                                ThreadPlanSP new_plan_sp(thread_sp->QueueThreadPlanForStepSingleInstruction(false, // step-over
                                                                                                            false,     // abort_other_plans
                                                                                                            true));    // stop_other_threads
                                new_plan_sp->SetIsMasterPlan (true);
                                new_plan_sp->SetOkayToDiscard (false);
                                new_plan_sp->SetPrivate (true);
                                process->GetThreadList().SetSelectedThreadByID (thread_sp->GetID());
                                process->ResumeSynchronous(nullptr);
                                process->GetThreadList().SetSelectedThreadByID (thread_sp->GetID());
                                thread_sp->SetStopInfo(stored_stop_info_sp);
                            }
                        }
                    }
                }

                /*
                 * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For example:
                 * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at 'm', then
                 * watch exception is generated even when 'n' is read/written. To handle this case,
                 * server emulates the instruction at PC and finds the base address of the load/store
                 * instruction and appends it in the description of the stop-info packet. If watchpoint
                 * is not set on this address by user then this do not stop.
                */
                if (m_watch_hit_addr != LLDB_INVALID_ADDRESS)
                {
                    WatchpointSP wp_hit_sp = thread_sp->CalculateTarget()->GetWatchpointList().FindByAddress(m_watch_hit_addr);
                    if (!wp_hit_sp)
                    {
                        m_should_stop = false;
                        wp_sp->IncrementFalseAlarmsAndReviseHitCount();
                    }
                }

                // TODO: This condition should be checked in the synchronous part of the watchpoint code
                // (Watchpoint::ShouldStop), so that we avoid pulling an event even if the watchpoint fails
                // the ignore count condition. It is moved here temporarily, because for archs with 
                // watchpoint_exceptions_received=before, the code in the previous lines takes care of moving
                // the inferior to next PC. We have to check the ignore count condition after this is done,
                // otherwise we will hit same watchpoint multiple times until we pass ignore condition, but we
                // won't actually be ignoring them.
                if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount())
                    m_should_stop = false;

                if (m_should_stop && wp_sp->GetConditionText() != nullptr)
                {
                    // We need to make sure the user sees any parse errors in their condition, so we'll hook the
                    // constructor errors up to the debugger's Async I/O.
                    ExpressionResults result_code;
                    EvaluateExpressionOptions expr_options;
                    expr_options.SetUnwindOnError(true);
                    expr_options.SetIgnoreBreakpoints(true);
                    ValueObjectSP result_value_sp;
                    Error error;
                    result_code = UserExpression::Evaluate(exe_ctx,
                                                           expr_options,
                                                           wp_sp->GetConditionText(),
                                                           nullptr,
                                                           result_value_sp,
                                                           error);
                                                            
                    if (result_code == eExpressionCompleted)
                    {
                        if (result_value_sp)
                        {
                            Scalar scalar_value;
                            if (result_value_sp->ResolveValue (scalar_value))
                            {
                                if (scalar_value.ULongLong(1) == 0)
                                {
                                    // We have been vetoed.  This takes precedence over querying
                                    // the watchpoint whether it should stop (aka ignore count and
                                    // friends).  See also StopInfoWatchpoint::ShouldStop() as well
                                    // as Process::ProcessEventData::DoOnRemoval().
                                    m_should_stop = false;
                                }
                                else
                                    m_should_stop = true;
                                if (log)
                                    log->Printf("Condition successfully evaluated, result is %s.\n", 
                                                m_should_stop ? "true" : "false");
                            }
                            else
                            {
                                m_should_stop = true;
                                if (log)
                                    log->Printf("Failed to get an integer result from the expression.");
                            }
                        }
                    }
                    else
                    {
                        Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
                        StreamSP error_sp = debugger.GetAsyncErrorStream ();
                        error_sp->Printf ("Stopped due to an error evaluating condition of watchpoint ");
                        wp_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief);
                        error_sp->Printf (": \"%s\"", 
                                          wp_sp->GetConditionText());
                        error_sp->EOL();
                        const char *err_str = error.AsCString("<Unknown Error>");
                        if (log)
                            log->Printf("Error evaluating condition: \"%s\"\n", err_str);

                        error_sp->PutCString (err_str);
                        error_sp->EOL();                       
                        error_sp->Flush();
                        // If the condition fails to be parsed or run, we should stop.
                        m_should_stop = true;
                    }
                }

                // If the condition says to stop, we run the callback to further decide whether to stop.
                if (m_should_stop)
                {
                    StoppointCallbackContext context (event_ptr, exe_ctx, false);
                    bool stop_requested = wp_sp->InvokeCallback (&context);
                    // Also make sure that the callback hasn't continued the target.  
                    // If it did, when we'll set m_should_stop to false and get out of here.
                    if (HasTargetRunSinceMe ())
                        m_should_stop = false;
                    
                    if (m_should_stop && !stop_requested)
                    {
                        // We have been vetoed by the callback mechanism.
                        m_should_stop = false;
                    }
                }
                // Finally, if we are going to stop, print out the new & old values:
                if (m_should_stop)
                {
                    wp_sp->CaptureWatchedValue(exe_ctx);
                    
                    Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
                    StreamSP output_sp = debugger.GetAsyncOutputStream ();
                    wp_sp->DumpSnapshots(output_sp.get());
                    output_sp->EOL();
                    output_sp->Flush();
                }
                
            }
            else
            {
                Log * log_process(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

                if (log_process)
                    log_process->Printf ("Process::%s could not find watchpoint id: %" PRId64 "...", __FUNCTION__, m_value);
            }
            if (log)
                log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop);
            
            m_should_stop_is_valid = true;
        }
    }
        
private:
    bool m_should_stop;
    bool m_should_stop_is_valid;
    lldb::addr_t m_watch_hit_addr;
};

//----------------------------------------------------------------------
// StopInfoUnixSignal
//----------------------------------------------------------------------

class StopInfoUnixSignal : public StopInfo
{
public:
    StopInfoUnixSignal (Thread &thread, int signo, const char *description) :
        StopInfo (thread, signo)
    {
        SetDescription (description);
    }

    ~StopInfoUnixSignal() override = default;

    StopReason
    GetStopReason() const override
    {
        return eStopReasonSignal;
    }

    bool
    ShouldStopSynchronous(Event *event_ptr) override
    {
        ThreadSP thread_sp (m_thread_wp.lock());
        if (thread_sp)
            return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);
        return false;
    }

    bool
    ShouldStop(Event *event_ptr) override
    {
        ThreadSP thread_sp (m_thread_wp.lock());
        if (thread_sp)
            return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);
        return false;
    }

    // If should stop returns false, check if we should notify of this event
    bool
    DoShouldNotify(Event *event_ptr) override
    {
        ThreadSP thread_sp (m_thread_wp.lock());
        if (thread_sp)
        {
            bool should_notify = thread_sp->GetProcess()->GetUnixSignals()->GetShouldNotify(m_value);
            if (should_notify)
            {
                StreamString strm;
                strm.Printf ("thread %d received signal: %s",
                             thread_sp->GetIndexID(),
                             thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(m_value));
                Process::ProcessEventData::AddRestartedReason(event_ptr, strm.GetData());
            }
            return should_notify;
        }
        return true;
    }

    void
    WillResume(lldb::StateType resume_state) override
    {
        ThreadSP thread_sp (m_thread_wp.lock());
        if (thread_sp)
        {
            if (!thread_sp->GetProcess()->GetUnixSignals()->GetShouldSuppress(m_value))
                thread_sp->SetResumeSignal(m_value);
        }
    }

    const char *
    GetDescription() override
    {
        if (m_description.empty())
        {
            ThreadSP thread_sp (m_thread_wp.lock());
            if (thread_sp)
            {
                StreamString strm;
                const char *signal_name = thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(m_value);
                if (signal_name)
                    strm.Printf("signal %s", signal_name);
                else
                    strm.Printf("signal %" PRIi64, m_value);
                m_description.swap (strm.GetString());
            }
        }
        return m_description.c_str();
    }
};

//----------------------------------------------------------------------
// StopInfoTrace
//----------------------------------------------------------------------

class StopInfoTrace : public StopInfo
{
public:
    StopInfoTrace (Thread &thread) :
        StopInfo (thread, LLDB_INVALID_UID)
    {
    }

    ~StopInfoTrace() override = default;

    StopReason
    GetStopReason() const override
    {
        return eStopReasonTrace;
    }

    const char *
    GetDescription() override
    {
        if (m_description.empty())
            return "trace";
        else
            return m_description.c_str();
    }
};

//----------------------------------------------------------------------
// StopInfoException
//----------------------------------------------------------------------

class StopInfoException : public StopInfo
{
public:
    StopInfoException (Thread &thread, const char *description) :
        StopInfo (thread, LLDB_INVALID_UID)
    {
        if (description)
            SetDescription (description);
    }

    ~StopInfoException() override = default;

    StopReason
    GetStopReason() const override
    {
        return eStopReasonException;
    }
    
    const char *
    GetDescription() override
    {
        if (m_description.empty())
            return "exception";
        else
            return m_description.c_str();
    }
};

//----------------------------------------------------------------------
// StopInfoThreadPlan
//----------------------------------------------------------------------

class StopInfoThreadPlan : public StopInfo
{
public:
    StopInfoThreadPlan (ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp, ExpressionVariableSP &expression_variable_sp) :
        StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID),
        m_plan_sp (plan_sp),
        m_return_valobj_sp (return_valobj_sp),
        m_expression_variable_sp (expression_variable_sp)
    {
    }

    ~StopInfoThreadPlan() override = default;

    StopReason
    GetStopReason() const override
    {
        return eStopReasonPlanComplete;
    }

    const char *
    GetDescription() override
    {
        if (m_description.empty())
        {
            StreamString strm;            
            m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief);
            m_description.swap (strm.GetString());
        }
        return m_description.c_str();
    }
    
    ValueObjectSP
    GetReturnValueObject()
    {
        return m_return_valobj_sp;
    }
    
    ExpressionVariableSP
    GetExpressionVariable()
    {
        return m_expression_variable_sp;
    }
    
protected:
    bool
    ShouldStop(Event *event_ptr) override
    {
        if (m_plan_sp)
            return m_plan_sp->ShouldStop(event_ptr);
        else
            return StopInfo::ShouldStop(event_ptr);
    }

private:
    ThreadPlanSP m_plan_sp;
    ValueObjectSP m_return_valobj_sp;
    ExpressionVariableSP m_expression_variable_sp;
};
    
class StopInfoExec : public StopInfo
{
public:
    StopInfoExec (Thread &thread) :
        StopInfo (thread, LLDB_INVALID_UID),
        m_performed_action (false)
    {
    }

    ~StopInfoExec() override = default;

    StopReason
    GetStopReason() const override
    {
        return eStopReasonExec;
    }
    
    const char *
    GetDescription() override
    {
        return "exec";
    }

protected:
    void
    PerformAction(Event *event_ptr) override
    {
        // Only perform the action once
        if (m_performed_action)
            return;
        m_performed_action = true;
        ThreadSP thread_sp (m_thread_wp.lock());
        if (thread_sp)
            thread_sp->GetProcess()->DidExec();
    }
    
    bool m_performed_action;
};

} // namespace lldb_private

StopInfoSP
StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id)
{
    return StopInfoSP (new StopInfoBreakpoint (thread, break_id));
}

StopInfoSP
StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id, bool should_stop)
{
    return StopInfoSP (new StopInfoBreakpoint (thread, break_id, should_stop));
}

StopInfoSP
StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id, lldb::addr_t watch_hit_addr)
{
    return StopInfoSP (new StopInfoWatchpoint (thread, watch_id, watch_hit_addr));
}

StopInfoSP
StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo, const char *description)
{
    return StopInfoSP (new StopInfoUnixSignal (thread, signo, description));
}

StopInfoSP
StopInfo::CreateStopReasonToTrace (Thread &thread)
{
    return StopInfoSP (new StopInfoTrace (thread));
}

StopInfoSP
StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp,
                                    ValueObjectSP return_valobj_sp,
                                    ExpressionVariableSP expression_variable_sp)
{
    return StopInfoSP (new StopInfoThreadPlan (plan_sp, return_valobj_sp, expression_variable_sp));
}

StopInfoSP
StopInfo::CreateStopReasonWithException (Thread &thread, const char *description)
{
    return StopInfoSP (new StopInfoException (thread, description));
}

StopInfoSP
StopInfo::CreateStopReasonWithExec (Thread &thread)
{
    return StopInfoSP (new StopInfoExec (thread));
}

ValueObjectSP
StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp)
{
    if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonPlanComplete)
    {
        StopInfoThreadPlan *plan_stop_info = static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
        return plan_stop_info->GetReturnValueObject();
    }
    else
        return ValueObjectSP();
}

ExpressionVariableSP
StopInfo::GetExpressionVariable(StopInfoSP &stop_info_sp)
{
    if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonPlanComplete)
    {
        StopInfoThreadPlan *plan_stop_info = static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
        return plan_stop_info->GetExpressionVariable();
    }
    else
        return ExpressionVariableSP();
}
