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

#include "lldb/lldb-python.h"

#include "lldb/API/SBTarget.h"

#include "lldb/lldb-public.h"

#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBExpressionOptions.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBModule.h"
#include "lldb/API/SBModuleSpec.h"
#include "lldb/API/SBSourceManager.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBSymbolContextList.h"
#include "lldb/Breakpoint/BreakpointID.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/AddressResolver.h"
#include "lldb/Core/AddressResolverName.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/STLUtils.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"

#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"

#include "lldb/Interpreter/CommandReturnObject.h"
#include "../source/Commands/CommandObjectBreakpoint.h"
#include "llvm/Support/Regex.h"


using namespace lldb;
using namespace lldb_private;

#define DEFAULT_DISASM_BYTE_SIZE 32


SBAttachInfo::SBAttachInfo () :
    m_opaque_sp (new ProcessAttachInfo())
{
}

SBAttachInfo::SBAttachInfo (lldb::pid_t pid) :
    m_opaque_sp (new ProcessAttachInfo())
{
    m_opaque_sp->SetProcessID (pid);
}

SBAttachInfo::SBAttachInfo (const char *path, bool wait_for) :
    m_opaque_sp (new ProcessAttachInfo())
{
    if (path && path[0])
        m_opaque_sp->GetExecutableFile().SetFile(path, false);
    m_opaque_sp->SetWaitForLaunch (wait_for);
}

SBAttachInfo::SBAttachInfo (const SBAttachInfo &rhs) :
    m_opaque_sp (new ProcessAttachInfo())
{
    *m_opaque_sp = *rhs.m_opaque_sp;
}

SBAttachInfo::~SBAttachInfo()
{
}

lldb_private::ProcessAttachInfo &
SBAttachInfo::ref ()
{
    return *m_opaque_sp;
}

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

lldb::pid_t
SBAttachInfo::GetProcessID ()
{
    return m_opaque_sp->GetProcessID();
}

void
SBAttachInfo::SetProcessID (lldb::pid_t pid)
{
    m_opaque_sp->SetProcessID (pid);
}


uint32_t
SBAttachInfo::GetResumeCount ()
{
    return m_opaque_sp->GetResumeCount();
}

void
SBAttachInfo::SetResumeCount (uint32_t c)
{
    m_opaque_sp->SetResumeCount (c);
}

const char *
SBAttachInfo::GetProcessPluginName ()
{
    return m_opaque_sp->GetProcessPluginName();
}

void
SBAttachInfo::SetProcessPluginName (const char *plugin_name)
{
    return m_opaque_sp->SetProcessPluginName (plugin_name);
}

void
SBAttachInfo::SetExecutable (const char *path)
{
    if (path && path[0])
        m_opaque_sp->GetExecutableFile().SetFile(path, false);
    else
        m_opaque_sp->GetExecutableFile().Clear();
}

void
SBAttachInfo::SetExecutable (SBFileSpec exe_file)
{
    if (exe_file.IsValid())
        m_opaque_sp->GetExecutableFile() = exe_file.ref();
    else
        m_opaque_sp->GetExecutableFile().Clear();
}

bool
SBAttachInfo::GetWaitForLaunch ()
{
    return m_opaque_sp->GetWaitForLaunch();
}

void
SBAttachInfo::SetWaitForLaunch (bool b)
{
    m_opaque_sp->SetWaitForLaunch (b);
}

bool
SBAttachInfo::GetIgnoreExisting ()
{
    return m_opaque_sp->GetIgnoreExisting();
}

void
SBAttachInfo::SetIgnoreExisting (bool b)
{
    m_opaque_sp->SetIgnoreExisting (b);
}

uint32_t
SBAttachInfo::GetUserID()
{
    return m_opaque_sp->GetUserID();
}

uint32_t
SBAttachInfo::GetGroupID()
{
    return m_opaque_sp->GetGroupID();
}

bool
SBAttachInfo::UserIDIsValid ()
{
    return m_opaque_sp->UserIDIsValid();
}

bool
SBAttachInfo::GroupIDIsValid ()
{
    return m_opaque_sp->GroupIDIsValid();
}

void
SBAttachInfo::SetUserID (uint32_t uid)
{
    m_opaque_sp->SetUserID (uid);
}

void
SBAttachInfo::SetGroupID (uint32_t gid)
{
    m_opaque_sp->SetGroupID (gid);
}

uint32_t
SBAttachInfo::GetEffectiveUserID()
{
    return m_opaque_sp->GetEffectiveUserID();
}

uint32_t
SBAttachInfo::GetEffectiveGroupID()
{
    return m_opaque_sp->GetEffectiveGroupID();
}

bool
SBAttachInfo::EffectiveUserIDIsValid ()
{
    return m_opaque_sp->EffectiveUserIDIsValid();
}

bool
SBAttachInfo::EffectiveGroupIDIsValid ()
{
    return m_opaque_sp->EffectiveGroupIDIsValid ();
}

void
SBAttachInfo::SetEffectiveUserID (uint32_t uid)
{
    m_opaque_sp->SetEffectiveUserID(uid);
}

void
SBAttachInfo::SetEffectiveGroupID (uint32_t gid)
{
    m_opaque_sp->SetEffectiveGroupID(gid);
}

lldb::pid_t
SBAttachInfo::GetParentProcessID ()
{
    return m_opaque_sp->GetParentProcessID();
}

void
SBAttachInfo::SetParentProcessID (lldb::pid_t pid)
{
    m_opaque_sp->SetParentProcessID (pid);
}

bool
SBAttachInfo::ParentProcessIDIsValid()
{
    return m_opaque_sp->ParentProcessIDIsValid();
}

SBListener
SBAttachInfo::GetListener ()
{
    return SBListener(m_opaque_sp->GetListener());
}

void
SBAttachInfo::SetListener (SBListener &listener)
{
    m_opaque_sp->SetListener(listener.GetSP());
}

//----------------------------------------------------------------------
// SBTarget constructor
//----------------------------------------------------------------------
SBTarget::SBTarget () :
    m_opaque_sp ()
{
}

SBTarget::SBTarget (const SBTarget& rhs) :
    m_opaque_sp (rhs.m_opaque_sp)
{
}

SBTarget::SBTarget(const TargetSP& target_sp) :
    m_opaque_sp (target_sp)
{
}

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

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

const char *
SBTarget::GetBroadcasterClassName ()
{
    return Target::GetStaticBroadcasterClass().AsCString();
}

bool
SBTarget::IsValid () const
{
    return m_opaque_sp.get() != NULL && m_opaque_sp->IsValid();
}

SBProcess
SBTarget::GetProcess ()
{
    SBProcess sb_process;
    ProcessSP process_sp;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        process_sp = target_sp->GetProcessSP();
        sb_process.SetSP (process_sp);
    }

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
        log->Printf ("SBTarget(%p)::GetProcess () => SBProcess(%p)",
                     static_cast<void*>(target_sp.get()),
                     static_cast<void*>(process_sp.get()));

    return sb_process;
}

SBPlatform
SBTarget::GetPlatform ()
{
    TargetSP target_sp(GetSP());
    if (!target_sp)
        return SBPlatform();

    SBPlatform platform;
    platform.m_opaque_sp = target_sp->GetPlatform();

    return platform;
}

SBDebugger
SBTarget::GetDebugger () const
{
    SBDebugger debugger;
    TargetSP target_sp(GetSP());
    if (target_sp)
        debugger.reset (target_sp->GetDebugger().shared_from_this());
    return debugger;
}

SBProcess
SBTarget::LoadCore (const char *core_file)
{
    SBProcess sb_process;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        FileSpec filespec(core_file, true);
        ProcessSP process_sp (target_sp->CreateProcess(target_sp->GetDebugger().GetListener(),
                                                       NULL,
                                                       &filespec));
        if (process_sp)
        {
            process_sp->LoadCore();
            sb_process.SetSP (process_sp);
        }
    }
    return sb_process;
}

SBProcess
SBTarget::LaunchSimple
(
    char const **argv,
    char const **envp,
    const char *working_directory
)
{
    char *stdin_path = NULL;
    char *stdout_path = NULL;
    char *stderr_path = NULL;
    uint32_t launch_flags = 0;
    bool stop_at_entry = false;
    SBError error;
    SBListener listener = GetDebugger().GetListener();
    return Launch (listener,
                   argv,
                   envp,
                   stdin_path,
                   stdout_path,
                   stderr_path,
                   working_directory,
                   launch_flags,
                   stop_at_entry,
                   error);
}

SBError
SBTarget::Install()
{
    SBError sb_error;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        sb_error.ref() = target_sp->Install(NULL);
    }
    return sb_error;
}

