//===-- Thread.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
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Target/ThreadPlanBase.h"
#include "lldb/Target/ThreadPlanPython.h"
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
#include "lldb/Target/ThreadPlanStepThrough.h"
#include "lldb/Target/ThreadPlanStepInRange.h"
#include "lldb/Target/ThreadPlanStepOverRange.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Target/ThreadPlanStepUntil.h"
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Target/Unwind.h"
#include "Plugins/Process/Utility/UnwindLLDB.h"
#include "Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h"

using namespace lldb;
using namespace lldb_private;

const ThreadPropertiesSP &
Thread::GetGlobalProperties()
{
    static ThreadPropertiesSP g_settings_sp;
    if (!g_settings_sp)
        g_settings_sp.reset (new ThreadProperties (true));
    return g_settings_sp;
}

static PropertyDefinition
g_properties[] =
{
    { "step-in-avoid-nodebug", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, step-in will not stop in functions with no debug information." },
    { "step-out-avoid-nodebug", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, when step-in/step-out/step-over leave the current frame, they will continue to step out till they come to a function with "
                                                                                    "debug information.  Passing a frame argument to step-out will override this option." },
    { "step-avoid-regexp",  OptionValue::eTypeRegex  , true , 0, "^std::", nullptr, "A regular expression defining functions step-in won't stop in." },
    { "step-avoid-libraries",  OptionValue::eTypeFileSpecList  , true , 0, nullptr, nullptr, "A list of libraries that source stepping won't stop in." },
    { "trace-thread",       OptionValue::eTypeBoolean, false, false, nullptr, nullptr, "If true, this thread will single-step and log execution." },
    {  nullptr               , OptionValue::eTypeInvalid, false, 0    , nullptr, nullptr, nullptr  }
};

enum {
    ePropertyStepInAvoidsNoDebug,
    ePropertyStepOutAvoidsNoDebug,
    ePropertyStepAvoidRegex,
    ePropertyStepAvoidLibraries,
    ePropertyEnableThreadTrace
};

class ThreadOptionValueProperties : public OptionValueProperties
{
public:
    ThreadOptionValueProperties (const ConstString &name) :
        OptionValueProperties (name)
    {
    }
    
    // This constructor is used when creating ThreadOptionValueProperties when it
    // is part of a new lldb_private::Thread instance. It will copy all current
    // global property values as needed
    ThreadOptionValueProperties (ThreadProperties *global_properties) :
        OptionValueProperties(*global_properties->GetValueProperties())
    {
    }
    
    const Property *
    GetPropertyAtIndex(const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const override
    {
        // When getting the value for a key from the thread options, we will always
        // try and grab the setting from the current thread if there is one. Else we just
        // use the one from this instance.
        if (exe_ctx)
        {
            Thread *thread = exe_ctx->GetThreadPtr();
            if (thread)
            {
                ThreadOptionValueProperties *instance_properties = static_cast<ThreadOptionValueProperties *>(thread->GetValueProperties().get());
                if (this != instance_properties)
                    return instance_properties->ProtectedGetPropertyAtIndex (idx);
            }
        }
        return ProtectedGetPropertyAtIndex (idx);
    }
};

ThreadProperties::ThreadProperties (bool is_global) :
    Properties ()
{
    if (is_global)
    {
        m_collection_sp.reset (new ThreadOptionValueProperties(ConstString("thread")));
        m_collection_sp->Initialize(g_properties);
    }
    else
        m_collection_sp.reset (new ThreadOptionValueProperties(Thread::GetGlobalProperties().get()));
}

ThreadProperties::~ThreadProperties() = default;

const RegularExpression *
ThreadProperties::GetSymbolsToAvoidRegexp()
{
    const uint32_t idx = ePropertyStepAvoidRegex;
    return m_collection_sp->GetPropertyAtIndexAsOptionValueRegex(nullptr, idx);
}

FileSpecList &
ThreadProperties::GetLibrariesToAvoid() const
{
    const uint32_t idx = ePropertyStepAvoidLibraries;
    OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, false, idx);
    assert(option_value);
    return option_value->GetCurrentValue();
}

bool
ThreadProperties::GetTraceEnabledState() const
{
    const uint32_t idx = ePropertyEnableThreadTrace;
    return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}

bool
ThreadProperties::GetStepInAvoidsNoDebug() const
{
    const uint32_t idx = ePropertyStepInAvoidsNoDebug;
    return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}

bool
ThreadProperties::GetStepOutAvoidsNoDebug() const
{
    const uint32_t idx = ePropertyStepOutAvoidsNoDebug;
    return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}

//------------------------------------------------------------------
// Thread Event Data
//------------------------------------------------------------------

const ConstString &
Thread::ThreadEventData::GetFlavorString ()
{
    static ConstString g_flavor ("Thread::ThreadEventData");
    return g_flavor;
}

Thread::ThreadEventData::ThreadEventData (const lldb::ThreadSP thread_sp) :
    m_thread_sp (thread_sp),
    m_stack_id ()
{
}

Thread::ThreadEventData::ThreadEventData (const lldb::ThreadSP thread_sp, const StackID &stack_id) :
    m_thread_sp (thread_sp),
    m_stack_id (stack_id)
{
}

Thread::ThreadEventData::ThreadEventData () :
    m_thread_sp (),
    m_stack_id ()
{
}

Thread::ThreadEventData::~ThreadEventData() = default;

void
Thread::ThreadEventData::Dump (Stream *s) const
{
}

const Thread::ThreadEventData *
Thread::ThreadEventData::GetEventDataFromEvent (const Event *event_ptr)
{
    if (event_ptr)
    {
        const EventData *event_data = event_ptr->GetData();
        if (event_data && event_data->GetFlavor() == ThreadEventData::GetFlavorString())
            return static_cast <const ThreadEventData *> (event_ptr->GetData());
    }
    return nullptr;
}

ThreadSP
Thread::ThreadEventData::GetThreadFromEvent (const Event *event_ptr)
{
    ThreadSP thread_sp;
    const ThreadEventData *event_data = GetEventDataFromEvent (event_ptr);
    if (event_data)
        thread_sp = event_data->GetThread();
    return thread_sp;
}

StackID
Thread::ThreadEventData::GetStackIDFromEvent (const Event *event_ptr)
{
    StackID stack_id;
    const ThreadEventData *event_data = GetEventDataFromEvent (event_ptr);
    if (event_data)
        stack_id = event_data->GetStackID();
    return stack_id;
}

StackFrameSP
Thread::ThreadEventData::GetStackFrameFromEvent (const Event *event_ptr)
{
    const ThreadEventData *event_data = GetEventDataFromEvent (event_ptr);
    StackFrameSP frame_sp;
    if (event_data)
    {
        ThreadSP thread_sp = event_data->GetThread();
        if (thread_sp)
        {
            frame_sp = thread_sp->GetStackFrameList()->GetFrameWithStackID (event_data->GetStackID());
        }
    }
    return frame_sp;
}

//------------------------------------------------------------------
// Thread class
//------------------------------------------------------------------

ConstString &
Thread::GetStaticBroadcasterClass ()
{
    static ConstString class_name ("lldb.thread");
    return class_name;
}

Thread::Thread (Process &process, lldb::tid_t tid, bool use_invalid_index_id) :
    ThreadProperties (false),
    UserID (tid),
    Broadcaster(&process.GetTarget().GetDebugger(), Thread::GetStaticBroadcasterClass().AsCString()),
    m_process_wp (process.shared_from_this()),
    m_stop_info_sp (),
    m_stop_info_stop_id (0),
    m_stop_info_override_stop_id (0),
    m_index_id (use_invalid_index_id ? LLDB_INVALID_INDEX32 : process.GetNextThreadIndexID(tid)),
    m_reg_context_sp (),
    m_state (eStateUnloaded),
    m_state_mutex (Mutex::eMutexTypeRecursive),
    m_plan_stack (),
    m_completed_plan_stack(),
    m_frame_mutex (Mutex::eMutexTypeRecursive),
    m_curr_frames_sp (),
    m_prev_frames_sp (),
    m_resume_signal (LLDB_INVALID_SIGNAL_NUMBER),
    m_resume_state (eStateRunning),
    m_temporary_resume_state (eStateRunning),
    m_unwinder_ap (),
    m_destroy_called (false),
    m_override_should_notify (eLazyBoolCalculate),
    m_extended_info_fetched (false),
    m_extended_info ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
    if (log)
        log->Printf ("%p Thread::Thread(tid = 0x%4.4" PRIx64 ")",
                     static_cast<void*>(this), GetID());

    CheckInWithManager();
    QueueFundamentalPlan(true);
}

Thread::~Thread()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
    if (log)
        log->Printf ("%p Thread::~Thread(tid = 0x%4.4" PRIx64 ")",
                     static_cast<void*>(this), GetID());
    /// If you hit this assert, it means your derived class forgot to call DoDestroy in its destructor.
    assert (m_destroy_called);
}

void 
Thread::DestroyThread ()
{
    // Tell any plans on the plan stacks that the thread is being destroyed since
    // any plans that have a thread go away in the middle of might need
    // to do cleanup, or in some cases NOT do cleanup...
    for (auto plan : m_plan_stack)
        plan->ThreadDestroyed();

    for (auto plan : m_discarded_plan_stack)
        plan->ThreadDestroyed();

    for (auto plan : m_completed_plan_stack)
        plan->ThreadDestroyed();

    m_destroy_called = true;
    m_plan_stack.clear();
    m_discarded_plan_stack.clear();
    m_completed_plan_stack.clear();
    
    // Push a ThreadPlanNull on the plan stack.  That way we can continue assuming that the
    // plan stack is never empty, but if somebody errantly asks questions of a destroyed thread
    // without checking first whether it is destroyed, they won't crash.
    ThreadPlanSP null_plan_sp(new ThreadPlanNull (*this));
    m_plan_stack.push_back (null_plan_sp);
    
    m_stop_info_sp.reset();
    m_reg_context_sp.reset();
    m_unwinder_ap.reset();
    Mutex::Locker locker(m_frame_mutex);
    m_curr_frames_sp.reset();
    m_prev_frames_sp.reset();
}

