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

#include "lldb/lldb-python.h"

#include "lldb/lldb-private-log.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.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, NULL, NULL, "If true, step-in will not stop in functions with no debug information." },
    { "step-out-avoid-nodebug", OptionValue::eTypeBoolean, true, false, NULL, NULL, "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 , REG_EXTENDED, "^std::", NULL, "A regular expression defining functions step-in won't stop in." },
    { "step-avoid-libraries",  OptionValue::eTypeFileSpecList  , true , REG_EXTENDED, NULL, NULL, "A list of libraries that source stepping won't stop in." },
    { "trace-thread",       OptionValue::eTypeBoolean, false, false, NULL, NULL, "If true, this thread will single-step and log execution." },
    {  NULL               , OptionValue::eTypeInvalid, false, 0    , NULL, NULL, NULL  }
};

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())
    {
    }
    
    virtual const Property *
    GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
    {
        // 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()
{
}

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

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

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

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

bool
ThreadProperties::GetStepOutAvoidsNoDebug() const
{
    const uint32_t idx = ePropertyStepOutAvoidsNoDebug;
    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, 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 ()
{
}

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 NULL;
}

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));
}

uint32_t
Thread::SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast)
{
    uint32_t ret_value = GetStackFrameList()->SetSelectedFrame(frame);
    if (broadcast)
        BroadcastSelectedFrameChange(frame->GetStackID());
    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());
        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;
            return frame_sp->GetStatus (output_stream, show_frame_info, show_source);
        }
        return false;
    }
    else
        return false;
}


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() == false)
                    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;
}



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.

//      StopReason stop_reason = lldb::eStopReasonInvalid;
//      StopInfoSP stop_info_sp = GetStopInfo();
//      if (stop_info_sp.get())
//          stop_reason = stop_info_sp->GetStopReason();
//      if (stop_reason == lldb::eStopReasonBreakpoint)
        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;

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

    // Make sure m_stop_info_sp is valid
    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)) != NULL)
        {
            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() == false)
    {
        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) == false)
    {
        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)) != NULL)
            {
                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.
                        if (plan_ptr->IsMasterPlan() && !plan_ptr->OkayToDiscard())
                            done_processing_current_plan = true;
                        else
                            done_processing_current_plan = false;
                    }
                    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 == NULL)
                        {
                            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)
{
    if (spec == NULL)
        return true;
        
    return 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.
    if (m_plan_stack.empty())
        return NULL;
    return 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();
}

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

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 == NULL)
        return NULL;

    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)
    {
        if (m_plan_stack.size() > 0)
            return m_plan_stack.back().get();
        else
            return NULL;
    }

    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 NULL;
}

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

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 NULL, 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;
}

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;
}


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_withoug_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_withoug_debug_info));
    
    if (thread_plan_sp->ValidatePlan(NULL))
    {
        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
)
{
    ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut (*this,
                                                        addr_context, 
                                                        first_insn, 
                                                        stop_other_threads, 
                                                        stop_vote, 
                                                        run_vote, 
                                                        frame_idx,
                                                        eLazyBoolNo));

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

    if (thread_plan_sp->ValidatePlan(NULL))
    {
        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 (NULL))
        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 != NULL)
        {
            Type *function_type = sc.function->GetType();
            if (function_type)
            {
                ClangASTType return_type = sc.function->GetClangType().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 == NULL)
        return;

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

    const char *thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat();
    assert (thread_format);
    Debugger::FormatPrompt (thread_format, 
                            frame_sp ? &frame_sc : NULL,
                            &exe_ctx, 
                            NULL,
                            strm);
}

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 = NULL;
        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();
    StructuredData::ObjectSP stop_info = m_stop_info_sp->GetExtendedInfo();
    
    if (print_json_thread || print_json_stopinfo)
    {
        if (thread_info && print_json_thread)
        {
            thread_info->Dump (strm);
            strm.Printf("\n");
        }
        
        if (stop_info && print_json_stopinfo)
        {
            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.get() == NULL)
    {
        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::mips64:
            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.range,
                                                         sc,
                                                         NULL,
                                                         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.range,
                                                           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,
                                                            NULL,
                                                            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;
}