SBProcess
SBTarget::Launch 
(
    SBListener &listener, 
    char const **argv,
    char const **envp,
    const char *stdin_path,
    const char *stdout_path,
    const char *stderr_path,
    const char *working_directory,
    uint32_t launch_flags,   // See LaunchFlags
    bool stop_at_entry,
    lldb::SBError& error
)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBProcess sb_process;
    ProcessSP process_sp;
    TargetSP target_sp(GetSP());

    if (log)
        log->Printf ("SBTarget(%p)::Launch (argv=%p, envp=%p, stdin=%s, stdout=%s, stderr=%s, working-dir=%s, launch_flags=0x%x, stop_at_entry=%i, &error (%p))...",
                     static_cast<void*>(target_sp.get()),
                     static_cast<void*>(argv), static_cast<void*>(envp),
                     stdin_path ? stdin_path : "NULL",
                     stdout_path ? stdout_path : "NULL",
                     stderr_path ? stderr_path : "NULL",
                     working_directory ? working_directory : "NULL",
                     launch_flags, stop_at_entry,
                     static_cast<void*>(error.get()));

    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());

        if (stop_at_entry)
            launch_flags |= eLaunchFlagStopAtEntry;

        if (getenv("LLDB_LAUNCH_FLAG_DISABLE_ASLR"))
            launch_flags |= eLaunchFlagDisableASLR;

        StateType state = eStateInvalid;
        process_sp = target_sp->GetProcessSP();
        if (process_sp)
        {
            state = process_sp->GetState();

            if (process_sp->IsAlive() && state != eStateConnected)
            {
                if (state == eStateAttaching)
                    error.SetErrorString ("process attach is in progress");
                else
                    error.SetErrorString ("a process is already being debugged");
                return sb_process;
            }
        }

        if (state == eStateConnected)
        {
            // If we are already connected, then we have already specified the
            // listener, so if a valid listener is supplied, we need to error out
            // to let the client know.
            if (listener.IsValid())
            {
                error.SetErrorString ("process is connected and already has a listener, pass empty listener");
                return sb_process;
            }
        }

        if (getenv("LLDB_LAUNCH_FLAG_DISABLE_STDIO"))
            launch_flags |= eLaunchFlagDisableSTDIO;

        ProcessLaunchInfo launch_info (stdin_path, stdout_path, stderr_path, working_directory, launch_flags);

        Module *exe_module = target_sp->GetExecutableModulePointer();
        if (exe_module)
            launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
        if (argv)
            launch_info.GetArguments().AppendArguments (argv);
        if (envp)
            launch_info.GetEnvironmentEntries ().SetArguments (envp);

        if (listener.IsValid())
            launch_info.SetListener(listener.GetSP());

        error.SetError (target_sp->Launch(launch_info, NULL));

        sb_process.SetSP(target_sp->GetProcessSP());
    }
    else
    {
        error.SetErrorString ("SBTarget is invalid");
    }

    log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
    if (log)
        log->Printf ("SBTarget(%p)::Launch (...) => SBProcess(%p)",
                     static_cast<void*>(target_sp.get()),
                     static_cast<void*>(sb_process.GetSP().get()));

    return sb_process;
}

SBProcess
SBTarget::Launch (SBLaunchInfo &sb_launch_info, SBError& error)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBProcess sb_process;
    TargetSP target_sp(GetSP());

    if (log)
        log->Printf ("SBTarget(%p)::Launch (launch_info, error)...",
                     static_cast<void*>(target_sp.get()));

    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        StateType state = eStateInvalid;
        {
            ProcessSP process_sp = target_sp->GetProcessSP();
            if (process_sp)
            {
                state = process_sp->GetState();
                
                if (process_sp->IsAlive() && state != eStateConnected)
                {
                    if (state == eStateAttaching)
                        error.SetErrorString ("process attach is in progress");
                    else
                        error.SetErrorString ("a process is already being debugged");
                    return sb_process;
                }
            }
        }

        lldb_private::ProcessLaunchInfo &launch_info = sb_launch_info.ref();

        if (!launch_info.GetExecutableFile())
        {
            Module *exe_module = target_sp->GetExecutableModulePointer();
            if (exe_module)
                launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
        }

        const ArchSpec &arch_spec = target_sp->GetArchitecture();
        if (arch_spec.IsValid())
            launch_info.GetArchitecture () = arch_spec;

        error.SetError (target_sp->Launch (launch_info, NULL));
        sb_process.SetSP(target_sp->GetProcessSP());
    }
    else
    {
        error.SetErrorString ("SBTarget is invalid");
    }

    log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
    if (log)
        log->Printf ("SBTarget(%p)::Launch (...) => SBProcess(%p)",
                     static_cast<void*>(target_sp.get()),
                     static_cast<void*>(sb_process.GetSP().get()));

    return sb_process;
}

lldb::SBProcess
SBTarget::Attach (SBAttachInfo &sb_attach_info, SBError& error)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBProcess sb_process;
    ProcessSP process_sp;
    TargetSP target_sp(GetSP());

    if (log)
        log->Printf ("SBTarget(%p)::Attach (sb_attach_info, error)...",
                     static_cast<void*>(target_sp.get()));

    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());

        StateType state = eStateInvalid;
        process_sp = target_sp->GetProcessSP();
        if (process_sp)
        {
            state = process_sp->GetState();

            if (process_sp->IsAlive() && state != eStateConnected)
            {
                if (state == eStateAttaching)
                    error.SetErrorString ("process attach is in progress");
                else
                    error.SetErrorString ("a process is already being debugged");
                if (log)
                    log->Printf ("SBTarget(%p)::Attach (...) => error %s",
                                 static_cast<void*>(target_sp.get()),
                                 error.GetCString());
                return sb_process;
            }
        }

        if (state != eStateConnected)
            process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);

        if (process_sp)
        {
            ProcessAttachInfo &attach_info = sb_attach_info.ref();
            if (attach_info.ProcessIDIsValid() && !attach_info.UserIDIsValid())
            {
                PlatformSP platform_sp = target_sp->GetPlatform();
                // See if we can pre-verify if a process exists or not
                if (platform_sp && platform_sp->IsConnected())
                {
                    lldb::pid_t attach_pid = attach_info.GetProcessID();
                    ProcessInstanceInfo instance_info;
                    if (platform_sp->GetProcessInfo(attach_pid, instance_info))
                    {
                        attach_info.SetUserID(instance_info.GetEffectiveUserID());
                    }
                    else
                    {
                        error.ref().SetErrorStringWithFormat("no process found with process ID %" PRIu64, attach_pid);
                        if (log)
                        {
                            log->Printf ("SBTarget(%p)::Attach (...) => error %s",
                                         static_cast<void*>(target_sp.get()), error.GetCString());
                        }
                        return sb_process;
                    }
                }
            }
            error.SetError (process_sp->Attach (attach_info));
            if (error.Success())
            {
                sb_process.SetSP (process_sp);
                // If we are doing synchronous mode, then wait for the
                // process to stop!
                if (target_sp->GetDebugger().GetAsyncExecution () == false)
                    process_sp->WaitForProcessToStop (NULL);
            }
        }
        else
        {
            error.SetErrorString ("unable to create lldb_private::Process");
        }
    }
    else
    {
        error.SetErrorString ("SBTarget is invalid");
    }

    if (log)
        log->Printf ("SBTarget(%p)::Attach (...) => SBProcess(%p)",
                     static_cast<void*>(target_sp.get()),
                     static_cast<void*>(process_sp.get()));

    return sb_process;
}


#if defined(__APPLE__)

lldb::SBProcess
SBTarget::AttachToProcessWithID (SBListener &listener,
                                ::pid_t pid,
                                 lldb::SBError& error)
{
    return AttachToProcessWithID (listener, (lldb::pid_t)pid, error);
}

#endif // #if defined(__APPLE__)