void
Thread::BroadcastSelectedFrameChange(StackID &new_frame_id)
{
    if (EventTypeHasListeners(eBroadcastBitSelectedFrameChanged))
        BroadcastEvent(eBroadcastBitSelectedFrameChanged, new ThreadEventData (this->shared_from_this(), new_frame_id));
}

lldb::StackFrameSP
Thread::GetSelectedFrame()
{
    StackFrameListSP stack_frame_list_sp(GetStackFrameList());
    StackFrameSP frame_sp = stack_frame_list_sp->GetFrameAtIndex (stack_frame_list_sp->GetSelectedFrameIndex());
    FunctionOptimizationWarning (frame_sp.get());
    return frame_sp;
}

uint32_t
Thread::SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast)
{
    uint32_t ret_value = GetStackFrameList()->SetSelectedFrame(frame);
    if (broadcast)
        BroadcastSelectedFrameChange(frame->GetStackID());
    FunctionOptimizationWarning (frame);
    return ret_value;
}

bool
Thread::SetSelectedFrameByIndex (uint32_t frame_idx, bool broadcast)
{
    StackFrameSP frame_sp(GetStackFrameList()->GetFrameAtIndex (frame_idx));
    if (frame_sp)
    {
        GetStackFrameList()->SetSelectedFrame(frame_sp.get());
        if (broadcast)
            BroadcastSelectedFrameChange(frame_sp->GetStackID());
        FunctionOptimizationWarning (frame_sp.get());
        return true;
    }
    else
        return false;
}

bool
Thread::SetSelectedFrameByIndexNoisily (uint32_t frame_idx, Stream &output_stream)
{
    const bool broadcast = true;
    bool success = SetSelectedFrameByIndex (frame_idx, broadcast);
    if (success)
    {
        StackFrameSP frame_sp = GetSelectedFrame();
        if (frame_sp)
        {
            bool already_shown = false;
            SymbolContext frame_sc(frame_sp->GetSymbolContext(eSymbolContextLineEntry));
            if (GetProcess()->GetTarget().GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
            {
                already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
            }

            bool show_frame_info = true;
            bool show_source = !already_shown;
            FunctionOptimizationWarning (frame_sp.get());
            return frame_sp->GetStatus (output_stream, show_frame_info, show_source);
        }
        return false;
    }
    else
        return false;
}

void
Thread::FunctionOptimizationWarning (StackFrame *frame)
{
    if (frame && frame->HasDebugInformation() && GetProcess()->GetWarningsOptimization())
    {
        SymbolContext sc = frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextModule);
        GetProcess()->PrintWarningOptimization (sc);
    }
}

lldb::StopInfoSP
Thread::GetStopInfo ()
{
    if (m_destroy_called)
        return m_stop_info_sp;

    ThreadPlanSP plan_sp (GetCompletedPlan());
    ProcessSP process_sp (GetProcess());
    const uint32_t stop_id = process_sp ? process_sp->GetStopID() : UINT32_MAX;
    if (plan_sp && plan_sp->PlanSucceeded())
    {
        return StopInfo::CreateStopReasonWithPlan (plan_sp, GetReturnValueObject(), GetExpressionVariable());
    }
    else
    {
        if ((m_stop_info_stop_id == stop_id) ||   // Stop info is valid, just return what we have (even if empty)
            (m_stop_info_sp && m_stop_info_sp->IsValid()))  // Stop info is valid, just return what we have
        {
            return m_stop_info_sp;
        }
        else
        {
            GetPrivateStopInfo ();
            return m_stop_info_sp;
        }
    }
}

lldb::StopInfoSP
Thread::GetPrivateStopInfo ()
{
    if (m_destroy_called)
        return m_stop_info_sp;

    ProcessSP process_sp (GetProcess());
    if (process_sp)
    {
        const uint32_t process_stop_id = process_sp->GetStopID();
        if (m_stop_info_stop_id != process_stop_id)
        {
            if (m_stop_info_sp)
            {
                if (m_stop_info_sp->IsValid()
                    || IsStillAtLastBreakpointHit()
                    || GetCurrentPlan()->IsVirtualStep())
                    SetStopInfo (m_stop_info_sp);
                else
                    m_stop_info_sp.reset();
            }

            if (!m_stop_info_sp)
            {
                if (!CalculateStopInfo())
                    SetStopInfo (StopInfoSP());
            }
        }

        // The stop info can be manually set by calling Thread::SetStopInfo()
        // prior to this function ever getting called, so we can't rely on
        // "m_stop_info_stop_id != process_stop_id" as the condition for
        // the if statement below, we must also check the stop info to see
        // if we need to override it. See the header documentation in
        // Process::GetStopInfoOverrideCallback() for more information on
        // the stop info override callback.
        if (m_stop_info_override_stop_id != process_stop_id)
        {
            m_stop_info_override_stop_id = process_stop_id;
            if (m_stop_info_sp)
            {
                ArchSpec::StopInfoOverrideCallbackType callback = GetProcess()->GetStopInfoOverrideCallback();
                if (callback)
                    callback(*this);
            }
        }
    }
    return m_stop_info_sp;
}

lldb::StopReason
Thread::GetStopReason()
{
    lldb::StopInfoSP stop_info_sp (GetStopInfo ());
    if (stop_info_sp)
        return stop_info_sp->GetStopReason();
    return eStopReasonNone;
}

bool
Thread::StopInfoIsUpToDate() const
{
    ProcessSP process_sp (GetProcess());
    if (process_sp)
        return m_stop_info_stop_id == process_sp->GetStopID();
    else
        return true; // Process is no longer around so stop info is always up to date...
}

void
Thread::SetStopInfo (const lldb::StopInfoSP &stop_info_sp)
{
    m_stop_info_sp = stop_info_sp;
    if (m_stop_info_sp)
    {
        m_stop_info_sp->MakeStopInfoValid();
        // If we are overriding the ShouldReportStop, do that here:
        if (m_override_should_notify != eLazyBoolCalculate)
            m_stop_info_sp->OverrideShouldNotify (m_override_should_notify == eLazyBoolYes);
    }
    
    ProcessSP process_sp (GetProcess());
    if (process_sp)
        m_stop_info_stop_id = process_sp->GetStopID();
    else
        m_stop_info_stop_id = UINT32_MAX;
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
    if (log)
        log->Printf("%p: tid = 0x%" PRIx64 ": stop info = %s (stop_id = %u)",
                    static_cast<void*>(this), GetID(),
                    stop_info_sp ? stop_info_sp->GetDescription() : "<NULL>",
                    m_stop_info_stop_id);
}

void
Thread::SetShouldReportStop (Vote vote)
{
    if (vote == eVoteNoOpinion)
        return;
    else
    {
        m_override_should_notify = (vote == eVoteYes ? eLazyBoolYes : eLazyBoolNo);
        if (m_stop_info_sp)
            m_stop_info_sp->OverrideShouldNotify (m_override_should_notify == eLazyBoolYes);
    }
}

void
Thread::SetStopInfoToNothing()
{
    // Note, we can't just NULL out the private reason, or the native thread implementation will try to
    // go calculate it again.  For now, just set it to a Unix Signal with an invalid signal number.
    SetStopInfo (StopInfo::CreateStopReasonWithSignal (*this,  LLDB_INVALID_SIGNAL_NUMBER));
}

bool
Thread::ThreadStoppedForAReason (void)
{
    return (bool) GetPrivateStopInfo ();
}

bool
Thread::CheckpointThreadState (ThreadStateCheckpoint &saved_state)
{
    saved_state.register_backup_sp.reset();
    lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
    if (frame_sp)
    {
        lldb::RegisterCheckpointSP reg_checkpoint_sp(new RegisterCheckpoint(RegisterCheckpoint::Reason::eExpression));
        if (reg_checkpoint_sp)
        {
            lldb::RegisterContextSP reg_ctx_sp (frame_sp->GetRegisterContext());
            if (reg_ctx_sp && reg_ctx_sp->ReadAllRegisterValues (*reg_checkpoint_sp))
                saved_state.register_backup_sp = reg_checkpoint_sp;
        }
    }
    if (!saved_state.register_backup_sp)
        return false;

    saved_state.stop_info_sp = GetStopInfo();
    ProcessSP process_sp (GetProcess());
    if (process_sp)
        saved_state.orig_stop_id = process_sp->GetStopID();
    saved_state.current_inlined_depth = GetCurrentInlinedDepth();
    
    return true;
}

bool
Thread::RestoreRegisterStateFromCheckpoint (ThreadStateCheckpoint &saved_state)
{
    if (saved_state.register_backup_sp)
    {
        lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
        if (frame_sp)
        {
            lldb::RegisterContextSP reg_ctx_sp (frame_sp->GetRegisterContext());
            if (reg_ctx_sp)
            {
                bool ret = reg_ctx_sp->WriteAllRegisterValues (*saved_state.register_backup_sp);
                
                // Clear out all stack frames as our world just changed.
                ClearStackFrames();
                reg_ctx_sp->InvalidateIfNeeded(true);
                if (m_unwinder_ap.get())
                    m_unwinder_ap->Clear();
                return ret;
            }
        }
    }
    return false;
}

