//===-- 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
#include <mutex>
// 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()
{
    // NOTE: intentional leak so we don't crash if global destructor chain gets
    // called as other threads still use the result of this function
    static ThreadPropertiesSP *g_settings_sp_ptr = nullptr;
    static std::once_flag g_once_flag;
    std::call_once(g_once_flag,  []() {
        g_settings_sp_ptr = new ThreadPropertiesSP(new ThreadProperties (true));
    });
    return *g_settings_sp_ptr;
}

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().GetBroadcasterManager(), 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;
}
