//===-- SBThread.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/API/SBThread.h"

#include "lldb/API/SBSymbolContext.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBStream.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Queue.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Target/ThreadPlanStepRange.h"
#include "lldb/Target/ThreadPlanStepInRange.h"

#include "lldb/API/SBAddress.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBThreadCollection.h"
#include "lldb/API/SBThreadPlan.h"
#include "lldb/API/SBValue.h"

using namespace lldb;
using namespace lldb_private;

const char *
SBThread::GetBroadcasterClassName ()
{
    return Thread::GetStaticBroadcasterClass().AsCString();
}

//----------------------------------------------------------------------
// Constructors
//----------------------------------------------------------------------
SBThread::SBThread () :
    m_opaque_sp (new ExecutionContextRef())
{
}

SBThread::SBThread (const ThreadSP& lldb_object_sp) :
    m_opaque_sp (new ExecutionContextRef(lldb_object_sp))
{
}

SBThread::SBThread (const SBThread &rhs) :
    m_opaque_sp (new ExecutionContextRef(*rhs.m_opaque_sp))
{
    
}

//----------------------------------------------------------------------
// Assignment operator
//----------------------------------------------------------------------

const lldb::SBThread &
SBThread::operator = (const SBThread &rhs)
{
    if (this != &rhs)
        *m_opaque_sp = *rhs.m_opaque_sp;
    return *this;
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
SBThread::~SBThread()
{
}

lldb::SBQueue
SBThread::GetQueue () const
{
    SBQueue sb_queue;
    QueueSP queue_sp;
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            queue_sp = exe_ctx.GetThreadPtr()->GetQueue();
            if (queue_sp)
            {
                sb_queue.SetQueue (queue_sp);
            }
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::GetQueue() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }

    if (log)
        log->Printf ("SBThread(%p)::GetQueue () => SBQueue(%p)",
                     static_cast<void*>(exe_ctx.GetThreadPtr()), static_cast<void*>(queue_sp.get()));

    return sb_queue;
}


bool
SBThread::IsValid() const
{
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    Target *target = exe_ctx.GetTargetPtr();
    Process *process = exe_ctx.GetProcessPtr();
    if (target && process)
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&process->GetRunLock()))
        return m_opaque_sp->GetThreadSP().get() != NULL;
    }
    // Without a valid target & process, this thread can't be valid.
    return false;
}

void
SBThread::Clear ()
{
    m_opaque_sp->Clear();
}


StopReason
SBThread::GetStopReason()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    StopReason reason = eStopReasonInvalid;
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            return exe_ctx.GetThreadPtr()->GetStopReason();
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::GetStopReason() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }

    if (log)
        log->Printf ("SBThread(%p)::GetStopReason () => %s",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     Thread::StopReasonAsCString (reason));

    return reason;
}