bool
Thread::RestoreThreadStateFromCheckpoint (ThreadStateCheckpoint &saved_state)
{
    if (saved_state.stop_info_sp)
        saved_state.stop_info_sp->MakeStopInfoValid();
    SetStopInfo(saved_state.stop_info_sp);
    GetStackFrameList()->SetCurrentInlinedDepth (saved_state.current_inlined_depth);
    return true;
}

StateType
Thread::GetState() const
{
    // If any other threads access this we will need a mutex for it
    Mutex::Locker locker(m_state_mutex);
    return m_state;
}

void
Thread::SetState(StateType state)
{
    Mutex::Locker locker(m_state_mutex);
    m_state = state;
}

void
Thread::WillStop()
{
    ThreadPlan *current_plan = GetCurrentPlan();

    // FIXME: I may decide to disallow threads with no plans.  In which
    // case this should go to an assert.

    if (!current_plan)
        return;

    current_plan->WillStop();
}

void
Thread::SetupForResume ()
{
    if (GetResumeState() != eStateSuspended)
    {
        // If we're at a breakpoint push the step-over breakpoint plan.  Do this before
        // telling the current plan it will resume, since we might change what the current
        // plan is.

        lldb::RegisterContextSP reg_ctx_sp (GetRegisterContext());
        if (reg_ctx_sp)
        {
            const addr_t thread_pc = reg_ctx_sp->GetPC();
            BreakpointSiteSP bp_site_sp = GetProcess()->GetBreakpointSiteList().FindByAddress(thread_pc);
            if (bp_site_sp)
            {
                // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the target may not require anything
                // special to step over a breakpoint.
                    
                ThreadPlan *cur_plan = GetCurrentPlan();

                bool push_step_over_bp_plan = false;
                if (cur_plan->GetKind() == ThreadPlan::eKindStepOverBreakpoint)
                {
                    ThreadPlanStepOverBreakpoint *bp_plan = (ThreadPlanStepOverBreakpoint *)cur_plan;
                    if (bp_plan->GetBreakpointLoadAddress() != thread_pc)
                        push_step_over_bp_plan = true;
                }
                else
                    push_step_over_bp_plan = true;

                if (push_step_over_bp_plan)
                {
                    ThreadPlanSP step_bp_plan_sp (new ThreadPlanStepOverBreakpoint (*this));
                    if (step_bp_plan_sp)
                    {
                        ;
                        step_bp_plan_sp->SetPrivate (true);

                        if (GetCurrentPlan()->RunState() != eStateStepping)
                        {
                            ThreadPlanStepOverBreakpoint *step_bp_plan
                                    = static_cast<ThreadPlanStepOverBreakpoint *>(step_bp_plan_sp.get());
                            step_bp_plan->SetAutoContinue(true);
                        }
                        QueueThreadPlan (step_bp_plan_sp, false);
                    }
                }
            }
        }
    }
}

bool
Thread::ShouldResume (StateType resume_state)
{
    // At this point clear the completed plan stack.
    m_completed_plan_stack.clear();
    m_discarded_plan_stack.clear();
    m_override_should_notify = eLazyBoolCalculate;

    StateType prev_resume_state = GetTemporaryResumeState();

    SetTemporaryResumeState(resume_state);
    
    lldb::ThreadSP backing_thread_sp (GetBackingThread ());
    if (backing_thread_sp)
        backing_thread_sp->SetTemporaryResumeState(resume_state);

    // Make sure m_stop_info_sp is valid.  Don't do this for threads we suspended in the previous run.
    if (prev_resume_state != eStateSuspended)
        GetPrivateStopInfo();
    
    // This is a little dubious, but we are trying to limit how often we actually fetch stop info from
    // the target, 'cause that slows down single stepping.  So assume that if we got to the point where
    // we're about to resume, and we haven't yet had to fetch the stop reason, then it doesn't need to know
    // about the fact that we are resuming...
    const uint32_t process_stop_id = GetProcess()->GetStopID();
    if (m_stop_info_stop_id == process_stop_id &&
        (m_stop_info_sp && m_stop_info_sp->IsValid()))
    {
        StopInfo *stop_info = GetPrivateStopInfo().get();
        if (stop_info)
            stop_info->WillResume (resume_state);
    }
    
    // Tell all the plans that we are about to resume in case they need to clear any state.
    // We distinguish between the plan on the top of the stack and the lower
    // plans in case a plan needs to do any special business before it runs.
    
    bool need_to_resume = false;
    ThreadPlan *plan_ptr = GetCurrentPlan();
    if (plan_ptr)
    {
        need_to_resume = plan_ptr->WillResume(resume_state, true);

        while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr)
        {
            plan_ptr->WillResume (resume_state, false);
        }
        
        // If the WillResume for the plan says we are faking a resume, then it will have set an appropriate stop info.
        // In that case, don't reset it here.
        
        if (need_to_resume && resume_state != eStateSuspended)
        {
            m_stop_info_sp.reset();
        }
    }

    if (need_to_resume)
    {
        ClearStackFrames();
        // Let Thread subclasses do any special work they need to prior to resuming
        WillResume (resume_state);
    }

    return need_to_resume;
}

void
Thread::DidResume ()
{
    SetResumeSignal (LLDB_INVALID_SIGNAL_NUMBER);
}

void
Thread::DidStop ()
{
    SetState (eStateStopped);
}

bool
Thread::ShouldStop (Event* event_ptr)
{
    ThreadPlan *current_plan = GetCurrentPlan();

    bool should_stop = true;

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));

    if (GetResumeState () == eStateSuspended)
    {
        if (log)
            log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", should_stop = 0 (ignore since thread was suspended)",
                         __FUNCTION__, GetID (), GetProtocolID());
        return false;
    }

    if (GetTemporaryResumeState () == eStateSuspended)
    {
        if (log)
            log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", should_stop = 0 (ignore since thread was suspended)",
                         __FUNCTION__, GetID (), GetProtocolID());
        return false;
    }

    // Based on the current thread plan and process stop info, check if this
    // thread caused the process to stop. NOTE: this must take place before
    // the plan is moved from the current plan stack to the completed plan
    // stack.
    if (!ThreadStoppedForAReason())
    {
        if (log)
            log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", pc = 0x%16.16" PRIx64 ", should_stop = 0 (ignore since no stop reason)",
                         __FUNCTION__, GetID (), GetProtocolID(),
                         GetRegisterContext() ? GetRegisterContext()->GetPC() : LLDB_INVALID_ADDRESS);
        return false;
    }

    if (log)
    {
        log->Printf ("Thread::%s(%p) for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", pc = 0x%16.16" PRIx64,
                     __FUNCTION__, static_cast<void*>(this), GetID (),
                     GetProtocolID (),
                     GetRegisterContext()
                        ? GetRegisterContext()->GetPC()
                        : LLDB_INVALID_ADDRESS);
        log->Printf ("^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^");
        StreamString s;
        s.IndentMore();
        DumpThreadPlans(&s);
        log->Printf ("Plan stack initial state:\n%s", s.GetData());
    }

    // The top most plan always gets to do the trace log...
    current_plan->DoTraceLog ();

    // First query the stop info's ShouldStopSynchronous.  This handles "synchronous" stop reasons, for example the breakpoint
    // command on internal breakpoints.  If a synchronous stop reason says we should not stop, then we don't have to
    // do any more work on this stop.
    StopInfoSP private_stop_info (GetPrivateStopInfo());
    if (private_stop_info && !private_stop_info->ShouldStopSynchronous(event_ptr))
    {
        if (log)
            log->Printf ("StopInfo::ShouldStop async callback says we should not stop, returning ShouldStop of false.");
        return false;
    }

    // If we've already been restarted, don't query the plans since the state they would examine is not current.
    if (Process::ProcessEventData::GetRestartedFromEvent(event_ptr))
        return false;

    // Before the plans see the state of the world, calculate the current inlined depth.
    GetStackFrameList()->CalculateCurrentInlinedDepth();

    // If the base plan doesn't understand why we stopped, then we have to find a plan that does.
    // If that plan is still working, then we don't need to do any more work.  If the plan that explains 
    // the stop is done, then we should pop all the plans below it, and pop it, and then let the plans above it decide
    // whether they still need to do more work.
    
    bool done_processing_current_plan = false;
    
    if (!current_plan->PlanExplainsStop(event_ptr))
    {
        if (current_plan->TracerExplainsStop())
        {
            done_processing_current_plan = true;
            should_stop = false;
        }
        else
        {
            // If the current plan doesn't explain the stop, then find one that
            // does and let it handle the situation.
            ThreadPlan *plan_ptr = current_plan;
            while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr)
            {
                if (plan_ptr->PlanExplainsStop(event_ptr))
                {
                    should_stop = plan_ptr->ShouldStop (event_ptr);

                    // plan_ptr explains the stop, next check whether plan_ptr is done, if so, then we should take it 
                    // and all the plans below it off the stack.

                    if (plan_ptr->MischiefManaged())
                    {
                        // We're going to pop the plans up to and including the plan that explains the stop.
                        ThreadPlan *prev_plan_ptr = GetPreviousPlan (plan_ptr);

                        do 
                        {
                            if (should_stop)
                                current_plan->WillStop();
                            PopPlan();
                        }
                        while ((current_plan = GetCurrentPlan()) != prev_plan_ptr);
                        // Now, if the responsible plan was not "Okay to discard" then we're done,
                        // otherwise we forward this to the next plan in the stack below.
                        done_processing_current_plan = (plan_ptr->IsMasterPlan() && !plan_ptr->OkayToDiscard());
                    }
                    else
                        done_processing_current_plan = true;

                    break;
                }
            }
        }
    }

    if (!done_processing_current_plan)
    {
        bool over_ride_stop = current_plan->ShouldAutoContinue(event_ptr);

        if (log)
            log->Printf("Plan %s explains stop, auto-continue %i.",
                        current_plan->GetName(), over_ride_stop);

        // We're starting from the base plan, so just let it decide;
        if (PlanIsBasePlan(current_plan))
        {
            should_stop = current_plan->ShouldStop (event_ptr);
            if (log)
                log->Printf("Base plan says should stop: %i.", should_stop);
        }
        else
        {
            // Otherwise, don't let the base plan override what the other plans say to do, since
            // presumably if there were other plans they would know what to do...
            while (1)
            {
                if (PlanIsBasePlan(current_plan))
                    break;

                should_stop = current_plan->ShouldStop(event_ptr);
                if (log)
                    log->Printf("Plan %s should stop: %d.",
                                current_plan->GetName(), should_stop);
                if (current_plan->MischiefManaged())
                {
                    if (should_stop)
                        current_plan->WillStop();

                    // If a Master Plan wants to stop, and wants to stick on the stack, we let it.
                    // Otherwise, see if the plan's parent wants to stop.

                    if (should_stop && current_plan->IsMasterPlan() && !current_plan->OkayToDiscard())
                    {
                        PopPlan();
                        break;
                    }
                    else
                    {
                        PopPlan();

                        current_plan = GetCurrentPlan();
                        if (current_plan == nullptr)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    break;
                }
            }
        }

        if (over_ride_stop)
            should_stop = false;
    }

    // One other potential problem is that we set up a master plan, then stop in before it is complete - for instance
    // by hitting a breakpoint during a step-over - then do some step/finish/etc operations that wind up
    // past the end point condition of the initial plan.  We don't want to strand the original plan on the stack,
    // This code clears stale plans off the stack.

    if (should_stop)
    {
        ThreadPlan *plan_ptr = GetCurrentPlan();
        while (!PlanIsBasePlan(plan_ptr))
        {
            bool stale = plan_ptr->IsPlanStale ();
            ThreadPlan *examined_plan = plan_ptr;
            plan_ptr = GetPreviousPlan (examined_plan);

            if (stale)
            {
                if (log)
                    log->Printf("Plan %s being discarded in cleanup, it says it is already done.",
                                examined_plan->GetName());
                DiscardThreadPlansUpToPlan(examined_plan);
            }
        }
    }

    if (log)
    {
        StreamString s;
        s.IndentMore();
        DumpThreadPlans(&s);
        log->Printf ("Plan stack final state:\n%s", s.GetData());
        log->Printf ("vvvvvvvv Thread::ShouldStop End (returning %i) vvvvvvvv", should_stop);
    }
    return should_stop;
}