lldb::SBProcess
SBTarget::AttachToProcessWithID 
(
    SBListener &listener, 
    lldb::pid_t pid,// The process ID to attach to
    SBError& error  // An error explaining what went wrong if attach fails
)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBProcess sb_process;
    ProcessSP process_sp;
    TargetSP target_sp(GetSP());

    if (log)
        log->Printf ("SBTarget(%p)::AttachToProcessWithID (listener, pid=%" PRId64 ", error)...",
                     static_cast<void*>(target_sp.get()), pid);

    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());

        StateType state = eStateInvalid;
        process_sp = target_sp->GetProcessSP();
        if (process_sp)
        {
            state = process_sp->GetState();

            if (process_sp->IsAlive() && state != eStateConnected)
            {
                if (state == eStateAttaching)
                    error.SetErrorString ("process attach is in progress");
                else
                    error.SetErrorString ("a process is already being debugged");
                return sb_process;
            }
        }

        if (state == eStateConnected)
        {
            // If we are already connected, then we have already specified the
            // listener, so if a valid listener is supplied, we need to error out
            // to let the client know.
            if (listener.IsValid())
            {
                error.SetErrorString ("process is connected and already has a listener, pass empty listener");
                return sb_process;
            }
        }
        else
        {
            if (listener.IsValid())
                process_sp = target_sp->CreateProcess (listener.ref(), NULL, NULL);
            else
                process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);
        }
        if (process_sp)
        {
            sb_process.SetSP (process_sp);

            ProcessAttachInfo attach_info;
            attach_info.SetProcessID (pid);

            PlatformSP platform_sp = target_sp->GetPlatform();
            ProcessInstanceInfo instance_info;
            if (platform_sp->GetProcessInfo(pid, instance_info))
            {
                attach_info.SetUserID(instance_info.GetEffectiveUserID());
            }
            error.SetError (process_sp->Attach (attach_info));            
            if (error.Success())
            {
                // If we are doing synchronous mode, then wait for the
                // process to stop!
                if (target_sp->GetDebugger().GetAsyncExecution () == false)
                    process_sp->WaitForProcessToStop (NULL);
            }
        }
        else
        {
            error.SetErrorString ("unable to create lldb_private::Process");
        }
    }
    else
    {
        error.SetErrorString ("SBTarget is invalid");
    }

    if (log)
        log->Printf ("SBTarget(%p)::AttachToProcessWithID (...) => SBProcess(%p)",
                     static_cast<void*>(target_sp.get()),
                     static_cast<void*>(process_sp.get()));
    return sb_process;
}

lldb::SBProcess
SBTarget::AttachToProcessWithName 
(
    SBListener &listener, 
    const char *name,   // basename of process to attach to
    bool wait_for,      // if true wait for a new instance of "name" to be launched
    SBError& error      // An error explaining what went wrong if attach fails
)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBProcess sb_process;
    ProcessSP process_sp;
    TargetSP target_sp(GetSP());

    if (log)
        log->Printf ("SBTarget(%p)::AttachToProcessWithName (listener, name=%s, wait_for=%s, error)...",
                     static_cast<void*>(target_sp.get()), name,
                     wait_for ? "true" : "false");

    if (name && target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());

        StateType state = eStateInvalid;
        process_sp = target_sp->GetProcessSP();
        if (process_sp)
        {
            state = process_sp->GetState();

            if (process_sp->IsAlive() && state != eStateConnected)
            {
                if (state == eStateAttaching)
                    error.SetErrorString ("process attach is in progress");
                else
                    error.SetErrorString ("a process is already being debugged");
                return sb_process;
            }
        }

        if (state == eStateConnected)
        {
            // If we are already connected, then we have already specified the
            // listener, so if a valid listener is supplied, we need to error out
            // to let the client know.
            if (listener.IsValid())
            {
                error.SetErrorString ("process is connected and already has a listener, pass empty listener");
                return sb_process;
            }
        }
        else
        {
            if (listener.IsValid())
                process_sp = target_sp->CreateProcess (listener.ref(), NULL, NULL);
            else
                process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);
        }

        if (process_sp)
        {
            sb_process.SetSP (process_sp);
            ProcessAttachInfo attach_info;
            attach_info.GetExecutableFile().SetFile(name, false);
            attach_info.SetWaitForLaunch(wait_for);
            error.SetError (process_sp->Attach (attach_info));
            if (error.Success())
            {
                // If we are doing synchronous mode, then wait for the
                // process to stop!
                if (target_sp->GetDebugger().GetAsyncExecution () == false)
                    process_sp->WaitForProcessToStop (NULL);
            }
        }
        else
        {
            error.SetErrorString ("unable to create lldb_private::Process");
        }
    }
    else
    {
        error.SetErrorString ("SBTarget is invalid");
    }

    if (log)
        log->Printf ("SBTarget(%p)::AttachToPorcessWithName (...) => SBProcess(%p)",
                     static_cast<void*>(target_sp.get()),
                     static_cast<void*>(process_sp.get()));
    return sb_process;
}

lldb::SBProcess
SBTarget::ConnectRemote
(
    SBListener &listener,
    const char *url,
    const char *plugin_name,
    SBError& error
)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBProcess sb_process;
    ProcessSP process_sp;
    TargetSP target_sp(GetSP());

    if (log)
        log->Printf ("SBTarget(%p)::ConnectRemote (listener, url=%s, plugin_name=%s, error)...",
                     static_cast<void*>(target_sp.get()), url, plugin_name);

    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        if (listener.IsValid())
            process_sp = target_sp->CreateProcess (listener.ref(), plugin_name, NULL);
        else
            process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), plugin_name, NULL);

        if (process_sp)
        {
            sb_process.SetSP (process_sp);
            error.SetError (process_sp->ConnectRemote (NULL, url));
        }
        else
        {
            error.SetErrorString ("unable to create lldb_private::Process");
        }
    }
    else
    {
        error.SetErrorString ("SBTarget is invalid");
    }

    if (log)
        log->Printf ("SBTarget(%p)::ConnectRemote (...) => SBProcess(%p)",
                     static_cast<void*>(target_sp.get()),
                     static_cast<void*>(process_sp.get()));
    return sb_process;
}

SBFileSpec
SBTarget::GetExecutable ()
{

    SBFileSpec exe_file_spec;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Module *exe_module = target_sp->GetExecutableModulePointer();
        if (exe_module)
            exe_file_spec.SetFileSpec (exe_module->GetFileSpec());
    }

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
    {
        log->Printf ("SBTarget(%p)::GetExecutable () => SBFileSpec(%p)",
                     static_cast<void*>(target_sp.get()),
                     static_cast<const void*>(exe_file_spec.get()));
    }

    return exe_file_spec;
}

bool
SBTarget::operator == (const SBTarget &rhs) const
{
    return m_opaque_sp.get() == rhs.m_opaque_sp.get();
}

bool
SBTarget::operator != (const SBTarget &rhs) const
{
    return m_opaque_sp.get() != rhs.m_opaque_sp.get();
}

lldb::TargetSP
SBTarget::GetSP () const
{
    return m_opaque_sp;
}

void
SBTarget::SetSP (const lldb::TargetSP& target_sp)
{
    m_opaque_sp = target_sp;
}

lldb::SBAddress
SBTarget::ResolveLoadAddress (lldb::addr_t vm_addr)
{
    lldb::SBAddress sb_addr;
    Address &addr = sb_addr.ref();
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        if (target_sp->ResolveLoadAddress (vm_addr, addr))
            return sb_addr;
    }

    // We have a load address that isn't in a section, just return an address
    // with the offset filled in (the address) and the section set to NULL
    addr.SetRawAddress(vm_addr);
    return sb_addr;
}

lldb::SBAddress
SBTarget::ResolveFileAddress (lldb::addr_t file_addr)
{
    lldb::SBAddress sb_addr;
    Address &addr = sb_addr.ref();
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        if (target_sp->ResolveFileAddress (file_addr, addr))
            return sb_addr;
    }

    addr.SetRawAddress(file_addr);
    return sb_addr;
}

lldb::SBAddress
SBTarget::ResolvePastLoadAddress (uint32_t stop_id, lldb::addr_t vm_addr)
{
    lldb::SBAddress sb_addr;
    Address &addr = sb_addr.ref();
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        if (target_sp->ResolveLoadAddress (vm_addr, addr))
            return sb_addr;
    }
    
    // We have a load address that isn't in a section, just return an address
    // with the offset filled in (the address) and the section set to NULL
    addr.SetRawAddress(vm_addr);
    return sb_addr;
}

SBSymbolContext
SBTarget::ResolveSymbolContextForAddress (const SBAddress& addr,
                                          uint32_t resolve_scope)
{
    SBSymbolContext sc;
    if (addr.IsValid())
    {
        TargetSP target_sp(GetSP());
        if (target_sp)
            target_sp->GetImages().ResolveSymbolContextForAddress (addr.ref(), resolve_scope, sc.ref());
    }
    return sc;
}

size_t
SBTarget::ReadMemory (const SBAddress addr,
                      void *buf,
                      size_t size,
                      lldb::SBError &error)
{
    SBError sb_error;
    size_t bytes_read = 0;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        bytes_read = target_sp->ReadMemory(addr.ref(), false, buf, size, sb_error.ref());
    }
    else
    {
        sb_error.SetErrorString("invalid target");
    }

    return bytes_read;
}