size_t
SBThread::GetStopReasonDataCount ()
{
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo ();
            if (stop_info_sp)
            {
                StopReason reason = stop_info_sp->GetStopReason();
                switch (reason)
                {
                case eStopReasonInvalid:
                case eStopReasonNone:
                case eStopReasonTrace:
                case eStopReasonExec:
                case eStopReasonPlanComplete:
                case eStopReasonThreadExiting:
                case eStopReasonInstrumentation:
                    // There is no data for these stop reasons.
                    return 0;

                case eStopReasonBreakpoint:
                    {
                        break_id_t site_id = stop_info_sp->GetValue();
                        lldb::BreakpointSiteSP bp_site_sp (exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID (site_id));
                        if (bp_site_sp)
                            return bp_site_sp->GetNumberOfOwners () * 2;
                        else
                            return 0; // Breakpoint must have cleared itself...
                    }
                    break;

                case eStopReasonWatchpoint:
                    return 1;

                case eStopReasonSignal:
                    return 1;

                case eStopReasonException:
                    return 1;
                }
            }
        }
        else
        {
            Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
            if (log)
                log->Printf ("SBThread(%p)::GetStopReasonDataCount() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }
    return 0;
}

uint64_t
SBThread::GetStopReasonDataAtIndex (uint32_t idx)
{
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            Thread *thread = exe_ctx.GetThreadPtr();
            StopInfoSP stop_info_sp = thread->GetStopInfo ();
            if (stop_info_sp)
            {
                StopReason reason = stop_info_sp->GetStopReason();
                switch (reason)
                {
                case eStopReasonInvalid:
                case eStopReasonNone:
                case eStopReasonTrace:
                case eStopReasonExec:
                case eStopReasonPlanComplete:
                case eStopReasonThreadExiting:
                case eStopReasonInstrumentation:
                    // There is no data for these stop reasons.
                    return 0;

                case eStopReasonBreakpoint:
                    {
                        break_id_t site_id = stop_info_sp->GetValue();
                        lldb::BreakpointSiteSP bp_site_sp (exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID (site_id));
                        if (bp_site_sp)
                        {
                            uint32_t bp_index = idx / 2;
                            BreakpointLocationSP bp_loc_sp (bp_site_sp->GetOwnerAtIndex (bp_index));
                            if (bp_loc_sp)
                            {
                                if (idx & 1)
                                {
                                    // Odd idx, return the breakpoint location ID
                                    return bp_loc_sp->GetID();
                                }
                                else
                                {
                                    // Even idx, return the breakpoint ID
                                    return bp_loc_sp->GetBreakpoint().GetID();
                                }
                            }
                        }
                        return LLDB_INVALID_BREAK_ID;
                    }
                    break;

                case eStopReasonWatchpoint:
                    return stop_info_sp->GetValue();

                case eStopReasonSignal:
                    return stop_info_sp->GetValue();

                case eStopReasonException:
                    return stop_info_sp->GetValue();
                }
            }
        }
        else
        {
            Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
            if (log)
                log->Printf ("SBThread(%p)::GetStopReasonDataAtIndex() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }
    return 0;
}

bool
SBThread::GetStopReasonExtendedInfoAsJSON (lldb::SBStream &stream)
{
    Stream &strm = stream.ref();
    
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (! exe_ctx.HasThreadScope())
        return false;

    
    StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
    StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
    if (! info)
        return false;

    info->Dump(strm);
    
    return true;
}

SBThreadCollection
SBThread::GetStopReasonExtendedBacktraces (InstrumentationRuntimeType type)
{
    ThreadCollectionSP threads;
    threads.reset(new ThreadCollection());
    
    // We currently only support ThreadSanitizer.
    if (type != eInstrumentationRuntimeTypeThreadSanitizer)
        return threads;
    
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (! exe_ctx.HasThreadScope())
        return threads;
    
    ProcessSP process_sp = exe_ctx.GetProcessSP();
    
    StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
    StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
    if (! info)
        return threads;
    
    return process_sp->GetInstrumentationRuntime(type)->GetBacktracesFromExtendedStopInfo(info);
}

size_t
SBThread::GetStopDescription (char *dst, size_t dst_len)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {

            StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo ();
            if (stop_info_sp)
            {
                const char *stop_desc = stop_info_sp->GetDescription();
                if (stop_desc)
                {
                    if (log)
                        log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => \"%s\"",
                                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                                     stop_desc);
                    if (dst)
                        return ::snprintf (dst, dst_len, "%s", stop_desc);
                    else
                    {
                        // NULL dst passed in, return the length needed to contain the description
                        return ::strlen (stop_desc) + 1; // Include the NULL byte for size
                    }
                }
                else
                {
                    size_t stop_desc_len = 0;
                    switch (stop_info_sp->GetStopReason())
                    {
                    case eStopReasonTrace:
                    case eStopReasonPlanComplete:
                        {
                            static char trace_desc[] = "step";
                            stop_desc = trace_desc;
                            stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size
                        }
                        break;

                    case eStopReasonBreakpoint:
                        {
                            static char bp_desc[] = "breakpoint hit";
                            stop_desc = bp_desc;
                            stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
                        }
                        break;

                    case eStopReasonWatchpoint:
                        {
                            static char wp_desc[] = "watchpoint hit";
                            stop_desc = wp_desc;
                            stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
                        }
                        break;

                    case eStopReasonSignal:
                        {
                            stop_desc = exe_ctx.GetProcessPtr()->GetUnixSignals()->GetSignalAsCString(stop_info_sp->GetValue());
                            if (stop_desc == NULL || stop_desc[0] == '\0')
                            {
                                static char signal_desc[] = "signal";
                                stop_desc = signal_desc;
                                stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size
                            }
                        }
                        break;

                    case eStopReasonException:
                        {
                            char exc_desc[] = "exception";
                            stop_desc = exc_desc;
                            stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
                        }
                        break;          

                    case eStopReasonExec:
                        {
                            char exc_desc[] = "exec";
                            stop_desc = exc_desc;
                            stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
                        }
                        break;

                    case eStopReasonThreadExiting:
                        {
                            char limbo_desc[] = "thread exiting";
                            stop_desc = limbo_desc;
                            stop_desc_len = sizeof(limbo_desc);
                        }
                        break;
                    default:
                        break;
                    }

                    if (stop_desc && stop_desc[0])
                    {
                        if (log)
                            log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => '%s'",
                                         static_cast<void*>(exe_ctx.GetThreadPtr()),
                                         stop_desc);

                        if (dst)
                            return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte

                        if (stop_desc_len == 0)
                            stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte

                        return stop_desc_len;
                    }
                }
            }
        }
        else
        {
            Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
            if (log)
                log->Printf ("SBThread(%p)::GetStopDescription() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }
    if (dst)
        *dst = 0;
    return 0;
}

SBValue
SBThread::GetStopReturnValue ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    ValueObjectSP return_valobj_sp;
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo ();
            if (stop_info_sp)
            {
                return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
            }
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::GetStopReturnValue() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }

    if (log)
        log->Printf ("SBThread(%p)::GetStopReturnValue () => %s",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     return_valobj_sp.get()
                        ? return_valobj_sp->GetValueAsCString()
                        : "<no return value>");

    return SBValue (return_valobj_sp);
}