Vote
Thread::ShouldReportStop (Event* event_ptr)
{
    StateType thread_state = GetResumeState ();
    StateType temp_thread_state = GetTemporaryResumeState();
    
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));

    if (thread_state == eStateSuspended || thread_state == eStateInvalid)
    {
        if (log)
            log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i (state was suspended or invalid)", GetID(), eVoteNoOpinion);
        return eVoteNoOpinion;
    }

    if (temp_thread_state == eStateSuspended || temp_thread_state == eStateInvalid)
    {
        if (log)
            log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i (temporary state was suspended or invalid)", GetID(), eVoteNoOpinion);
        return eVoteNoOpinion;
    }

    if (!ThreadStoppedForAReason())
    {
        if (log)
            log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i (thread didn't stop for a reason.)", GetID(), eVoteNoOpinion);
        return eVoteNoOpinion;
    }

    if (m_completed_plan_stack.size() > 0)
    {
        // Don't use GetCompletedPlan here, since that suppresses private plans.
        if (log)
            log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote  for complete stack's back plan", GetID());
        return m_completed_plan_stack.back()->ShouldReportStop (event_ptr);
    }
    else
    {
        Vote thread_vote = eVoteNoOpinion;
        ThreadPlan *plan_ptr = GetCurrentPlan();
        while (1)
        {
            if (plan_ptr->PlanExplainsStop(event_ptr))
            {
                thread_vote = plan_ptr->ShouldReportStop(event_ptr);
                break;
            }
            if (PlanIsBasePlan(plan_ptr))
                break;
            else
                plan_ptr = GetPreviousPlan(plan_ptr);
        }
        if (log)
            log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i for current plan", GetID(), thread_vote);

        return thread_vote;
    }
}

Vote
Thread::ShouldReportRun (Event* event_ptr)
{
    StateType thread_state = GetResumeState ();

    if (thread_state == eStateSuspended
            || thread_state == eStateInvalid)
    {
        return eVoteNoOpinion;
    }

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    if (m_completed_plan_stack.size() > 0)
    {
        // Don't use GetCompletedPlan here, since that suppresses private plans.
        if (log)
            log->Printf ("Current Plan for thread %d(%p) (0x%4.4" PRIx64 ", %s): %s being asked whether we should report run.",
                         GetIndexID(), static_cast<void*>(this), GetID(),
                         StateAsCString(GetTemporaryResumeState()),
                         m_completed_plan_stack.back()->GetName());

        return m_completed_plan_stack.back()->ShouldReportRun (event_ptr);
    }
    else
    {
        if (log)
            log->Printf ("Current Plan for thread %d(%p) (0x%4.4" PRIx64 ", %s): %s being asked whether we should report run.",
                         GetIndexID(), static_cast<void*>(this), GetID(),
                         StateAsCString(GetTemporaryResumeState()),
                         GetCurrentPlan()->GetName());

        return GetCurrentPlan()->ShouldReportRun (event_ptr);
     }
}

bool
Thread::MatchesSpec (const ThreadSpec *spec)
{
    return (spec == nullptr) ? true : spec->ThreadPassesBasicTests(*this);
}

void
Thread::PushPlan (ThreadPlanSP &thread_plan_sp)
{
    if (thread_plan_sp)
    {
        // If the thread plan doesn't already have a tracer, give it its parent's tracer:
        if (!thread_plan_sp->GetThreadPlanTracer())
            thread_plan_sp->SetThreadPlanTracer(m_plan_stack.back()->GetThreadPlanTracer());
        m_plan_stack.push_back (thread_plan_sp);

        thread_plan_sp->DidPush();

        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
        if (log)
        {
            StreamString s;
            thread_plan_sp->GetDescription (&s, lldb::eDescriptionLevelFull);
            log->Printf("Thread::PushPlan(0x%p): \"%s\", tid = 0x%4.4" PRIx64 ".",
                        static_cast<void*>(this), s.GetData(),
                        thread_plan_sp->GetThread().GetID());
        }
    }
}

void
Thread::PopPlan ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));

    if (m_plan_stack.size() <= 1)
        return;
    else
    {
        ThreadPlanSP &plan = m_plan_stack.back();
        if (log)
        {
            log->Printf("Popping plan: \"%s\", tid = 0x%4.4" PRIx64 ".", plan->GetName(), plan->GetThread().GetID());
        }
        m_completed_plan_stack.push_back (plan);
        plan->WillPop();
        m_plan_stack.pop_back();
    }
}

void
Thread::DiscardPlan ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    if (m_plan_stack.size() > 1)
    {
        ThreadPlanSP &plan = m_plan_stack.back();
        if (log)
            log->Printf("Discarding plan: \"%s\", tid = 0x%4.4" PRIx64 ".", plan->GetName(), plan->GetThread().GetID());

        m_discarded_plan_stack.push_back (plan);
        plan->WillPop();
        m_plan_stack.pop_back();
    }
}

ThreadPlan *
Thread::GetCurrentPlan ()
{
    // There will always be at least the base plan.  If somebody is mucking with a
    // thread with an empty plan stack, we should assert right away.
    return m_plan_stack.empty() ? nullptr : m_plan_stack.back().get();
}

ThreadPlanSP
Thread::GetCompletedPlan ()
{
    ThreadPlanSP empty_plan_sp;
    if (!m_completed_plan_stack.empty())
    {
        for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
        {
            ThreadPlanSP completed_plan_sp;
            completed_plan_sp = m_completed_plan_stack[i];
            if (!completed_plan_sp->GetPrivate ())
            return completed_plan_sp;
        }
    }
    return empty_plan_sp;
}

ValueObjectSP
Thread::GetReturnValueObject ()
{
    if (!m_completed_plan_stack.empty())
    {
        for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
        {
            ValueObjectSP return_valobj_sp;
            return_valobj_sp = m_completed_plan_stack[i]->GetReturnValueObject();
            if (return_valobj_sp)
                return return_valobj_sp;
        }
    }
    return ValueObjectSP();
}

ExpressionVariableSP
Thread::GetExpressionVariable ()
{
    if (!m_completed_plan_stack.empty())
    {
        for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
        {
            ExpressionVariableSP expression_variable_sp;
            expression_variable_sp = m_completed_plan_stack[i]->GetExpressionVariable();
            if (expression_variable_sp)
                return expression_variable_sp;
        }
    }
    return ExpressionVariableSP();
}

bool
Thread::IsThreadPlanDone (ThreadPlan *plan)
{
    if (!m_completed_plan_stack.empty())
    {
        for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
        {
            if (m_completed_plan_stack[i].get() == plan)
                return true;
        }
    }
    return false;
}

bool
Thread::WasThreadPlanDiscarded (ThreadPlan *plan)
{
    if (!m_discarded_plan_stack.empty())
    {
        for (int i = m_discarded_plan_stack.size() - 1; i >= 0; i--)
        {
            if (m_discarded_plan_stack[i].get() == plan)
                return true;
        }
    }
    return false;
}