SBBreakpoint
SBTarget::BreakpointCreateByLocation (const char *file,
                                      uint32_t line)
{
    return SBBreakpoint(BreakpointCreateByLocation (SBFileSpec (file, false), line));
}

SBBreakpoint
SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec,
                                      uint32_t line)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBBreakpoint sb_bp;
    TargetSP target_sp(GetSP());
    if (target_sp && line != 0)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());

        const LazyBool check_inlines = eLazyBoolCalculate;
        const LazyBool skip_prologue = eLazyBoolCalculate;
        const bool internal = false;
        const bool hardware = false;
        *sb_bp = target_sp->CreateBreakpoint (NULL, *sb_file_spec, line, check_inlines, skip_prologue, internal, hardware);
    }

    if (log)
    {
        SBStream sstr;
        sb_bp.GetDescription (sstr);
        char path[PATH_MAX];
        sb_file_spec->GetPath (path, sizeof(path));
        log->Printf ("SBTarget(%p)::BreakpointCreateByLocation ( %s:%u ) => SBBreakpoint(%p): %s",
                     static_cast<void*>(target_sp.get()), path, line,
                     static_cast<void*>(sb_bp.get()), sstr.GetData());
    }

    return sb_bp;
}

SBBreakpoint
SBTarget::BreakpointCreateByName (const char *symbol_name,
                                  const char *module_name)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBBreakpoint sb_bp;
    TargetSP target_sp(GetSP());
    if (target_sp.get())
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());

        const bool internal = false;
        const bool hardware = false;
        const LazyBool skip_prologue = eLazyBoolCalculate;
        if (module_name && module_name[0])
        {
            FileSpecList module_spec_list;
            module_spec_list.Append (FileSpec (module_name, false));
            *sb_bp = target_sp->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal, hardware);
        }
        else
        {
            *sb_bp = target_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal, hardware);
        }
    }

    if (log)
        log->Printf ("SBTarget(%p)::BreakpointCreateByName (symbol=\"%s\", module=\"%s\") => SBBreakpoint(%p)",
                     static_cast<void*>(target_sp.get()), symbol_name,
                     module_name, static_cast<void*>(sb_bp.get()));

    return sb_bp;
}

lldb::SBBreakpoint
SBTarget::BreakpointCreateByName (const char *symbol_name, 
                                  const SBFileSpecList &module_list,
                                  const SBFileSpecList &comp_unit_list)
{
    uint32_t name_type_mask = eFunctionNameTypeAuto;
    return BreakpointCreateByName (symbol_name, name_type_mask, module_list, comp_unit_list);
}

lldb::SBBreakpoint
SBTarget::BreakpointCreateByName (const char *symbol_name,
                                  uint32_t name_type_mask,
                                  const SBFileSpecList &module_list,
                                  const SBFileSpecList &comp_unit_list)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBBreakpoint sb_bp;
    TargetSP target_sp(GetSP());
    if (target_sp && symbol_name && symbol_name[0])
    {
        const bool internal = false;
        const bool hardware = false;
        const LazyBool skip_prologue = eLazyBoolCalculate;
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        *sb_bp = target_sp->CreateBreakpoint (module_list.get(), 
                                              comp_unit_list.get(),
                                              symbol_name,
                                              name_type_mask,
                                              skip_prologue,
                                              internal,
                                              hardware);
    }

    if (log)
        log->Printf ("SBTarget(%p)::BreakpointCreateByName (symbol=\"%s\", name_type: %d) => SBBreakpoint(%p)",
                     static_cast<void*>(target_sp.get()), symbol_name,
                     name_type_mask, static_cast<void*>(sb_bp.get()));

    return sb_bp;
}

lldb::SBBreakpoint
SBTarget::BreakpointCreateByNames (const char *symbol_names[],
                                   uint32_t num_names,
                                   uint32_t name_type_mask,
                                   const SBFileSpecList &module_list,
                                   const SBFileSpecList &comp_unit_list)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBBreakpoint sb_bp;
    TargetSP target_sp(GetSP());
    if (target_sp && num_names > 0)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        const bool internal = false;
        const bool hardware = false;
        const LazyBool skip_prologue = eLazyBoolCalculate;
        *sb_bp = target_sp->CreateBreakpoint (module_list.get(), 
                                                comp_unit_list.get(), 
                                                symbol_names,
                                                num_names,
                                                name_type_mask, 
                                                skip_prologue,
                                                internal,
                                                hardware);
    }

    if (log)
    {
        log->Printf ("SBTarget(%p)::BreakpointCreateByName (symbols={",
                     static_cast<void*>(target_sp.get()));
        for (uint32_t i = 0 ; i < num_names; i++)
        {
            char sep;
            if (i < num_names - 1)
                sep = ',';
            else
                sep = '}';
            if (symbol_names[i] != NULL)
                log->Printf ("\"%s\"%c ", symbol_names[i], sep);
            else
                log->Printf ("\"<NULL>\"%c ", sep);
        }
        log->Printf ("name_type: %d) => SBBreakpoint(%p)", name_type_mask,
                     static_cast<void*>(sb_bp.get()));
    }

    return sb_bp;
}

SBBreakpoint
SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
                                   const char *module_name)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBBreakpoint sb_bp;
    TargetSP target_sp(GetSP());
    if (target_sp && symbol_name_regex && symbol_name_regex[0])
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        RegularExpression regexp(symbol_name_regex);
        const bool internal = false;
        const bool hardware = false;
        const LazyBool skip_prologue = eLazyBoolCalculate;

        if (module_name && module_name[0])
        {
            FileSpecList module_spec_list;
            module_spec_list.Append (FileSpec (module_name, false));

            *sb_bp = target_sp->CreateFuncRegexBreakpoint (&module_spec_list, NULL, regexp, skip_prologue, internal, hardware);
        }
        else
        {
            *sb_bp = target_sp->CreateFuncRegexBreakpoint (NULL, NULL, regexp, skip_prologue, internal, hardware);
        }
    }

    if (log)
        log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\", module_name=\"%s\") => SBBreakpoint(%p)",
                     static_cast<void*>(target_sp.get()), symbol_name_regex,
                     module_name, static_cast<void*>(sb_bp.get()));

    return sb_bp;
}

lldb::SBBreakpoint
SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, 
                                   const SBFileSpecList &module_list,
                                   const SBFileSpecList &comp_unit_list)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBBreakpoint sb_bp;
    TargetSP target_sp(GetSP());
    if (target_sp && symbol_name_regex && symbol_name_regex[0])
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        RegularExpression regexp(symbol_name_regex);
        const bool internal = false;
        const bool hardware = false;
        const LazyBool skip_prologue = eLazyBoolCalculate;

        *sb_bp = target_sp->CreateFuncRegexBreakpoint (module_list.get(), comp_unit_list.get(), regexp, skip_prologue, internal, hardware);
    }

    if (log)
        log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\") => SBBreakpoint(%p)",
                     static_cast<void*>(target_sp.get()), symbol_name_regex,
                     static_cast<void*>(sb_bp.get()));

    return sb_bp;
}

SBBreakpoint
SBTarget::BreakpointCreateByAddress (addr_t address)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBBreakpoint sb_bp;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        const bool hardware = false;
        *sb_bp = target_sp->CreateBreakpoint (address, false, hardware);
    }

    if (log)
        log->Printf ("SBTarget(%p)::BreakpointCreateByAddress (address=%" PRIu64 ") => SBBreakpoint(%p)",
                     static_cast<void*>(target_sp.get()),
                     static_cast<uint64_t>(address),
                     static_cast<void*>(sb_bp.get()));

    return sb_bp;
}

lldb::SBBreakpoint
SBTarget::BreakpointCreateBySourceRegex (const char *source_regex,
                                         const lldb::SBFileSpec &source_file,
                                         const char *module_name)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBBreakpoint sb_bp;
    TargetSP target_sp(GetSP());
    if (target_sp && source_regex && source_regex[0])
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        RegularExpression regexp(source_regex);
        FileSpecList source_file_spec_list;
        const bool hardware = false;
        source_file_spec_list.Append (source_file.ref());

        if (module_name && module_name[0])
        {
            FileSpecList module_spec_list;
            module_spec_list.Append (FileSpec (module_name, false));

            *sb_bp = target_sp->CreateSourceRegexBreakpoint (&module_spec_list, &source_file_spec_list, regexp, false, hardware);
        }
        else
        {
            *sb_bp = target_sp->CreateSourceRegexBreakpoint (NULL, &source_file_spec_list, regexp, false, hardware);
        }
    }

    if (log)
    {
        char path[PATH_MAX];
        source_file->GetPath (path, sizeof(path));
        log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (source_regex=\"%s\", file=\"%s\", module_name=\"%s\") => SBBreakpoint(%p)",
                     static_cast<void*>(target_sp.get()), source_regex, path,
                     module_name, static_cast<void*>(sb_bp.get()));
    }

    return sb_bp;
}