void
SBThread::SetThread (const ThreadSP& lldb_object_sp)
{
    m_opaque_sp->SetThreadSP (lldb_object_sp);
}

lldb::tid_t
SBThread::GetThreadID () const
{
    ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
    if (thread_sp)
        return thread_sp->GetID();
    return LLDB_INVALID_THREAD_ID;
}

uint32_t
SBThread::GetIndexID () const
{
    ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
    if (thread_sp)
        return thread_sp->GetIndexID();
    return LLDB_INVALID_INDEX32;
}

const char *
SBThread::GetName () const
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    const char *name = NULL;
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            name = exe_ctx.GetThreadPtr()->GetName();
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::GetName() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }

    if (log)
        log->Printf ("SBThread(%p)::GetName () => %s",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     name ? name : "NULL");

    return name;
}

const char *
SBThread::GetQueueName () const
{
    const char *name = NULL;
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            name = exe_ctx.GetThreadPtr()->GetQueueName();
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::GetQueueName() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }

    if (log)
        log->Printf ("SBThread(%p)::GetQueueName () => %s",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     name ? name : "NULL");

    return name;
}

lldb::queue_id_t
SBThread::GetQueueID () const
{
    queue_id_t id = LLDB_INVALID_QUEUE_ID;
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            id = exe_ctx.GetThreadPtr()->GetQueueID();
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::GetQueueID() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }

    if (log)
        log->Printf ("SBThread(%p)::GetQueueID () => 0x%" PRIx64,
                     static_cast<void*>(exe_ctx.GetThreadPtr()), id);

    return id;
}

bool
SBThread::GetInfoItemByPathAsString (const char *path, SBStream &strm)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    bool success = false;
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            Thread *thread = exe_ctx.GetThreadPtr();
            StructuredData::ObjectSP info_root_sp = thread->GetExtendedInfo();
            if (info_root_sp)
            {
                StructuredData::ObjectSP node = info_root_sp->GetObjectForDotSeparatedPath (path);
                if (node)
                {
                    if (node->GetType() == StructuredData::Type::eTypeString)
                    {
                        strm.Printf ("%s", node->GetAsString()->GetValue().c_str());
                        success = true;
                    }
                    if (node->GetType() == StructuredData::Type::eTypeInteger)
                    {
                        strm.Printf ("0x%" PRIx64, node->GetAsInteger()->GetValue());
                        success = true;
                    }
                    if (node->GetType() == StructuredData::Type::eTypeFloat)
                    {
                        strm.Printf ("0x%f", node->GetAsFloat()->GetValue());
                        success = true;
                    }
                    if (node->GetType() == StructuredData::Type::eTypeBoolean)
                    {
                        if (node->GetAsBoolean()->GetValue() == true)
                            strm.Printf ("true");
                        else
                            strm.Printf ("false");
                        success = true;
                    }
                    if (node->GetType() == StructuredData::Type::eTypeNull)
                    {
                        strm.Printf ("null");
                        success = true;
                    }
                }
            }
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::GetInfoItemByPathAsString() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }

    if (log)
        log->Printf ("SBThread(%p)::GetInfoItemByPathAsString () => %s",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     strm.GetData());

    return success;
}


