//===-- 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 == false;
            }
        }
        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 != NULL)
                            {
                                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;

                    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() != NULL)
                        {
                            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(NULL);
                                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() != NULL)
                {
                    // 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(),
                                                            NULL,
                                                            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) == false)
                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();
}