lldb::SBBreakpoint
SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, 
                                         const SBFileSpecList &module_list,
                                         const lldb::SBFileSpecList &source_file_list)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBBreakpoint sb_bp;
    TargetSP target_sp(GetSP());
    if (target_sp && source_regex && source_regex[0])
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        const bool hardware = false;
        RegularExpression regexp(source_regex);
        *sb_bp = target_sp->CreateSourceRegexBreakpoint (module_list.get(), source_file_list.get(), regexp, false, hardware);
    }

    if (log)
        log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (source_regex=\"%s\") => SBBreakpoint(%p)",
                     static_cast<void*>(target_sp.get()), source_regex,
                     static_cast<void*>(sb_bp.get()));

    return sb_bp;
}

lldb::SBBreakpoint
SBTarget::BreakpointCreateForException  (lldb::LanguageType language,
                                         bool catch_bp,
                                         bool throw_bp)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBBreakpoint sb_bp;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        const bool hardware = false;
        *sb_bp = target_sp->CreateExceptionBreakpoint (language, catch_bp, throw_bp, hardware);
    }

    if (log)
        log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (Language: %s, catch: %s throw: %s) => SBBreakpoint(%p)",
                     static_cast<void*>(target_sp.get()),
                     LanguageRuntime::GetNameForLanguageType(language),
                     catch_bp ? "on" : "off", throw_bp ? "on" : "off",
                     static_cast<void*>(sb_bp.get()));

    return sb_bp;
}

uint32_t
SBTarget::GetNumBreakpoints () const
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        // The breakpoint list is thread safe, no need to lock
        return target_sp->GetBreakpointList().GetSize();
    }
    return 0;
}

SBBreakpoint
SBTarget::GetBreakpointAtIndex (uint32_t idx) const
{
    SBBreakpoint sb_breakpoint;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        // The breakpoint list is thread safe, no need to lock
        *sb_breakpoint = target_sp->GetBreakpointList().GetBreakpointAtIndex(idx);
    }
    return sb_breakpoint;
}

bool
SBTarget::BreakpointDelete (break_id_t bp_id)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    bool result = false;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        result = target_sp->RemoveBreakpointByID (bp_id);
    }

    if (log)
        log->Printf ("SBTarget(%p)::BreakpointDelete (bp_id=%d) => %i",
                     static_cast<void*>(target_sp.get()),
                     static_cast<uint32_t>(bp_id), result);

    return result;
}

SBBreakpoint
SBTarget::FindBreakpointByID (break_id_t bp_id)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBBreakpoint sb_breakpoint;
    TargetSP target_sp(GetSP());
    if (target_sp && bp_id != LLDB_INVALID_BREAK_ID)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        *sb_breakpoint = target_sp->GetBreakpointByID (bp_id);
    }

    if (log)
        log->Printf ("SBTarget(%p)::FindBreakpointByID (bp_id=%d) => SBBreakpoint(%p)",
                     static_cast<void*>(target_sp.get()),
                     static_cast<uint32_t>(bp_id),
                     static_cast<void*>(sb_breakpoint.get()));

    return sb_breakpoint;
}

bool
SBTarget::EnableAllBreakpoints ()
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        target_sp->EnableAllBreakpoints ();
        return true;
    }
    return false;
}

bool
SBTarget::DisableAllBreakpoints ()
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        target_sp->DisableAllBreakpoints ();
        return true;
    }
    return false;
}

bool
SBTarget::DeleteAllBreakpoints ()
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        target_sp->RemoveAllBreakpoints ();
        return true;
    }
    return false;
}

uint32_t
SBTarget::GetNumWatchpoints () const
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        // The watchpoint list is thread safe, no need to lock
        return target_sp->GetWatchpointList().GetSize();
    }
    return 0;
}

SBWatchpoint
SBTarget::GetWatchpointAtIndex (uint32_t idx) const
{
    SBWatchpoint sb_watchpoint;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        // The watchpoint list is thread safe, no need to lock
        sb_watchpoint.SetSP (target_sp->GetWatchpointList().GetByIndex(idx));
    }
    return sb_watchpoint;
}

bool
SBTarget::DeleteWatchpoint (watch_id_t wp_id)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    bool result = false;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        Mutex::Locker locker;
        target_sp->GetWatchpointList().GetListMutex(locker);
        result = target_sp->RemoveWatchpointByID (wp_id);
    }

    if (log)
        log->Printf ("SBTarget(%p)::WatchpointDelete (wp_id=%d) => %i",
                     static_cast<void*>(target_sp.get()),
                     static_cast<uint32_t>(wp_id), result);

    return result;
}

SBWatchpoint
SBTarget::FindWatchpointByID (lldb::watch_id_t wp_id)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBWatchpoint sb_watchpoint;
    lldb::WatchpointSP watchpoint_sp;
    TargetSP target_sp(GetSP());
    if (target_sp && wp_id != LLDB_INVALID_WATCH_ID)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        Mutex::Locker locker;
        target_sp->GetWatchpointList().GetListMutex(locker);
        watchpoint_sp = target_sp->GetWatchpointList().FindByID(wp_id);
        sb_watchpoint.SetSP (watchpoint_sp);
    }

    if (log)
        log->Printf ("SBTarget(%p)::FindWatchpointByID (bp_id=%d) => SBWatchpoint(%p)",
                     static_cast<void*>(target_sp.get()),
                     static_cast<uint32_t>(wp_id),
                     static_cast<void*>(watchpoint_sp.get()));

    return sb_watchpoint;
}

lldb::SBWatchpoint
SBTarget::WatchAddress (lldb::addr_t addr, size_t size, bool read, bool write, SBError &error)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBWatchpoint sb_watchpoint;
    lldb::WatchpointSP watchpoint_sp;
    TargetSP target_sp(GetSP());
    if (target_sp && (read || write) && addr != LLDB_INVALID_ADDRESS && size > 0)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        uint32_t watch_type = 0;
        if (read)
            watch_type |= LLDB_WATCH_TYPE_READ;
        if (write)
            watch_type |= LLDB_WATCH_TYPE_WRITE;
        if (watch_type == 0)
        {
            error.SetErrorString("Can't create a watchpoint that is neither read nor write.");
            return sb_watchpoint;
        }

        // Target::CreateWatchpoint() is thread safe.
        Error cw_error;
        // This API doesn't take in a type, so we can't figure out what it is.
        ClangASTType *type = NULL;
        watchpoint_sp = target_sp->CreateWatchpoint(addr, size, type, watch_type, cw_error);
        error.SetError(cw_error);
        sb_watchpoint.SetSP (watchpoint_sp);
    }

    if (log)
        log->Printf ("SBTarget(%p)::WatchAddress (addr=0x%" PRIx64 ", 0x%u) => SBWatchpoint(%p)",
                     static_cast<void*>(target_sp.get()), addr,
                     static_cast<uint32_t>(size),
                     static_cast<void*>(watchpoint_sp.get()));

    return sb_watchpoint;
}

bool
SBTarget::EnableAllWatchpoints ()
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        Mutex::Locker locker;
        target_sp->GetWatchpointList().GetListMutex(locker);
        target_sp->EnableAllWatchpoints ();
        return true;
    }
    return false;
}

bool
SBTarget::DisableAllWatchpoints ()
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        Mutex::Locker locker;
        target_sp->GetWatchpointList().GetListMutex(locker);
        target_sp->DisableAllWatchpoints ();
        return true;
    }
    return false;
}

SBValue
SBTarget::CreateValueFromAddress (const char *name, SBAddress addr, SBType type)
{
    SBValue sb_value;
    lldb::ValueObjectSP new_value_sp;
    if (IsValid() && name && *name && addr.IsValid() && type.IsValid())
    {
        lldb::addr_t load_addr(addr.GetLoadAddress(*this));
        ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false)));
        ClangASTType ast_type(type.GetSP()->GetClangASTType(true));
        new_value_sp = ValueObject::CreateValueObjectFromAddress(name, load_addr, exe_ctx, ast_type);
    }
    sb_value.SetSP(new_value_sp);
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
    {
        if (new_value_sp)
            log->Printf ("SBTarget(%p)::CreateValueFromAddress => \"%s\"",
                         static_cast<void*>(m_opaque_sp.get()),
                         new_value_sp->GetName().AsCString());
        else
            log->Printf ("SBTarget(%p)::CreateValueFromAddress => NULL",
                         static_cast<void*>(m_opaque_sp.get()));
    }
    return sb_value;
}