SBError
SBThread::ResumeNewPlan (ExecutionContext &exe_ctx, ThreadPlan *new_plan)
{
    SBError sb_error;
    
    Process *process = exe_ctx.GetProcessPtr();
    if (!process)
    {
        sb_error.SetErrorString("No process in SBThread::ResumeNewPlan");
        return sb_error;
    }

    Thread *thread = exe_ctx.GetThreadPtr();
    if (!thread)
    {
        sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan");
        return sb_error;
    }
    
    // User level plans should be Master Plans so they can be interrupted, other plans executed, and
    // then a "continue" will resume the plan.
    if (new_plan != NULL)
    {
        new_plan->SetIsMasterPlan(true);
        new_plan->SetOkayToDiscard(false);
    }
    
    // Why do we need to set the current thread by ID here???
    process->GetThreadList().SetSelectedThreadByID (thread->GetID());

    if (process->GetTarget().GetDebugger().GetAsyncExecution ())
        sb_error.ref() = process->Resume ();
    else
        sb_error.ref() = process->ResumeSynchronous (NULL);
    
    return sb_error;
}

void
SBThread::StepOver (lldb::RunMode stop_other_threads)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (log)
        log->Printf ("SBThread(%p)::StepOver (stop_other_threads='%s')",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     Thread::RunModeAsCString (stop_other_threads));

    if (exe_ctx.HasThreadScope())
    {
        Thread *thread = exe_ctx.GetThreadPtr();
        bool abort_other_plans = false;
        StackFrameSP frame_sp(thread->GetStackFrameAtIndex (0));

        ThreadPlanSP new_plan_sp;
        if (frame_sp)
        {
            if (frame_sp->HasDebugInformation ())
            {
                const LazyBool avoid_no_debug = eLazyBoolCalculate;
                SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
                new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
                                                                    sc.line_entry,
                                                                    sc,
                                                                    stop_other_threads,
                                                                    avoid_no_debug);
            }
            else
            {
                new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true,
                                                                               abort_other_plans,
                                                                               stop_other_threads);
            }
        }

        // This returns an error, we should use it!
        ResumeNewPlan (exe_ctx, new_plan_sp.get());
    }
}

void
SBThread::StepInto (lldb::RunMode stop_other_threads)
{
    StepInto (NULL, stop_other_threads);
}

void
SBThread::StepInto (const char *target_name, lldb::RunMode stop_other_threads)
{
    SBError error;
    StepInto(target_name, LLDB_INVALID_LINE_NUMBER, error, stop_other_threads);
}

void
SBThread::StepInto (const char *target_name, uint32_t end_line, SBError &error, lldb::RunMode stop_other_threads)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (log)
        log->Printf ("SBThread(%p)::StepInto (target_name='%s', stop_other_threads='%s')",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     target_name? target_name: "<NULL>",
                     Thread::RunModeAsCString (stop_other_threads));

    if (exe_ctx.HasThreadScope())
    {
        bool abort_other_plans = false;

        Thread *thread = exe_ctx.GetThreadPtr();
        StackFrameSP frame_sp(thread->GetStackFrameAtIndex (0));
        ThreadPlanSP new_plan_sp;

        if (frame_sp && frame_sp->HasDebugInformation ())
        {
            SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
            AddressRange range;
            if (end_line == LLDB_INVALID_LINE_NUMBER)
                range = sc.line_entry.range;
            else
            {
                if (!sc.GetAddressRangeFromHereToEndLine(end_line, range, error.ref()))
                    return;
            }
            
            const LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate;
            const LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate;
            new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
                                                              range,
                                                              sc,
                                                              target_name,
                                                              stop_other_threads,
                                                              step_in_avoids_code_without_debug_info,
                                                              step_out_avoids_code_without_debug_info);
        }
        else
        {
            new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false,
                                                                           abort_other_plans,
                                                                           stop_other_threads);
        }

        error = ResumeNewPlan (exe_ctx, new_plan_sp.get());
    }
}

void
SBThread::StepOut ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (log)
        log->Printf ("SBThread(%p)::StepOut ()",
                     static_cast<void*>(exe_ctx.GetThreadPtr()));

    if (exe_ctx.HasThreadScope())
    {
        bool abort_other_plans = false;
        bool stop_other_threads = false;

        Thread *thread = exe_ctx.GetThreadPtr();

        const LazyBool avoid_no_debug = eLazyBoolCalculate;
        ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut (abort_other_plans,
                                                                    NULL,
                                                                    false,
                                                                    stop_other_threads,
                                                                    eVoteYes,
                                                                    eVoteNoOpinion,
                                                                    0,
                                                                    avoid_no_debug));

        // This returns an error, we should use it!
        ResumeNewPlan (exe_ctx, new_plan_sp.get());
    }
}

