//===-- 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/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/FormatEntity.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/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/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 , 0, "^std::", NULL, "A regular expression defining functions step-in won't stop in." },
    { "step-avoid-libraries",  OptionValue::eTypeFileSpecList  , true , 0, 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.

        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_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 : NULL,
                         &exe_ctx,
                         NULL,
                         NULL,
                         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 = 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();

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