lldb::SBValue
SBTarget::CreateValueFromData (const char *name, lldb::SBData data, lldb::SBType type)
{
    SBValue sb_value;
    lldb::ValueObjectSP new_value_sp;
    if (IsValid() && name && *name && data.IsValid() && type.IsValid())
    {
        DataExtractorSP extractor(*data);
        ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false)));
        ClangASTType ast_type(type.GetSP()->GetClangASTType(true));
        new_value_sp = ValueObject::CreateValueObjectFromData(name, *extractor, exe_ctx, ast_type);
    }
    sb_value.SetSP(new_value_sp);
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
    {
        if (new_value_sp)
            log->Printf ("SBTarget(%p)::CreateValueFromData => \"%s\"",
                         static_cast<void*>(m_opaque_sp.get()),
                         new_value_sp->GetName().AsCString());
        else
            log->Printf ("SBTarget(%p)::CreateValueFromData => NULL",
                         static_cast<void*>(m_opaque_sp.get()));
    }
    return sb_value;
}

lldb::SBValue
SBTarget::CreateValueFromExpression (const char *name, const char* expr)
{
    SBValue sb_value;
    lldb::ValueObjectSP new_value_sp;
    if (IsValid() && name && *name && expr && *expr)
    {
        ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false)));
        new_value_sp = ValueObject::CreateValueObjectFromExpression(name, expr, exe_ctx);
    }
    sb_value.SetSP(new_value_sp);
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
    {
        if (new_value_sp)
            log->Printf ("SBTarget(%p)::CreateValueFromExpression => \"%s\"",
                         static_cast<void*>(m_opaque_sp.get()),
                         new_value_sp->GetName().AsCString());
        else
            log->Printf ("SBTarget(%p)::CreateValueFromExpression => NULL",
                         static_cast<void*>(m_opaque_sp.get()));
    }
    return sb_value;
}

bool
SBTarget::DeleteAllWatchpoints ()
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        Mutex::Locker locker;
        target_sp->GetWatchpointList().GetListMutex(locker);
        target_sp->RemoveAllWatchpoints ();
        return true;
    }
    return false;
}


lldb::SBModule
SBTarget::AddModule (const char *path,
                     const char *triple,
                     const char *uuid_cstr)
{
    return AddModule (path, triple, uuid_cstr, NULL);
}

lldb::SBModule
SBTarget::AddModule (const char *path,
                     const char *triple,
                     const char *uuid_cstr,
                     const char *symfile)
{
    lldb::SBModule sb_module;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        ModuleSpec module_spec;
        if (path)
            module_spec.GetFileSpec().SetFile(path, false);
        
        if (uuid_cstr)
            module_spec.GetUUID().SetFromCString(uuid_cstr);
        
        if (triple)
            module_spec.GetArchitecture().SetTriple (triple, target_sp->GetPlatform ().get());
        else
            module_spec.GetArchitecture() = target_sp->GetArchitecture();
        
        if (symfile)
            module_spec.GetSymbolFileSpec ().SetFile(symfile, false);

        sb_module.SetSP(target_sp->GetSharedModule (module_spec));
    }
    return sb_module;
}

lldb::SBModule
SBTarget::AddModule (const SBModuleSpec &module_spec)
{
    lldb::SBModule sb_module;
    TargetSP target_sp(GetSP());
    if (target_sp)
        sb_module.SetSP(target_sp->GetSharedModule (*module_spec.m_opaque_ap));
    return sb_module;
}

bool
SBTarget::AddModule (lldb::SBModule &module)
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        target_sp->GetImages().AppendIfNeeded (module.GetSP());
        return true;
    }
    return false;
}

uint32_t
SBTarget::GetNumModules () const
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    uint32_t num = 0;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        // The module list is thread safe, no need to lock
        num = target_sp->GetImages().GetSize();
    }

    if (log)
        log->Printf ("SBTarget(%p)::GetNumModules () => %d",
                     static_cast<void*>(target_sp.get()), num);

    return num;
}

void
SBTarget::Clear ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBTarget(%p)::Clear ()",
                     static_cast<void*>(m_opaque_sp.get()));

    m_opaque_sp.reset();
}


SBModule
SBTarget::FindModule (const SBFileSpec &sb_file_spec)
{
    SBModule sb_module;
    TargetSP target_sp(GetSP());
    if (target_sp && sb_file_spec.IsValid())
    {
        ModuleSpec module_spec(*sb_file_spec);
        // The module list is thread safe, no need to lock
        sb_module.SetSP (target_sp->GetImages().FindFirstModule (module_spec));
    }
    return sb_module;
}

lldb::ByteOrder
SBTarget::GetByteOrder ()
{
    TargetSP target_sp(GetSP());
    if (target_sp)
        return target_sp->GetArchitecture().GetByteOrder();
    return eByteOrderInvalid;
}

const char *
SBTarget::GetTriple ()
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        std::string triple (target_sp->GetArchitecture().GetTriple().str());
        // Unique the string so we don't run into ownership issues since
        // the const strings put the string into the string pool once and
        // the strings never comes out
        ConstString const_triple (triple.c_str());
        return const_triple.GetCString();
    }
    return NULL;
}

uint32_t
SBTarget::GetDataByteSize ()
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        return target_sp->GetArchitecture().GetDataByteSize() ;
    }
    return 0;
}

uint32_t
SBTarget::GetCodeByteSize ()
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        return target_sp->GetArchitecture().GetCodeByteSize() ;
    }
    return 0;
}

uint32_t
SBTarget::GetAddressByteSize()
{
    TargetSP target_sp(GetSP());
    if (target_sp)
        return target_sp->GetArchitecture().GetAddressByteSize();
    return sizeof(void*);
}


SBModule
SBTarget::GetModuleAtIndex (uint32_t idx)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBModule sb_module;
    ModuleSP module_sp;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        // The module list is thread safe, no need to lock
        module_sp = target_sp->GetImages().GetModuleAtIndex(idx);
        sb_module.SetSP (module_sp);
    }

    if (log)
        log->Printf ("SBTarget(%p)::GetModuleAtIndex (idx=%d) => SBModule(%p)",
                     static_cast<void*>(target_sp.get()), idx,
                     static_cast<void*>(module_sp.get()));

    return sb_module;
}

bool
SBTarget::RemoveModule (lldb::SBModule module)
{
    TargetSP target_sp(GetSP());
    if (target_sp)
        return target_sp->GetImages().Remove(module.GetSP());
    return false;
}


SBBroadcaster
SBTarget::GetBroadcaster () const
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    TargetSP target_sp(GetSP());
    SBBroadcaster broadcaster(target_sp.get(), false);

    if (log)
        log->Printf ("SBTarget(%p)::GetBroadcaster () => SBBroadcaster(%p)",
                     static_cast<void*>(target_sp.get()),
                     static_cast<void*>(broadcaster.get()));

    return broadcaster;
}

bool
SBTarget::GetDescription (SBStream &description, lldb::DescriptionLevel description_level)
{
    Stream &strm = description.ref();

    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        target_sp->Dump (&strm, description_level);
    }
    else
        strm.PutCString ("No value");
    
    return true;
}

lldb::SBSymbolContextList
SBTarget::FindFunctions (const char *name, uint32_t name_type_mask)
{
    lldb::SBSymbolContextList sb_sc_list;
    if (name && name[0])
    {
        TargetSP target_sp(GetSP());
        if (target_sp)
        {
            const bool symbols_ok = true;
            const bool inlines_ok = true;
            const bool append = true;
            target_sp->GetImages().FindFunctions (ConstString(name), 
                                                  name_type_mask, 
                                                  symbols_ok,
                                                  inlines_ok,
                                                  append, 
                                                  *sb_sc_list);
        }
    }
    return sb_sc_list;
}

lldb::SBSymbolContextList 
SBTarget::FindGlobalFunctions(const char *name, uint32_t max_matches, MatchType matchtype)
{
    lldb::SBSymbolContextList sb_sc_list;
    if (name && name[0])
    {
        TargetSP target_sp(GetSP());
        if (target_sp)
        {
            std::string regexstr;
            switch (matchtype)
            {
            case eMatchTypeRegex:
                target_sp->GetImages().FindFunctions(RegularExpression(name), true, true, true, *sb_sc_list);
                break;
            case eMatchTypeStartsWith:
                regexstr = llvm::Regex::escape(name) + ".*";
                target_sp->GetImages().FindFunctions(RegularExpression(regexstr.c_str()), true, true, true, *sb_sc_list);
                break;
            default:
                target_sp->GetImages().FindFunctions(ConstString(name), eFunctionNameTypeAny, true, true, true, *sb_sc_list);
                break;
            }
        }
    }
    return sb_sc_list;
}