void
SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (!sb_frame.IsValid())
    {
        if (log)
            log->Printf("SBThread(%p)::StepOutOfFrame passed an invalid frame, returning.",
                        static_cast<void*>(exe_ctx.GetThreadPtr()));
        return;
    }
    
    StackFrameSP frame_sp (sb_frame.GetFrameSP());
    if (log)
    {
        SBStream frame_desc_strm;
        sb_frame.GetDescription (frame_desc_strm);
        log->Printf ("SBThread(%p)::StepOutOfFrame (frame = SBFrame(%p): %s)",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     static_cast<void*>(frame_sp.get()),
                     frame_desc_strm.GetData());
    }

    if (exe_ctx.HasThreadScope())
    {
        bool abort_other_plans = false;
        bool stop_other_threads = false;
        Thread *thread = exe_ctx.GetThreadPtr();
        if (sb_frame.GetThread().GetThreadID() != thread->GetID())
        {
            log->Printf("SBThread(%p)::StepOutOfFrame passed a frame from another thread (0x%" PRIx64 " vrs. 0x%" PRIx64 ", returning.",
                        static_cast<void*>(exe_ctx.GetThreadPtr()),
                        sb_frame.GetThread().GetThreadID(),
                        thread->GetID());
        }

        ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut (abort_other_plans,
                                                                    NULL,
                                                                    false,
                                                                    stop_other_threads,
                                                                    eVoteYes,
                                                                    eVoteNoOpinion,
                                                                    frame_sp->GetFrameIndex()));

        // This returns an error, we should use it!
        ResumeNewPlan (exe_ctx, new_plan_sp.get());
    }
}

void
SBThread::StepInstruction (bool step_over)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (log)
        log->Printf ("SBThread(%p)::StepInstruction (step_over=%i)",
                     static_cast<void*>(exe_ctx.GetThreadPtr()), step_over);

    if (exe_ctx.HasThreadScope())
    {
        Thread *thread = exe_ctx.GetThreadPtr();
        ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepSingleInstruction (step_over, true, true));

        // This returns an error, we should use it!
        ResumeNewPlan (exe_ctx, new_plan_sp.get());
    }
}

void
SBThread::RunToAddress (lldb::addr_t addr)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (log)
        log->Printf ("SBThread(%p)::RunToAddress (addr=0x%" PRIx64 ")",
                     static_cast<void*>(exe_ctx.GetThreadPtr()), addr);

    if (exe_ctx.HasThreadScope())
    {
        bool abort_other_plans = false;
        bool stop_other_threads = true;

        Address target_addr (addr);

        Thread *thread = exe_ctx.GetThreadPtr();

        ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress (abort_other_plans,
                                                                         target_addr,
                                                                         stop_other_threads));

        // This returns an error, we should use it!
        ResumeNewPlan (exe_ctx, new_plan_sp.get());
    }
}