ThreadPlan *
Thread::GetPreviousPlan (ThreadPlan *current_plan)
{
    if (current_plan == nullptr)
        return nullptr;

    int stack_size = m_completed_plan_stack.size();
    for (int i = stack_size - 1; i > 0; i--)
    {
        if (current_plan == m_completed_plan_stack[i].get())
            return m_completed_plan_stack[i-1].get();
    }

    if (stack_size > 0 && m_completed_plan_stack[0].get() == current_plan)
    {
        return GetCurrentPlan();
    }

    stack_size = m_plan_stack.size();
    for (int i = stack_size - 1; i > 0; i--)
    {
        if (current_plan == m_plan_stack[i].get())
            return m_plan_stack[i-1].get();
    }
    return nullptr;
}

void
Thread::QueueThreadPlan (ThreadPlanSP &thread_plan_sp, bool abort_other_plans)
{
    if (abort_other_plans)
       DiscardThreadPlans(true);

    PushPlan (thread_plan_sp);
}

void
Thread::EnableTracer (bool value, bool single_stepping)
{
    int stack_size = m_plan_stack.size();
    for (int i = 0; i < stack_size; i++)
    {
        if (m_plan_stack[i]->GetThreadPlanTracer())
        {
            m_plan_stack[i]->GetThreadPlanTracer()->EnableTracing(value);
            m_plan_stack[i]->GetThreadPlanTracer()->EnableSingleStep(single_stepping);
        }
    }
}

void
Thread::SetTracer (lldb::ThreadPlanTracerSP &tracer_sp)
{
    int stack_size = m_plan_stack.size();
    for (int i = 0; i < stack_size; i++)
        m_plan_stack[i]->SetThreadPlanTracer(tracer_sp);
}

bool
Thread::DiscardUserThreadPlansUpToIndex (uint32_t thread_index)
{
    // Count the user thread plans from the back end to get the number of the one we want
    // to discard:

    uint32_t idx = 0;
    ThreadPlan *up_to_plan_ptr = nullptr;

    for (ThreadPlanSP plan_sp : m_plan_stack)
    {
        if (plan_sp->GetPrivate())
            continue;
        if (idx == thread_index)
        {
            up_to_plan_ptr = plan_sp.get();
            break;
        }
        else
            idx++;
    }

    if (up_to_plan_ptr == nullptr)
        return false;

    DiscardThreadPlansUpToPlan(up_to_plan_ptr);
    return true;
}

void
Thread::DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp)
{
    DiscardThreadPlansUpToPlan (up_to_plan_sp.get());
}

void
Thread::DiscardThreadPlansUpToPlan (ThreadPlan *up_to_plan_ptr)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    if (log)
        log->Printf("Discarding thread plans for thread tid = 0x%4.4" PRIx64 ", up to %p",
                    GetID(), static_cast<void*>(up_to_plan_ptr));

    int stack_size = m_plan_stack.size();

    // If the input plan is nullptr, discard all plans.  Otherwise make sure this plan is in the
    // stack, and if so discard up to and including it.

    if (up_to_plan_ptr == nullptr)
    {
        for (int i = stack_size - 1; i > 0; i--)
            DiscardPlan();
    }
    else
    {
        bool found_it = false;
        for (int i = stack_size - 1; i > 0; i--)
        {
            if (m_plan_stack[i].get() == up_to_plan_ptr)
                found_it = true;
        }
        if (found_it)
        {
            bool last_one = false;
            for (int i = stack_size - 1; i > 0 && !last_one ; i--)
            {
                if (GetCurrentPlan() == up_to_plan_ptr)
                    last_one = true;
                DiscardPlan();
            }
        }
    }
}

void
Thread::DiscardThreadPlans(bool force)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    if (log)
    {
        log->Printf("Discarding thread plans for thread (tid = 0x%4.4" PRIx64 ", force %d)", GetID(), force);
    }

    if (force)
    {
        int stack_size = m_plan_stack.size();
        for (int i = stack_size - 1; i > 0; i--)
        {
            DiscardPlan();
        }
        return;
    }

    while (1)
    {
        int master_plan_idx;
        bool discard = true;

        // Find the first master plan, see if it wants discarding, and if yes discard up to it.
        for (master_plan_idx = m_plan_stack.size() - 1; master_plan_idx >= 0; master_plan_idx--)
        {
            if (m_plan_stack[master_plan_idx]->IsMasterPlan())
            {
                discard = m_plan_stack[master_plan_idx]->OkayToDiscard();
                break;
            }
        }

        if (discard)
        {
            // First pop all the dependent plans:
            for (int i = m_plan_stack.size() - 1; i > master_plan_idx; i--)
            {
                // FIXME: Do we need a finalize here, or is the rule that "PrepareForStop"
                // for the plan leaves it in a state that it is safe to pop the plan
                // with no more notice?
                DiscardPlan();
            }

            // Now discard the master plan itself.
            // The bottom-most plan never gets discarded.  "OkayToDiscard" for it means
            // discard it's dependent plans, but not it...
            if (master_plan_idx > 0)
            {
                DiscardPlan();
            }
        }
        else
        {
            // If the master plan doesn't want to get discarded, then we're done.
            break;
        }
    }
}

bool
Thread::PlanIsBasePlan (ThreadPlan *plan_ptr)
{
    if (plan_ptr->IsBasePlan())
        return true;
    else if (m_plan_stack.size() == 0)
        return false;
    else
       return m_plan_stack[0].get() == plan_ptr;
}

Error
Thread::UnwindInnermostExpression()
{
    Error error;
    int stack_size = m_plan_stack.size();
    
    // If the input plan is nullptr, discard all plans.  Otherwise make sure this plan is in the
    // stack, and if so discard up to and including it.
    
    for (int i = stack_size - 1; i > 0; i--)
    {
        if (m_plan_stack[i]->GetKind() == ThreadPlan::eKindCallFunction)
        {
            DiscardThreadPlansUpToPlan(m_plan_stack[i].get());
            return error;
        }
    }
    error.SetErrorString("No expressions currently active on this thread");
    return error;
}

ThreadPlanSP
Thread::QueueFundamentalPlan (bool abort_other_plans)
{
    ThreadPlanSP thread_plan_sp (new ThreadPlanBase(*this));
    QueueThreadPlan (thread_plan_sp, abort_other_plans);
    return thread_plan_sp;
}

ThreadPlanSP
Thread::QueueThreadPlanForStepSingleInstruction(bool step_over,
                                                bool abort_other_plans,
                                                bool stop_other_threads)
{
    ThreadPlanSP thread_plan_sp (new ThreadPlanStepInstruction (*this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
    QueueThreadPlan (thread_plan_sp, abort_other_plans);
    return thread_plan_sp;
}

ThreadPlanSP
Thread::QueueThreadPlanForStepOverRange(bool abort_other_plans,
                                        const AddressRange &range,
                                        const SymbolContext &addr_context,
                                        lldb::RunMode stop_other_threads,
                                        LazyBool step_out_avoids_code_withoug_debug_info)
{
    ThreadPlanSP thread_plan_sp;
    thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads, step_out_avoids_code_withoug_debug_info));
    
    QueueThreadPlan (thread_plan_sp, abort_other_plans);
    return thread_plan_sp;
}

// Call the QueueThreadPlanForStepOverRange method which takes an address range.
ThreadPlanSP
Thread::QueueThreadPlanForStepOverRange(bool abort_other_plans,
                                        const LineEntry &line_entry,
                                        const SymbolContext &addr_context,
                                        lldb::RunMode stop_other_threads,
                                        LazyBool step_out_avoids_code_withoug_debug_info)
{
    return QueueThreadPlanForStepOverRange (abort_other_plans, 
                                            line_entry.GetSameLineContiguousAddressRange(), 
                                            addr_context, 
                                            stop_other_threads, 
                                            step_out_avoids_code_withoug_debug_info);
}

ThreadPlanSP
Thread::QueueThreadPlanForStepInRange(bool abort_other_plans,
                                      const AddressRange &range,
                                      const SymbolContext &addr_context,
                                      const char *step_in_target,
                                      lldb::RunMode stop_other_threads,
                                      LazyBool step_in_avoids_code_without_debug_info,
                                      LazyBool step_out_avoids_code_without_debug_info)
{
    ThreadPlanSP thread_plan_sp (new ThreadPlanStepInRange (*this,
                                                             range,
                                                             addr_context,
                                                             stop_other_threads,
                                                             step_in_avoids_code_without_debug_info,
                                                             step_out_avoids_code_without_debug_info));
    ThreadPlanStepInRange *plan = static_cast<ThreadPlanStepInRange *>(thread_plan_sp.get());
    
    if (step_in_target)
        plan->SetStepInTarget(step_in_target);

    QueueThreadPlan (thread_plan_sp, abort_other_plans);
    return thread_plan_sp;
}

// Call the QueueThreadPlanForStepInRange method which takes an address range.
ThreadPlanSP
Thread::QueueThreadPlanForStepInRange(bool abort_other_plans,
                                      const LineEntry &line_entry,
                                      const SymbolContext &addr_context,
                                      const char *step_in_target,
                                      lldb::RunMode stop_other_threads,
                                      LazyBool step_in_avoids_code_without_debug_info,
                                      LazyBool step_out_avoids_code_without_debug_info)
{
    return QueueThreadPlanForStepInRange (abort_other_plans, 
                                          line_entry.GetSameLineContiguousAddressRange(), 
                                          addr_context, 
                                          step_in_target, 
                                          stop_other_threads, 
                                          step_in_avoids_code_without_debug_info, 
                                          step_out_avoids_code_without_debug_info);
}