lldb::SBType
SBTarget::FindFirstType (const char* typename_cstr)
{
    TargetSP target_sp(GetSP());
    if (typename_cstr && typename_cstr[0] && target_sp)
    {
        ConstString const_typename(typename_cstr);
        SymbolContext sc;
        const bool exact_match = false;

        const ModuleList &module_list = target_sp->GetImages();
        size_t count = module_list.GetSize();
        for (size_t idx = 0; idx < count; idx++)
        {
            ModuleSP module_sp (module_list.GetModuleAtIndex(idx));
            if (module_sp)
            {
                TypeSP type_sp (module_sp->FindFirstType(sc, const_typename, exact_match));
                if (type_sp)
                    return SBType(type_sp);
            }
        }
        
        // Didn't find the type in the symbols; try the Objective-C runtime
        // if one is installed
        
        ProcessSP process_sp(target_sp->GetProcessSP());
        
        if (process_sp)
        {
            ObjCLanguageRuntime *objc_language_runtime = process_sp->GetObjCLanguageRuntime();
            
            if (objc_language_runtime)
            {
                DeclVendor *objc_decl_vendor = objc_language_runtime->GetDeclVendor();
                
                if (objc_decl_vendor)
                {
                    std::vector <clang::NamedDecl *> decls;
                    
                    if (objc_decl_vendor->FindDecls(const_typename, true, 1, decls) > 0)
                    {
                        if (ClangASTType type = ClangASTContext::GetTypeForDecl(decls[0]))
                        {
                            return SBType(type);
                        }
                    }
                }
            }
        }

        // No matches, search for basic typename matches
        ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext();
        if (clang_ast)
            return SBType (ClangASTContext::GetBasicType (clang_ast->getASTContext(), const_typename));
    }
    return SBType();
}

SBType
SBTarget::GetBasicType(lldb::BasicType type)
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext();
        if (clang_ast)
            return SBType (ClangASTContext::GetBasicType (clang_ast->getASTContext(), type));
    }
    return SBType();
}


lldb::SBTypeList
SBTarget::FindTypes (const char* typename_cstr)
{
    SBTypeList sb_type_list;
    TargetSP target_sp(GetSP());
    if (typename_cstr && typename_cstr[0] && target_sp)
    {
        ModuleList& images = target_sp->GetImages();
        ConstString const_typename(typename_cstr);
        bool exact_match = false;
        SymbolContext sc;
        TypeList type_list;
        
        uint32_t num_matches = images.FindTypes (sc,
                                                 const_typename,
                                                 exact_match,
                                                 UINT32_MAX,
                                                 type_list);
        
        if (num_matches > 0)
        {
            for (size_t idx = 0; idx < num_matches; idx++)
            {
                TypeSP type_sp (type_list.GetTypeAtIndex(idx));
                if (type_sp)
                    sb_type_list.Append(SBType(type_sp));
            }
        }
        
        // Try the Objective-C runtime if one is installed
        
        ProcessSP process_sp(target_sp->GetProcessSP());
        
        if (process_sp)
        {
            ObjCLanguageRuntime *objc_language_runtime = process_sp->GetObjCLanguageRuntime();
            
            if (objc_language_runtime)
            {
                DeclVendor *objc_decl_vendor = objc_language_runtime->GetDeclVendor();
                
                if (objc_decl_vendor)
                {
                    std::vector <clang::NamedDecl *> decls;
                    
                    if (objc_decl_vendor->FindDecls(const_typename, true, 1, decls) > 0)
                    {
                        for (clang::NamedDecl *decl : decls)
                        {
                            if (ClangASTType type = ClangASTContext::GetTypeForDecl(decl))
                            {
                                sb_type_list.Append(SBType(type));
                            }
                        }
                    }
                }
            }
        }
        
        if (sb_type_list.GetSize() == 0)
        {
            // No matches, search for basic typename matches
            ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext();
            if (clang_ast)
                sb_type_list.Append (SBType (ClangASTContext::GetBasicType (clang_ast->getASTContext(), const_typename)));
        }
    }
    return sb_type_list;
}

SBValueList
SBTarget::FindGlobalVariables (const char *name, uint32_t max_matches)
{
    SBValueList sb_value_list;
    
    TargetSP target_sp(GetSP());
    if (name && target_sp)
    {
        VariableList variable_list;
        const bool append = true;
        const uint32_t match_count = target_sp->GetImages().FindGlobalVariables (ConstString (name), 
                                                                                 append, 
                                                                                 max_matches,
                                                                                 variable_list);
        
        if (match_count > 0)
        {
            ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get();
            if (exe_scope == NULL)
                exe_scope = target_sp.get();
            for (uint32_t i=0; i<match_count; ++i)
            {
                lldb::ValueObjectSP valobj_sp (ValueObjectVariable::Create (exe_scope, variable_list.GetVariableAtIndex(i)));
                if (valobj_sp)
                    sb_value_list.Append(SBValue(valobj_sp));
            }
        }
    }

    return sb_value_list;
}

SBValueList
SBTarget::FindGlobalVariables(const char *name, uint32_t max_matches, MatchType matchtype)
{
    SBValueList sb_value_list;

    TargetSP target_sp(GetSP());
    if (name && target_sp)
    {
        VariableList variable_list;
        const bool append = true;

        std::string regexstr;
        uint32_t match_count;
        switch (matchtype)
        {
        case eMatchTypeNormal:
            match_count = target_sp->GetImages().FindGlobalVariables(ConstString(name),
                append,
                max_matches,
                variable_list);
            break;
        case eMatchTypeRegex:
            match_count = target_sp->GetImages().FindGlobalVariables(RegularExpression(name),
                append,
                max_matches,
                variable_list);
            break;
        case eMatchTypeStartsWith:
            regexstr = llvm::Regex::escape(name) + ".*";
            match_count = target_sp->GetImages().FindGlobalVariables(RegularExpression(regexstr.c_str()),
                append,
                max_matches,
                variable_list);
            break;
        }


        if (match_count > 0)
        {
            ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get();
            if (exe_scope == NULL)
                exe_scope = target_sp.get();
            for (uint32_t i = 0; i<match_count; ++i)
            {
                lldb::ValueObjectSP valobj_sp(ValueObjectVariable::Create(exe_scope, variable_list.GetVariableAtIndex(i)));
                if (valobj_sp)
                    sb_value_list.Append(SBValue(valobj_sp));
            }
        }
    }

    return sb_value_list;
}


lldb::SBValue
SBTarget::FindFirstGlobalVariable (const char* name)
{
    SBValueList sb_value_list(FindGlobalVariables(name, 1));
    if (sb_value_list.IsValid() && sb_value_list.GetSize() > 0)
        return sb_value_list.GetValueAtIndex(0);
    return SBValue();
}

SBSourceManager
SBTarget::GetSourceManager()
{
    SBSourceManager source_manager (*this);
    return source_manager;
}

lldb::SBInstructionList
SBTarget::ReadInstructions (lldb::SBAddress base_addr, uint32_t count)
{
    return ReadInstructions (base_addr, count, NULL);
}

lldb::SBInstructionList
SBTarget::ReadInstructions (lldb::SBAddress base_addr, uint32_t count, const char *flavor_string)
{
    SBInstructionList sb_instructions;
    
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Address *addr_ptr = base_addr.get();
        
        if (addr_ptr)
        {
            DataBufferHeap data (target_sp->GetArchitecture().GetMaximumOpcodeByteSize() * count, 0);
            bool prefer_file_cache = false;
            lldb_private::Error error;
            lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
            const size_t bytes_read = target_sp->ReadMemory(*addr_ptr,
                                                            prefer_file_cache,
                                                            data.GetBytes(),
                                                            data.GetByteSize(),
                                                            error,
                                                            &load_addr);
            const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
            sb_instructions.SetDisassembler (Disassembler::DisassembleBytes (target_sp->GetArchitecture(),
                                                                             NULL,
                                                                             flavor_string,
                                                                             *addr_ptr,
                                                                             data.GetBytes(),
                                                                             bytes_read,
                                                                             count,
                                                                             data_from_file));
        }
    }
    
    return sb_instructions;
    
}

lldb::SBInstructionList
SBTarget::GetInstructions (lldb::SBAddress base_addr, const void *buf, size_t size)
{
    return GetInstructionsWithFlavor (base_addr, NULL, buf, size);
}