SBError
SBThread::StepOverUntil (lldb::SBFrame &sb_frame, 
                         lldb::SBFileSpec &sb_file_spec, 
                         uint32_t line)
{
    SBError sb_error;
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    char path[PATH_MAX];

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    StackFrameSP frame_sp (sb_frame.GetFrameSP());

    if (log)
    {
        SBStream frame_desc_strm;
        sb_frame.GetDescription (frame_desc_strm);
        sb_file_spec->GetPath (path, sizeof(path));
        log->Printf ("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, file+line = %s:%u)",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     static_cast<void*>(frame_sp.get()),
                     frame_desc_strm.GetData(), path, line);
    }

    if (exe_ctx.HasThreadScope())
    {
        Target *target = exe_ctx.GetTargetPtr();
        Thread *thread = exe_ctx.GetThreadPtr();

        if (line == 0)
        {
            sb_error.SetErrorString("invalid line argument");
            return sb_error;
        }

        if (!frame_sp)
        {
            frame_sp = thread->GetSelectedFrame ();
            if (!frame_sp)
                frame_sp = thread->GetStackFrameAtIndex (0);
        }

        SymbolContext frame_sc;
        if (!frame_sp)        
        {
            sb_error.SetErrorString("no valid frames in thread to step");
            return sb_error;
        }

        // If we have a frame, get its line
        frame_sc = frame_sp->GetSymbolContext (eSymbolContextCompUnit  |
                                               eSymbolContextFunction  | 
                                               eSymbolContextLineEntry | 
                                               eSymbolContextSymbol    );

        if (frame_sc.comp_unit == NULL)
        {
            sb_error.SetErrorStringWithFormat("frame %u doesn't have debug information", frame_sp->GetFrameIndex());
            return sb_error;
        }

        FileSpec step_file_spec;
        if (sb_file_spec.IsValid())
        {
            // The file spec passed in was valid, so use it
            step_file_spec = sb_file_spec.ref();
        }
        else
        {
            if (frame_sc.line_entry.IsValid())
                step_file_spec = frame_sc.line_entry.file;
            else
            {
                sb_error.SetErrorString("invalid file argument or no file for frame");
                return sb_error;
            }
        }

        // Grab the current function, then we will make sure the "until" address is
        // within the function.  We discard addresses that are out of the current
        // function, and then if there are no addresses remaining, give an appropriate
        // error message.

        bool all_in_function = true;
        AddressRange fun_range = frame_sc.function->GetAddressRange();

        std::vector<addr_t> step_over_until_addrs;
        const bool abort_other_plans = false;
        const bool stop_other_threads = false;
        const bool check_inlines = true;
        const bool exact = false;

        SymbolContextList sc_list;
        const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext (step_file_spec, 
                                                                               line, 
                                                                               check_inlines, 
                                                                               exact, 
                                                                               eSymbolContextLineEntry, 
                                                                               sc_list);
        if (num_matches > 0)
        {
            SymbolContext sc;
            for (uint32_t i=0; i<num_matches; ++i)
            {
                if (sc_list.GetContextAtIndex(i, sc))
                {
                    addr_t step_addr = sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
                    if (step_addr != LLDB_INVALID_ADDRESS)
                    {
                        if (fun_range.ContainsLoadAddress(step_addr, target))
                            step_over_until_addrs.push_back(step_addr);
                        else
                            all_in_function = false;
                    }
                }
            }
        }

        if (step_over_until_addrs.empty())
        {
            if (all_in_function)
            {
                step_file_spec.GetPath (path, sizeof(path));
                sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path, line);
            }
            else
                sb_error.SetErrorString ("step until target not in current function");
        }
        else
        {
            ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepUntil (abort_other_plans,
                                                                        &step_over_until_addrs[0],
                                                                        step_over_until_addrs.size(),
                                                                        stop_other_threads,
                                                                        frame_sp->GetFrameIndex()));

            sb_error = ResumeNewPlan (exe_ctx, new_plan_sp.get());
        }
    }
    else
    {
        sb_error.SetErrorString("this SBThread object is invalid");
    }
    return sb_error;
}

SBError
SBThread::StepUsingScriptedThreadPlan (const char *script_class_name)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    SBError sb_error;

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (log)
    {
        log->Printf ("SBThread(%p)::StepUsingScriptedThreadPlan: class name: %s",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     script_class_name);
    }


    if (!exe_ctx.HasThreadScope())
    {
        sb_error.SetErrorString("this SBThread object is invalid");
        return sb_error;
    }

    Thread *thread = exe_ctx.GetThreadPtr();
    ThreadPlanSP thread_plan_sp = thread->QueueThreadPlanForStepScripted(false, script_class_name, false);

    if (thread_plan_sp)
        sb_error = ResumeNewPlan(exe_ctx, thread_plan_sp.get());
    else
    {
        sb_error.SetErrorStringWithFormat("Error queuing thread plan for class: %s.", script_class_name);
        if (log)
        log->Printf ("SBThread(%p)::StepUsingScriptedThreadPlan: Error queuing thread plan for class: %s",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     script_class_name);
    }

    return sb_error;
}

SBError
SBThread::JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    SBError sb_error;

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (log)
        log->Printf ("SBThread(%p)::JumpToLine (file+line = %s:%u)",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     file_spec->GetPath().c_str(), line);

    if (!exe_ctx.HasThreadScope())
    {
        sb_error.SetErrorString("this SBThread object is invalid");
        return sb_error;
    }

    Thread *thread = exe_ctx.GetThreadPtr();

    Error err = thread->JumpToLine (file_spec.get(), line, true);
    sb_error.SetError (err);
    return sb_error;
}