ThreadPlanSP
Thread::QueueThreadPlanForStepOut(bool abort_other_plans,
                                  SymbolContext *addr_context,
                                  bool first_insn,
                                  bool stop_other_threads,
                                  Vote stop_vote,
                                  Vote run_vote,
                                  uint32_t frame_idx,
                                  LazyBool step_out_avoids_code_without_debug_info)
{
    ThreadPlanSP thread_plan_sp (new ThreadPlanStepOut (*this, 
                                                        addr_context, 
                                                        first_insn, 
                                                        stop_other_threads, 
                                                        stop_vote, 
                                                        run_vote, 
                                                        frame_idx,
                                                        step_out_avoids_code_without_debug_info));
    
    if (thread_plan_sp->ValidatePlan(nullptr))
    {
        QueueThreadPlan (thread_plan_sp, abort_other_plans);
        return thread_plan_sp;
    }
    else
    {
        return ThreadPlanSP();
    }
}

ThreadPlanSP
Thread::QueueThreadPlanForStepOutNoShouldStop(bool abort_other_plans,
                                              SymbolContext *addr_context,
                                              bool first_insn,
                                              bool stop_other_threads,
                                              Vote stop_vote,
                                              Vote run_vote,
                                              uint32_t frame_idx,
                                              bool continue_to_next_branch)
{
    ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut (*this,
                                                        addr_context, 
                                                        first_insn, 
                                                        stop_other_threads, 
                                                        stop_vote, 
                                                        run_vote, 
                                                        frame_idx,
                                                        eLazyBoolNo,
                                                        continue_to_next_branch));

    ThreadPlanStepOut *new_plan = static_cast<ThreadPlanStepOut *>(thread_plan_sp.get());
    new_plan->ClearShouldStopHereCallbacks();

    if (thread_plan_sp->ValidatePlan(nullptr))
    {
        QueueThreadPlan (thread_plan_sp, abort_other_plans);
        return thread_plan_sp;
    }
    else
    {
        return ThreadPlanSP();
    }
}

ThreadPlanSP
Thread::QueueThreadPlanForStepThrough (StackID &return_stack_id, bool abort_other_plans, bool stop_other_threads)
{
    ThreadPlanSP thread_plan_sp(new ThreadPlanStepThrough (*this, return_stack_id, stop_other_threads));
    if (!thread_plan_sp || !thread_plan_sp->ValidatePlan(nullptr))
        return ThreadPlanSP();

    QueueThreadPlan (thread_plan_sp, abort_other_plans);
    return thread_plan_sp;
}

ThreadPlanSP
Thread::QueueThreadPlanForRunToAddress (bool abort_other_plans,
                                        Address &target_addr,
                                        bool stop_other_threads)
{
    ThreadPlanSP thread_plan_sp (new ThreadPlanRunToAddress (*this, target_addr, stop_other_threads));
    QueueThreadPlan (thread_plan_sp, abort_other_plans);
    return thread_plan_sp;
}

ThreadPlanSP
Thread::QueueThreadPlanForStepUntil (bool abort_other_plans,
                                     lldb::addr_t *address_list,
                                     size_t num_addresses,
                                     bool stop_other_threads,
                                     uint32_t frame_idx)
{
    ThreadPlanSP thread_plan_sp (new ThreadPlanStepUntil (*this, address_list, num_addresses, stop_other_threads, frame_idx));
    QueueThreadPlan (thread_plan_sp, abort_other_plans);
    return thread_plan_sp;

}

lldb::ThreadPlanSP
Thread::QueueThreadPlanForStepScripted (bool abort_other_plans,
                                        const char *class_name,
                                        bool stop_other_threads)
{
    ThreadPlanSP thread_plan_sp (new ThreadPlanPython (*this, class_name));
    QueueThreadPlan (thread_plan_sp, abort_other_plans);
    // This seems a little funny, but I don't want to have to split up the constructor and the
    // DidPush in the scripted plan, that seems annoying.
    // That means the constructor has to be in DidPush.
    // So I have to validate the plan AFTER pushing it, and then take it off again...
    if (!thread_plan_sp->ValidatePlan(nullptr))
    {
        DiscardThreadPlansUpToPlan(thread_plan_sp);
        return ThreadPlanSP();
    }
    else
        return thread_plan_sp;
}

uint32_t
Thread::GetIndexID () const
{
    return m_index_id;
}

static void
PrintPlanElement (Stream *s, const ThreadPlanSP &plan, lldb::DescriptionLevel desc_level, int32_t elem_idx)
{
        s->IndentMore();
        s->Indent();
        s->Printf ("Element %d: ", elem_idx);
        plan->GetDescription (s, desc_level);
        s->EOL();
        s->IndentLess();
}

static void
PrintPlanStack (Stream *s, const std::vector<lldb::ThreadPlanSP> &plan_stack, lldb::DescriptionLevel desc_level, bool include_internal)
{
    int32_t print_idx = 0;
    for (ThreadPlanSP plan_sp : plan_stack)
    {
        if (include_internal || !plan_sp->GetPrivate())
        {
            PrintPlanElement (s, plan_sp, desc_level, print_idx++);
        }
    }
}

void
Thread::DumpThreadPlans (Stream *s,
                         lldb::DescriptionLevel desc_level,
                         bool include_internal,
                         bool ignore_boring_threads) const
{
    uint32_t stack_size;

    if (ignore_boring_threads)
    {
        uint32_t stack_size = m_plan_stack.size();
        uint32_t completed_stack_size = m_completed_plan_stack.size();
        uint32_t discarded_stack_size = m_discarded_plan_stack.size();
        if (stack_size == 1 && completed_stack_size == 0 && discarded_stack_size == 0)
        {
            s->Printf ("thread #%u: tid = 0x%4.4" PRIx64 "\n", GetIndexID(), GetID());
            s->IndentMore();
            s->Indent();
            s->Printf("No active thread plans\n");
            s->IndentLess();
            return;
        }
    }

    s->Indent();
    s->Printf ("thread #%u: tid = 0x%4.4" PRIx64 ":\n", GetIndexID(), GetID());
    s->IndentMore();
    s->Indent();
    s->Printf ("Active plan stack:\n");
    PrintPlanStack (s, m_plan_stack, desc_level, include_internal);

    stack_size = m_completed_plan_stack.size();
    if (stack_size > 0)
    {
        s->Indent();
        s->Printf ("Completed Plan Stack:\n");
        PrintPlanStack (s, m_completed_plan_stack, desc_level, include_internal);
    }

    stack_size = m_discarded_plan_stack.size();
    if (stack_size > 0)
    {
        s->Indent();
        s->Printf ("Discarded Plan Stack:\n");
        PrintPlanStack (s, m_discarded_plan_stack, desc_level, include_internal);
    }

    s->IndentLess();
}

TargetSP
Thread::CalculateTarget ()
{
    TargetSP target_sp;
    ProcessSP process_sp(GetProcess());
    if (process_sp)
        target_sp = process_sp->CalculateTarget();
    return target_sp;
}

ProcessSP
Thread::CalculateProcess ()
{
    return GetProcess();
}

ThreadSP
Thread::CalculateThread ()
{
    return shared_from_this();
}

StackFrameSP
Thread::CalculateStackFrame ()
{
    return StackFrameSP();
}

void
Thread::CalculateExecutionContext (ExecutionContext &exe_ctx)
{
    exe_ctx.SetContext (shared_from_this());
}

StackFrameListSP
Thread::GetStackFrameList ()
{
    StackFrameListSP frame_list_sp;
    Mutex::Locker locker(m_frame_mutex);
    if (m_curr_frames_sp)
    {
        frame_list_sp = m_curr_frames_sp;
    }
    else
    {
        frame_list_sp.reset(new StackFrameList (*this, m_prev_frames_sp, true));
        m_curr_frames_sp = frame_list_sp;
    }
    return frame_list_sp;
}

void
Thread::ClearStackFrames ()
{
    Mutex::Locker locker(m_frame_mutex);

    Unwind *unwinder = GetUnwinder ();
    if (unwinder)
        unwinder->Clear();

    // Only store away the old "reference" StackFrameList if we got all its frames:
    // FIXME: At some point we can try to splice in the frames we have fetched into
    // the new frame as we make it, but let's not try that now.
    if (m_curr_frames_sp && m_curr_frames_sp->GetAllFramesFetched())
        m_prev_frames_sp.swap (m_curr_frames_sp);
    m_curr_frames_sp.reset();

    m_extended_info.reset();
    m_extended_info_fetched = false;
}

lldb::StackFrameSP
Thread::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx)
{
    return GetStackFrameList()->GetFrameWithConcreteFrameIndex (unwind_idx);
}

Error
Thread::ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp, bool broadcast)
{
    StackFrameSP frame_sp = GetStackFrameAtIndex (frame_idx);
    Error return_error;
    
    if (!frame_sp)
    {
        return_error.SetErrorStringWithFormat("Could not find frame with index %d in thread 0x%" PRIx64 ".", frame_idx, GetID());
    }
    
    return ReturnFromFrame(frame_sp, return_value_sp, broadcast);
}