lldb::SBInstructionList
SBTarget::GetInstructionsWithFlavor (lldb::SBAddress base_addr, const char *flavor_string, const void *buf, size_t size)
{
    SBInstructionList sb_instructions;
    
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        Address addr;
        
        if (base_addr.get())
            addr = *base_addr.get();
        
        const bool data_from_file = true;

        sb_instructions.SetDisassembler (Disassembler::DisassembleBytes (target_sp->GetArchitecture(),
                                                                         NULL,
                                                                         flavor_string,
                                                                         addr,
                                                                         buf,
                                                                         size,
                                                                         UINT32_MAX,
                                                                         data_from_file));
    }

    return sb_instructions;
}

lldb::SBInstructionList
SBTarget::GetInstructions (lldb::addr_t base_addr, const void *buf, size_t size)
{
    return GetInstructionsWithFlavor (ResolveLoadAddress(base_addr), NULL, buf, size);
}

lldb::SBInstructionList
SBTarget::GetInstructionsWithFlavor (lldb::addr_t base_addr, const char *flavor_string, const void *buf, size_t size)
{
    return GetInstructionsWithFlavor (ResolveLoadAddress(base_addr), flavor_string, buf, size);
}

SBError
SBTarget::SetSectionLoadAddress (lldb::SBSection section,
                                 lldb::addr_t section_base_addr)
{
    SBError sb_error;
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        if (!section.IsValid())
        {
            sb_error.SetErrorStringWithFormat ("invalid section");
        }
        else
        {
            SectionSP section_sp (section.GetSP());
            if (section_sp)
            {
                if (section_sp->IsThreadSpecific())
                {
                    sb_error.SetErrorString ("thread specific sections are not yet supported");
                }
                else
                {
                    ProcessSP process_sp (target_sp->GetProcessSP());
                    if (target_sp->SetSectionLoadAddress (section_sp, section_base_addr))
                    {
                        // Flush info in the process (stack frames, etc)
                        if (process_sp)
                            process_sp->Flush();
                    }
                }
            }
        }
    }
    else
    {
        sb_error.SetErrorString ("invalid target");
    }
    return sb_error;
}

SBError
SBTarget::ClearSectionLoadAddress (lldb::SBSection section)
{
    SBError sb_error;
    
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        if (!section.IsValid())
        {
            sb_error.SetErrorStringWithFormat ("invalid section");
        }
        else
        {
            ProcessSP process_sp (target_sp->GetProcessSP());
            if (target_sp->SetSectionUnloaded (section.GetSP()))
            {
                // Flush info in the process (stack frames, etc)
                if (process_sp)
                    process_sp->Flush();                
            }
        }
    }
    else
    {
        sb_error.SetErrorStringWithFormat ("invalid target");
    }
    return sb_error;
}

SBError
SBTarget::SetModuleLoadAddress (lldb::SBModule module, int64_t slide_offset)
{
    SBError sb_error;
    
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        ModuleSP module_sp (module.GetSP());
        if (module_sp)
        {
            bool changed = false;
            if (module_sp->SetLoadAddress (*target_sp, slide_offset, true, changed))
            {
                // The load was successful, make sure that at least some sections
                // changed before we notify that our module was loaded.
                if (changed)
                {
                    ModuleList module_list;
                    module_list.Append(module_sp);
                    target_sp->ModulesDidLoad (module_list);
                    // Flush info in the process (stack frames, etc)
                    ProcessSP process_sp (target_sp->GetProcessSP());
                    if (process_sp)
                        process_sp->Flush();
                }
            }
        }
        else
        {
            sb_error.SetErrorStringWithFormat ("invalid module");
        }

    }
    else
    {
        sb_error.SetErrorStringWithFormat ("invalid target");
    }
    return sb_error;
}

SBError
SBTarget::ClearModuleLoadAddress (lldb::SBModule module)
{
    SBError sb_error;
    
    char path[PATH_MAX];
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        ModuleSP module_sp (module.GetSP());
        if (module_sp)
        {
            ObjectFile *objfile = module_sp->GetObjectFile();
            if (objfile)
            {
                SectionList *section_list = objfile->GetSectionList();
                if (section_list)
                {
                    ProcessSP process_sp (target_sp->GetProcessSP());

                    bool changed = false;
                    const size_t num_sections = section_list->GetSize();
                    for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx)
                    {
                        SectionSP section_sp (section_list->GetSectionAtIndex(sect_idx));
                        if (section_sp)
                            changed |= target_sp->SetSectionUnloaded (section_sp);
                    }
                    if (changed)
                    {
                        // Flush info in the process (stack frames, etc)
                        ProcessSP process_sp (target_sp->GetProcessSP());
                        if (process_sp)
                            process_sp->Flush();                        
                    }
                }
                else
                {
                    module_sp->GetFileSpec().GetPath (path, sizeof(path));
                    sb_error.SetErrorStringWithFormat ("no sections in object file '%s'", path);
                }
            }
            else
            {
                module_sp->GetFileSpec().GetPath (path, sizeof(path));
                sb_error.SetErrorStringWithFormat ("no object file for module '%s'", path);
            }
        }
        else
        {
            sb_error.SetErrorStringWithFormat ("invalid module");
        }
    }
    else
    {
        sb_error.SetErrorStringWithFormat ("invalid target");
    }
    return sb_error;
}


lldb::SBSymbolContextList
SBTarget::FindSymbols (const char *name, lldb::SymbolType symbol_type)
{
    SBSymbolContextList sb_sc_list;
    if (name && name[0])
    {
        TargetSP target_sp(GetSP());
        if (target_sp)
        {
            bool append = true;
            target_sp->GetImages().FindSymbolsWithNameAndType (ConstString(name),
                                                               symbol_type,
                                                               *sb_sc_list,
                                                               append);
        }
    }
    return sb_sc_list;
    
}


lldb::SBValue
SBTarget::EvaluateExpression (const char *expr, const SBExpressionOptions &options)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    Log * expr_log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
    SBValue expr_result;
    ExpressionResults exe_results = eExpressionSetupError;
    ValueObjectSP expr_value_sp;
    TargetSP target_sp(GetSP());
    StackFrame *frame = NULL;
    if (target_sp)
    {
        if (expr == NULL || expr[0] == '\0')
        {
            if (log)
                log->Printf ("SBTarget::EvaluateExpression called with an empty expression");
            return expr_result;
        }

        Mutex::Locker api_locker (target_sp->GetAPIMutex());
        ExecutionContext exe_ctx (m_opaque_sp.get());

        if (log)
            log->Printf ("SBTarget()::EvaluateExpression (expr=\"%s\")...", expr);

        frame = exe_ctx.GetFramePtr();
        Target *target = exe_ctx.GetTargetPtr();

        if (target)
        {
#ifdef LLDB_CONFIGURATION_DEBUG
            StreamString frame_description;
            if (frame)
                frame->DumpUsingSettingsFormat (&frame_description);
            Host::SetCrashDescriptionWithFormat ("SBTarget::EvaluateExpression (expr = \"%s\", fetch_dynamic_value = %u) %s",
                                                 expr, options.GetFetchDynamicValue(), frame_description.GetString().c_str());
#endif
            exe_results = target->EvaluateExpression (expr,
                                                      frame,
                                                      expr_value_sp,
                                                      options.ref());

            expr_result.SetSP(expr_value_sp, options.GetFetchDynamicValue());
#ifdef LLDB_CONFIGURATION_DEBUG
            Host::SetCrashDescription (NULL);
#endif
        }
        else
        {
            if (log)
                log->Printf ("SBTarget::EvaluateExpression () => error: could not reconstruct frame object for this SBTarget.");
        }
    }
#ifndef LLDB_DISABLE_PYTHON
    if (expr_log)
        expr_log->Printf("** [SBTarget::EvaluateExpression] Expression result is %s, summary %s **",
                         expr_result.GetValue(), expr_result.GetSummary());

    if (log)
        log->Printf ("SBTarget(%p)::EvaluateExpression (expr=\"%s\") => SBValue(%p) (execution result=%d)",
                     static_cast<void*>(frame), expr,
                     static_cast<void*>(expr_value_sp.get()), exe_results);
#endif

    return expr_result;
}


lldb::addr_t
SBTarget::GetStackRedZoneSize()
{
    TargetSP target_sp(GetSP());
    if (target_sp)
    {
        ABISP abi_sp;
        ProcessSP process_sp (target_sp->GetProcessSP());
        if (process_sp)
            abi_sp = process_sp->GetABI();
        else
            abi_sp = ABI::FindPlugin(target_sp->GetArchitecture());
        if (abi_sp)
            return abi_sp->GetRedZoneSize();
    }
    return 0;
}