SBError
SBThread::ReturnFromFrame (SBFrame &frame, SBValue &return_value)
{
    SBError sb_error;

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

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (log)
        log->Printf ("SBThread(%p)::ReturnFromFrame (frame=%d)",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     frame.GetFrameID());

    if (exe_ctx.HasThreadScope())
    {
        Thread *thread = exe_ctx.GetThreadPtr();
        sb_error.SetError (thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
    }

    return sb_error;
}

SBError
SBThread::UnwindInnermostExpression()
{
    SBError sb_error;

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

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (log)
        log->Printf ("SBThread(%p)::UnwindExpressionEvaluation",
                     static_cast<void*>(exe_ctx.GetThreadPtr()));

    if (exe_ctx.HasThreadScope())
    {
        Thread *thread = exe_ctx.GetThreadPtr();
        sb_error.SetError (thread->UnwindInnermostExpression());
        if (sb_error.Success())
            thread->SetSelectedFrameByIndex(0, false);
    }

    return sb_error;

}

bool
SBThread::Suspend()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    bool result = false;
    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            exe_ctx.GetThreadPtr()->SetResumeState (eStateSuspended);
            result = true;
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::Suspend() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }
    if (log)
        log->Printf ("SBThread(%p)::Suspend() => %i",
                     static_cast<void*>(exe_ctx.GetThreadPtr()), result);
    return result;
}

bool
SBThread::Resume ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    bool result = false;
    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            const bool override_suspend = true;
            exe_ctx.GetThreadPtr()->SetResumeState (eStateRunning, override_suspend);
            result = true;
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::Resume() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }
    if (log)
        log->Printf ("SBThread(%p)::Resume() => %i",
                     static_cast<void*>(exe_ctx.GetThreadPtr()), result);
    return result;
}

bool
SBThread::IsSuspended()
{
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
        return exe_ctx.GetThreadPtr()->GetResumeState () == eStateSuspended;
    return false;
}

bool
SBThread::IsStopped()
{
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
        return StateIsStoppedState(exe_ctx.GetThreadPtr()->GetState(), true);
    return false;
}

SBProcess
SBThread::GetProcess ()
{
    SBProcess sb_process;
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        // Have to go up to the target so we can get a shared pointer to our process...
        sb_process.SetSP (exe_ctx.GetProcessSP());
    }

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
    {
        SBStream frame_desc_strm;
        sb_process.GetDescription (frame_desc_strm);
        log->Printf ("SBThread(%p)::GetProcess () => SBProcess(%p): %s",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     static_cast<void*>(sb_process.GetSP().get()),
                     frame_desc_strm.GetData());
    }

    return sb_process;
}

uint32_t
SBThread::GetNumFrames ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    uint32_t num_frames = 0;
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount();
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::GetNumFrames() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }

    if (log)
        log->Printf ("SBThread(%p)::GetNumFrames () => %u",
                     static_cast<void*>(exe_ctx.GetThreadPtr()), num_frames);

    return num_frames;
}

SBFrame
SBThread::GetFrameAtIndex (uint32_t idx)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBFrame sb_frame;
    StackFrameSP frame_sp;
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex (idx);
            sb_frame.SetFrameSP (frame_sp);
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::GetFrameAtIndex() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }

    if (log)
    {
        SBStream frame_desc_strm;
        sb_frame.GetDescription (frame_desc_strm);
        log->Printf ("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s",
                     static_cast<void*>(exe_ctx.GetThreadPtr()), idx,
                     static_cast<void*>(frame_sp.get()),
                     frame_desc_strm.GetData());
    }

    return sb_frame;
}

lldb::SBFrame
SBThread::GetSelectedFrame ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBFrame sb_frame;
    StackFrameSP frame_sp;
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            frame_sp = exe_ctx.GetThreadPtr()->GetSelectedFrame ();
            sb_frame.SetFrameSP (frame_sp);
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::GetSelectedFrame() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }

    if (log)
    {
        SBStream frame_desc_strm;
        sb_frame.GetDescription (frame_desc_strm);
        log->Printf ("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     static_cast<void*>(frame_sp.get()),
                     frame_desc_strm.GetData());
    }

    return sb_frame;
}

lldb::SBFrame
SBThread::SetSelectedFrame (uint32_t idx)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBFrame sb_frame;
    StackFrameSP frame_sp;
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            Thread *thread = exe_ctx.GetThreadPtr();
            frame_sp = thread->GetStackFrameAtIndex (idx);
            if (frame_sp)
            {
                thread->SetSelectedFrame (frame_sp.get());
                sb_frame.SetFrameSP (frame_sp);
            }
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::SetSelectedFrame() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }

    if (log)
    {
        SBStream frame_desc_strm;
        sb_frame.GetDescription (frame_desc_strm);
        log->Printf ("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s",
                     static_cast<void*>(exe_ctx.GetThreadPtr()), idx,
                     static_cast<void*>(frame_sp.get()),
                     frame_desc_strm.GetData());
    }
    return sb_frame;
}