Error
Thread::ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp, bool broadcast)
{
    Error return_error;
    
    if (!frame_sp)
    {
        return_error.SetErrorString("Can't return to a null frame.");
        return return_error;
    }
    
    Thread *thread = frame_sp->GetThread().get();
    uint32_t older_frame_idx = frame_sp->GetFrameIndex() + 1;
    StackFrameSP older_frame_sp = thread->GetStackFrameAtIndex(older_frame_idx);
    if (!older_frame_sp)
    {
        return_error.SetErrorString("No older frame to return to.");
        return return_error;
    }
    
    if (return_value_sp)
    {    
        lldb::ABISP abi = thread->GetProcess()->GetABI();
        if (!abi)
        {
            return_error.SetErrorString("Could not find ABI to set return value.");
            return return_error;
        }
        SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextFunction);
        
        // FIXME: ValueObject::Cast doesn't currently work correctly, at least not for scalars.
        // Turn that back on when that works.
        if (/* DISABLES CODE */ (0) && sc.function != nullptr)
        {
            Type *function_type = sc.function->GetType();
            if (function_type)
            {
                CompilerType return_type = sc.function->GetCompilerType().GetFunctionReturnType();
                if (return_type)
                {
                    StreamString s;
                    return_type.DumpTypeDescription(&s);
                    ValueObjectSP cast_value_sp = return_value_sp->Cast(return_type);
                    if (cast_value_sp)
                    {
                        cast_value_sp->SetFormat(eFormatHex);
                        return_value_sp = cast_value_sp;
                    }
                }
            }
        }

        return_error = abi->SetReturnValueObject(older_frame_sp, return_value_sp);
        if (!return_error.Success())
            return return_error;
    }
    
    // Now write the return registers for the chosen frame:
    // Note, we can't use ReadAllRegisterValues->WriteAllRegisterValues, since the read & write
    // cook their data
    
    StackFrameSP youngest_frame_sp = thread->GetStackFrameAtIndex(0);
    if (youngest_frame_sp)
    {
        lldb::RegisterContextSP reg_ctx_sp (youngest_frame_sp->GetRegisterContext());
        if (reg_ctx_sp)
        {
            bool copy_success = reg_ctx_sp->CopyFromRegisterContext(older_frame_sp->GetRegisterContext());
            if (copy_success)
            {
                thread->DiscardThreadPlans(true);
                thread->ClearStackFrames();
                if (broadcast && EventTypeHasListeners(eBroadcastBitStackChanged))
                    BroadcastEvent(eBroadcastBitStackChanged, new ThreadEventData (this->shared_from_this()));
            }
            else
            {
                return_error.SetErrorString("Could not reset register values.");
            }
        }
        else
        {
            return_error.SetErrorString("Frame has no register context.");
        }
    }
    else
    {
        return_error.SetErrorString("Returned past top frame.");
    }
    return return_error;
}

static void DumpAddressList (Stream &s, const std::vector<Address> &list, ExecutionContextScope *exe_scope)
{
    for (size_t n=0;n<list.size();n++)
    {
        s << "\t";
        list[n].Dump (&s, exe_scope, Address::DumpStyleResolvedDescription, Address::DumpStyleSectionNameOffset);
        s << "\n";
    }
}

Error
Thread::JumpToLine (const FileSpec &file, uint32_t line, bool can_leave_function, std::string *warnings)
{
    ExecutionContext exe_ctx (GetStackFrameAtIndex(0));
    Target *target = exe_ctx.GetTargetPtr();
    TargetSP target_sp = exe_ctx.GetTargetSP();
    RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
    StackFrame *frame = exe_ctx.GetFramePtr();
    const SymbolContext &sc = frame->GetSymbolContext(eSymbolContextFunction);

    // Find candidate locations.
    std::vector<Address> candidates, within_function, outside_function;
    target->GetImages().FindAddressesForLine (target_sp, file, line, sc.function, within_function, outside_function);

    // If possible, we try and stay within the current function.
    // Within a function, we accept multiple locations (optimized code may do this,
    // there's no solution here so we do the best we can).
    // However if we're trying to leave the function, we don't know how to pick the
    // right location, so if there's more than one then we bail.
    if (!within_function.empty())
        candidates = within_function;
    else if (outside_function.size() == 1 && can_leave_function)
        candidates = outside_function;

    // Check if we got anything.
    if (candidates.empty())
    {
        if (outside_function.empty())
        {
            return Error("Cannot locate an address for %s:%i.",
                         file.GetFilename().AsCString(), line);
        }
        else if (outside_function.size() == 1)
        {
            return Error("%s:%i is outside the current function.",
                         file.GetFilename().AsCString(), line);
        }
        else
        {
            StreamString sstr;
            DumpAddressList(sstr, outside_function, target);
            return Error("%s:%i has multiple candidate locations:\n%s",
                         file.GetFilename().AsCString(), line, sstr.GetString().c_str());
        }
    }

    // Accept the first location, warn about any others.
    Address dest = candidates[0];
    if (warnings && candidates.size() > 1)
    {
        StreamString sstr;
        sstr.Printf("%s:%i appears multiple times in this function, selecting the first location:\n",
                     file.GetFilename().AsCString(), line);
        DumpAddressList(sstr, candidates, target);
        *warnings = sstr.GetString();
    }

    if (!reg_ctx->SetPC (dest))
        return Error("Cannot change PC to target address.");

    return Error();
}

void
Thread::DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx)
{
    ExecutionContext exe_ctx (shared_from_this());
    Process *process = exe_ctx.GetProcessPtr();
    if (process == nullptr)
        return;

    StackFrameSP frame_sp;
    SymbolContext frame_sc;
    if (frame_idx != LLDB_INVALID_FRAME_ID)
    {
        frame_sp = GetStackFrameAtIndex (frame_idx);
        if (frame_sp)
        {
            exe_ctx.SetFrameSP(frame_sp);
            frame_sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
        }
    }

    const FormatEntity::Entry *thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat();
    assert (thread_format);
    
    FormatEntity::Format(*thread_format,
                         strm,
                         frame_sp ? &frame_sc : nullptr,
                         &exe_ctx,
                         nullptr,
                         nullptr,
                         false,
                         false);
}

void
Thread::SettingsInitialize ()
{
}

void
Thread::SettingsTerminate ()
{
}

lldb::addr_t
Thread::GetThreadPointer ()
{
    return LLDB_INVALID_ADDRESS;
}

addr_t
Thread::GetThreadLocalData (const ModuleSP module)
{
    // The default implementation is to ask the dynamic loader for it.
    // This can be overridden for specific platforms.
    DynamicLoader *loader = GetProcess()->GetDynamicLoader();
    if (loader)
        return loader->GetThreadLocalData (module, shared_from_this());
    else
        return LLDB_INVALID_ADDRESS;
}

bool
Thread::SafeToCallFunctions ()
{
    Process *process = GetProcess().get();
    if (process)
    {
        SystemRuntime *runtime = process->GetSystemRuntime ();
        if (runtime)
        {
            return runtime->SafeToCallFunctionsOnThisThread (shared_from_this());
        }
    }
    return true;
}

lldb::StackFrameSP
Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
{
    return GetStackFrameList()->GetStackFrameSPForStackFramePtr (stack_frame_ptr);
}

const char *
Thread::StopReasonAsCString (lldb::StopReason reason)
{
    switch (reason)
    {
    case eStopReasonInvalid:       return "invalid";
    case eStopReasonNone:          return "none";
    case eStopReasonTrace:         return "trace";
    case eStopReasonBreakpoint:    return "breakpoint";
    case eStopReasonWatchpoint:    return "watchpoint";
    case eStopReasonSignal:        return "signal";
    case eStopReasonException:     return "exception";
    case eStopReasonExec:          return "exec";
    case eStopReasonPlanComplete:  return "plan complete";
    case eStopReasonThreadExiting: return "thread exiting";
    case eStopReasonInstrumentation: return "instrumentation break";
    }

    static char unknown_state_string[64];
    snprintf(unknown_state_string, sizeof (unknown_state_string), "StopReason = %i", reason);
    return unknown_state_string;
}

const char *
Thread::RunModeAsCString (lldb::RunMode mode)
{
    switch (mode)
    {
    case eOnlyThisThread:     return "only this thread";
    case eAllThreads:         return "all threads";
    case eOnlyDuringStepping: return "only during stepping";
    }

    static char unknown_state_string[64];
    snprintf(unknown_state_string, sizeof (unknown_state_string), "RunMode = %i", mode);
    return unknown_state_string;
}

size_t
Thread::GetStatus (Stream &strm, uint32_t start_frame, uint32_t num_frames, uint32_t num_frames_with_source)
{
    ExecutionContext exe_ctx (shared_from_this());
    Target *target = exe_ctx.GetTargetPtr();
    Process *process = exe_ctx.GetProcessPtr();
    size_t num_frames_shown = 0;
    strm.Indent();
    bool is_selected = false;
    if (process)
    {
        if (process->GetThreadList().GetSelectedThread().get() == this)
            is_selected = true;
    }
    strm.Printf("%c ", is_selected ? '*' : ' ');
    if (target && target->GetDebugger().GetUseExternalEditor())
    {
        StackFrameSP frame_sp = GetStackFrameAtIndex(start_frame);
        if (frame_sp)
        {
            SymbolContext frame_sc(frame_sp->GetSymbolContext (eSymbolContextLineEntry));
            if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.file)
            {
                Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
            }
        }
    }
    
    DumpUsingSettingsFormat (strm, start_frame);
    
    if (num_frames > 0)
    {
        strm.IndentMore();
        
        const bool show_frame_info = true;
        
        const char *selected_frame_marker = nullptr;
        if (num_frames == 1 || (GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID()))
            strm.IndentMore ();
        else
            selected_frame_marker = "* ";

        num_frames_shown = GetStackFrameList ()->GetStatus (strm,
                                                            start_frame, 
                                                            num_frames, 
                                                            show_frame_info, 
                                                            num_frames_with_source,
                                                            selected_frame_marker);
        if (num_frames == 1)
            strm.IndentLess();
        strm.IndentLess();
    }
    return num_frames_shown;
}