bool
SBThread::EventIsThreadEvent (const SBEvent &event)
{
    return Thread::ThreadEventData::GetEventDataFromEvent(event.get()) != NULL;
}

SBFrame
SBThread::GetStackFrameFromEvent (const SBEvent &event)
{
    return Thread::ThreadEventData::GetStackFrameFromEvent (event.get());

}

SBThread
SBThread::GetThreadFromEvent (const SBEvent &event)
{
    return Thread::ThreadEventData::GetThreadFromEvent (event.get());
}

bool
SBThread::operator == (const SBThread &rhs) const
{
    return m_opaque_sp->GetThreadSP().get() == rhs.m_opaque_sp->GetThreadSP().get();
}

bool
SBThread::operator != (const SBThread &rhs) const
{
    return m_opaque_sp->GetThreadSP().get() != rhs.m_opaque_sp->GetThreadSP().get();
}

bool
SBThread::GetStatus (SBStream &status) const
{
    Stream &strm = status.ref();

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        exe_ctx.GetThreadPtr()->GetStatus(strm, 0, 1, 1);
    }
    else
        strm.PutCString ("No status");
    
    return true;
}

bool
SBThread::GetDescription (SBStream &description) const
{
    Stream &strm = description.ref();

    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

    if (exe_ctx.HasThreadScope())
    {
        exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat(strm, LLDB_INVALID_THREAD_ID);
        //strm.Printf("SBThread: tid = 0x%4.4" PRIx64, exe_ctx.GetThreadPtr()->GetID());
    }
    else
        strm.PutCString ("No value");
    
    return true;
}

SBThread
SBThread::GetExtendedBacktraceThread (const char *type)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    std::unique_lock<std::recursive_mutex> lock;
    ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
    SBThread sb_origin_thread;

    if (exe_ctx.HasThreadScope())
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
        {
            ThreadSP real_thread(exe_ctx.GetThreadSP());
            if (real_thread)
            {
                ConstString type_const (type);
                Process *process = exe_ctx.GetProcessPtr();
                if (process)
                {
                    SystemRuntime *runtime = process->GetSystemRuntime();
                    if (runtime)
                    {
                        ThreadSP new_thread_sp (runtime->GetExtendedBacktraceThread (real_thread, type_const));
                        if (new_thread_sp)
                        {
                            // Save this in the Process' ExtendedThreadList so a strong pointer retains the
                            // object.
                            process->GetExtendedThreadList().AddThread (new_thread_sp);
                            sb_origin_thread.SetThread (new_thread_sp);
                            if (log)
                            {
                                const char *queue_name = new_thread_sp->GetQueueName();
                                if (queue_name == NULL)
                                    queue_name = "";
                                log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => new extended Thread "
                                             "created (%p) with queue_id 0x%" PRIx64 " queue name '%s'",
                                             static_cast<void*>(exe_ctx.GetThreadPtr()),
                                             static_cast<void*>(new_thread_sp.get()),
                                             new_thread_sp->GetQueueID(),
                                             queue_name);
                            }
                        }
                    }
                }
            }
        }
        else
        {
            if (log)
                log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => error: process is running",
                             static_cast<void*>(exe_ctx.GetThreadPtr()));
        }
    }

    if (log && sb_origin_thread.IsValid() == false)
        log->Printf("SBThread(%p)::GetExtendedBacktraceThread() is not returning a Valid thread",
                    static_cast<void*>(exe_ctx.GetThreadPtr()));
    return sb_origin_thread;
}

uint32_t
SBThread::GetExtendedBacktraceOriginatingIndexID ()
{
    ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
    if (thread_sp)
        return thread_sp->GetExtendedBacktraceOriginatingIndexID();
    return LLDB_INVALID_INDEX32;
}

bool
SBThread::SafeToCallFunctions ()
{
    ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
    if (thread_sp)
        return thread_sp->SafeToCallFunctions();
    return true;
}

lldb_private::Thread *
SBThread::operator->()
{
    ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
    if (thread_sp)
        return thread_sp.get();
    else
        return NULL;
}

lldb_private::Thread *
SBThread::get()
{
    ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
    if (thread_sp)
        return thread_sp.get();
    else
        return NULL;
}