bool
Thread::GetDescription (Stream &strm, lldb::DescriptionLevel level, bool print_json_thread, bool print_json_stopinfo)
{
    DumpUsingSettingsFormat (strm, 0);
    strm.Printf("\n");

    StructuredData::ObjectSP thread_info = GetExtendedInfo();

    if (print_json_thread || print_json_stopinfo)
    {
        if (thread_info && print_json_thread)
        {
            thread_info->Dump (strm);
            strm.Printf("\n");
        }

        if (print_json_stopinfo && m_stop_info_sp)
        {
            StructuredData::ObjectSP stop_info = m_stop_info_sp->GetExtendedInfo();
            if (stop_info)
            {
                stop_info->Dump (strm);
                strm.Printf("\n");
            }
        }

        return true;
    }

    if (thread_info)
    {
        StructuredData::ObjectSP activity = thread_info->GetObjectForDotSeparatedPath("activity");
        StructuredData::ObjectSP breadcrumb = thread_info->GetObjectForDotSeparatedPath("breadcrumb");
        StructuredData::ObjectSP messages = thread_info->GetObjectForDotSeparatedPath("trace_messages");

        bool printed_activity = false;
        if (activity && activity->GetType() == StructuredData::Type::eTypeDictionary)
        {
            StructuredData::Dictionary *activity_dict = activity->GetAsDictionary();
            StructuredData::ObjectSP id = activity_dict->GetValueForKey("id");
            StructuredData::ObjectSP name = activity_dict->GetValueForKey("name");
            if (name && name->GetType() == StructuredData::Type::eTypeString
                && id && id->GetType() == StructuredData::Type::eTypeInteger)
            {
                strm.Printf("  Activity '%s', 0x%" PRIx64 "\n", name->GetAsString()->GetValue().c_str(), id->GetAsInteger()->GetValue());
            }
            printed_activity = true;
        }
        bool printed_breadcrumb = false;
        if (breadcrumb && breadcrumb->GetType() == StructuredData::Type::eTypeDictionary)
        {
            if (printed_activity)
                strm.Printf ("\n");
            StructuredData::Dictionary *breadcrumb_dict = breadcrumb->GetAsDictionary();
            StructuredData::ObjectSP breadcrumb_text = breadcrumb_dict->GetValueForKey ("name");
            if (breadcrumb_text && breadcrumb_text->GetType() == StructuredData::Type::eTypeString)
            {
                strm.Printf ("  Current Breadcrumb: %s\n", breadcrumb_text->GetAsString()->GetValue().c_str());
            }
            printed_breadcrumb = true;
        }
        if (messages && messages->GetType() == StructuredData::Type::eTypeArray)
        {
            if (printed_breadcrumb)
                strm.Printf("\n");
            StructuredData::Array *messages_array = messages->GetAsArray();
            const size_t msg_count = messages_array->GetSize();
            if (msg_count > 0)
            {
                strm.Printf ("  %zu trace messages:\n", msg_count);
                for (size_t i = 0; i < msg_count; i++)
                {
                    StructuredData::ObjectSP message = messages_array->GetItemAtIndex(i);
                    if (message && message->GetType() == StructuredData::Type::eTypeDictionary)
                    {
                        StructuredData::Dictionary *message_dict = message->GetAsDictionary();
                        StructuredData::ObjectSP message_text = message_dict->GetValueForKey ("message");
                        if (message_text && message_text->GetType() == StructuredData::Type::eTypeString)
                        {
                            strm.Printf ("    %s\n", message_text->GetAsString()->GetValue().c_str());
                        }
                    }
                }
            }
        }
    }

    return true;
}

size_t
Thread::GetStackFrameStatus (Stream& strm,
                             uint32_t first_frame,
                             uint32_t num_frames,
                             bool show_frame_info,
                             uint32_t num_frames_with_source)
{
    return GetStackFrameList()->GetStatus (strm,
                                           first_frame,
                                           num_frames,
                                           show_frame_info,
                                           num_frames_with_source);
}

Unwind *
Thread::GetUnwinder ()
{
    if (!m_unwinder_ap)
    {
        const ArchSpec target_arch (CalculateTarget()->GetArchitecture ());
        const llvm::Triple::ArchType machine = target_arch.GetMachine();
        switch (machine)
        {
            case llvm::Triple::x86_64:
            case llvm::Triple::x86:
            case llvm::Triple::arm:
            case llvm::Triple::aarch64:
            case llvm::Triple::thumb:
            case llvm::Triple::mips:
            case llvm::Triple::mipsel:
            case llvm::Triple::mips64:
            case llvm::Triple::mips64el:
            case llvm::Triple::ppc:
            case llvm::Triple::ppc64:
            case llvm::Triple::hexagon:
                m_unwinder_ap.reset (new UnwindLLDB (*this));
                break;
                
            default:
                if (target_arch.GetTriple().getVendor() == llvm::Triple::Apple)
                    m_unwinder_ap.reset (new UnwindMacOSXFrameBackchain (*this));
                break;
        }
    }
    return m_unwinder_ap.get();
}

void
Thread::Flush ()
{
    ClearStackFrames ();
    m_reg_context_sp.reset();
}

bool
Thread::IsStillAtLastBreakpointHit ()
{
    // If we are currently stopped at a breakpoint, always return that stopinfo and don't reset it.
    // This allows threads to maintain their breakpoint stopinfo, such as when thread-stepping in
    // multithreaded programs.
    if (m_stop_info_sp) {
        StopReason stop_reason = m_stop_info_sp->GetStopReason();
        if (stop_reason == lldb::eStopReasonBreakpoint) {
            uint64_t value = m_stop_info_sp->GetValue();
            lldb::RegisterContextSP reg_ctx_sp (GetRegisterContext());
            if (reg_ctx_sp)
            {
                lldb::addr_t pc = reg_ctx_sp->GetPC();
                BreakpointSiteSP bp_site_sp = GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
                if (bp_site_sp &&
                    static_cast<break_id_t>(value) == bp_site_sp->GetID())
                    return true;
            }
        }
    }
    return false;
}

Error
Thread::StepIn (bool source_step,
                LazyBool step_in_avoids_code_without_debug_info,
                LazyBool step_out_avoids_code_without_debug_info)

{
    Error error;
    Process *process = GetProcess().get();
    if (StateIsStoppedState (process->GetState(), true))
    {
        StackFrameSP frame_sp = GetStackFrameAtIndex (0);
        ThreadPlanSP new_plan_sp;
        const lldb::RunMode run_mode = eOnlyThisThread;
        const bool abort_other_plans = false;
    
        if (source_step && frame_sp && frame_sp->HasDebugInformation ())
        {
            SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
            new_plan_sp = QueueThreadPlanForStepInRange(abort_other_plans,
                                                        sc.line_entry,
                                                        sc,
                                                        nullptr,
                                                        run_mode,
                                                        step_in_avoids_code_without_debug_info,
                                                        step_out_avoids_code_without_debug_info);
        }
        else
        {
            new_plan_sp = QueueThreadPlanForStepSingleInstruction (false,
                                                                   abort_other_plans,
                                                                   run_mode);
        }
        
        new_plan_sp->SetIsMasterPlan(true);
        new_plan_sp->SetOkayToDiscard(false);
        
        // Why do we need to set the current thread by ID here???
        process->GetThreadList().SetSelectedThreadByID (GetID());
        error = process->Resume();
    }
    else
    {
        error.SetErrorString("process not stopped");
    }
    return error;
}

Error
Thread::StepOver (bool source_step,
                LazyBool step_out_avoids_code_without_debug_info)
{
    Error error;
    Process *process = GetProcess().get();
    if (StateIsStoppedState (process->GetState(), true))
    {
        StackFrameSP frame_sp = GetStackFrameAtIndex (0);
        ThreadPlanSP new_plan_sp;
        
        const lldb::RunMode run_mode = eOnlyThisThread;
        const bool abort_other_plans = false;
        
        if (source_step && frame_sp && frame_sp->HasDebugInformation ())
        {
            SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
            new_plan_sp = QueueThreadPlanForStepOverRange (abort_other_plans,
                                                           sc.line_entry,
                                                           sc,
                                                           run_mode,
                                                           step_out_avoids_code_without_debug_info);
        }
        else
        {
            new_plan_sp = QueueThreadPlanForStepSingleInstruction (true,
                                                                   abort_other_plans,
                                                                   run_mode);
        }
        
        new_plan_sp->SetIsMasterPlan(true);
        new_plan_sp->SetOkayToDiscard(false);
        
        // Why do we need to set the current thread by ID here???
        process->GetThreadList().SetSelectedThreadByID (GetID());
        error = process->Resume();
    }
    else
    {
        error.SetErrorString("process not stopped");
    }
    return error;
}

Error
Thread::StepOut ()
{
    Error error;
    Process *process = GetProcess().get();
    if (StateIsStoppedState (process->GetState(), true))
    {
        const bool first_instruction = false;
        const bool stop_other_threads = false;
        const bool abort_other_plans = false;

        ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut(abort_other_plans,
                                                           nullptr,
                                                           first_instruction,
                                                           stop_other_threads,
                                                           eVoteYes,
                                                           eVoteNoOpinion,
                                                           0));
        
        new_plan_sp->SetIsMasterPlan(true);
        new_plan_sp->SetOkayToDiscard(false);
        
        // Why do we need to set the current thread by ID here???
        process->GetThreadList().SetSelectedThreadByID (GetID());
        error = process->Resume();
    }
    else
    {
        error.SetErrorString("process not stopped");
    }
    return error;
}
