//===-- Process.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/Target/Process.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Event.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Expression/ClangUserExpression.h"
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Pipe.h"
#include "lldb/Host/Terminal.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/InstrumentationRuntime.h"
#include "lldb/Target/JITLoader.h"
#include "lldb/Target/JITLoaderList.h"
#include "lldb/Target/MemoryHistory.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/OperatingSystem.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanBase.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/NameMatches.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"

using namespace lldb;
using namespace lldb_private;


// Comment out line below to disable memory caching, overriding the process setting
// target.process.disable-memory-cache
#define ENABLE_MEMORY_CACHING

#ifdef ENABLE_MEMORY_CACHING
#define DISABLE_MEM_CACHE_DEFAULT false
#else
#define DISABLE_MEM_CACHE_DEFAULT true
#endif

class ProcessOptionValueProperties : public OptionValueProperties
{
public:
    ProcessOptionValueProperties (const ConstString &name) :
        OptionValueProperties (name)
    {
    }
    
    // This constructor is used when creating ProcessOptionValueProperties when it
    // is part of a new lldb_private::Process instance. It will copy all current
    // global property values as needed
    ProcessOptionValueProperties (ProcessProperties *global_properties) :
        OptionValueProperties(*global_properties->GetValueProperties())
    {
    }
    
    virtual const Property *
    GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
    {
        // When getting the value for a key from the process options, we will always
        // try and grab the setting from the current process if there is one. Else we just
        // use the one from this instance.
        if (exe_ctx)
        {
            Process *process = exe_ctx->GetProcessPtr();
            if (process)
            {
                ProcessOptionValueProperties *instance_properties = static_cast<ProcessOptionValueProperties *>(process->GetValueProperties().get());
                if (this != instance_properties)
                    return instance_properties->ProtectedGetPropertyAtIndex (idx);
            }
        }
        return ProtectedGetPropertyAtIndex (idx);
    }
};

static PropertyDefinition
g_properties[] =
{
    { "disable-memory-cache" , OptionValue::eTypeBoolean, false, DISABLE_MEM_CACHE_DEFAULT, NULL, NULL, "Disable reading and caching of memory in fixed-size units." },
    { "extra-startup-command", OptionValue::eTypeArray  , false, OptionValue::eTypeString, NULL, NULL, "A list containing extra commands understood by the particular process plugin used.  "
                                                                                                       "For instance, to turn on debugserver logging set this to \"QSetLogging:bitmask=LOG_DEFAULT;\"" },
    { "ignore-breakpoints-in-expressions", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, breakpoints will be ignored during expression evaluation." },
    { "unwind-on-error-in-expressions", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, errors in expression evaluation will unwind the stack back to the state before the call." },
    { "python-os-plugin-path", OptionValue::eTypeFileSpec, false, true, NULL, NULL, "A path to a python OS plug-in module file that contains a OperatingSystemPlugIn class." },
    { "stop-on-sharedlibrary-events" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, stop when a shared library is loaded or unloaded." },
    { "detach-keeps-stopped" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, detach will attempt to keep the process stopped." },
    { "memory-cache-line-size" , OptionValue::eTypeUInt64, false, 512, NULL, NULL, "The memory cache line size" },
    {  NULL                  , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL  }
};

enum {
    ePropertyDisableMemCache,
    ePropertyExtraStartCommand,
    ePropertyIgnoreBreakpointsInExpressions,
    ePropertyUnwindOnErrorInExpressions,
    ePropertyPythonOSPluginPath,
    ePropertyStopOnSharedLibraryEvents,
    ePropertyDetachKeepsStopped,
    ePropertyMemCacheLineSize
};

ProcessProperties::ProcessProperties (lldb_private::Process *process) :
    Properties (),
    m_process (process) // Can be NULL for global ProcessProperties
{
    if (process == NULL)
    {
        // Global process properties, set them up one time
        m_collection_sp.reset (new ProcessOptionValueProperties(ConstString("process")));
        m_collection_sp->Initialize(g_properties);
        m_collection_sp->AppendProperty(ConstString("thread"),
                                        ConstString("Settings specific to threads."),
                                        true,
                                        Thread::GetGlobalProperties()->GetValueProperties());
    }
    else
    {
        m_collection_sp.reset (new ProcessOptionValueProperties(Process::GetGlobalProperties().get()));
        m_collection_sp->SetValueChangedCallback(ePropertyPythonOSPluginPath, ProcessProperties::OptionValueChangedCallback, this);
    }
}

ProcessProperties::~ProcessProperties()
{
}

void
ProcessProperties::OptionValueChangedCallback (void *baton, OptionValue *option_value)
{
    ProcessProperties *properties = (ProcessProperties *)baton;
    if (properties->m_process)
        properties->m_process->LoadOperatingSystemPlugin(true);
}

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

uint64_t
ProcessProperties::GetMemoryCacheLineSize() const
{
    const uint32_t idx = ePropertyMemCacheLineSize;
    return m_collection_sp->GetPropertyAtIndexAsUInt64 (NULL, idx, g_properties[idx].default_uint_value);
}

Args
ProcessProperties::GetExtraStartupCommands () const
{
    Args args;
    const uint32_t idx = ePropertyExtraStartCommand;
    m_collection_sp->GetPropertyAtIndexAsArgs(NULL, idx, args);
    return args;
}

void
ProcessProperties::SetExtraStartupCommands (const Args &args)
{
    const uint32_t idx = ePropertyExtraStartCommand;
    m_collection_sp->SetPropertyAtIndexFromArgs(NULL, idx, args);
}

FileSpec
ProcessProperties::GetPythonOSPluginPath () const
{
    const uint32_t idx = ePropertyPythonOSPluginPath;
    return m_collection_sp->GetPropertyAtIndexAsFileSpec(NULL, idx);
}

void
ProcessProperties::SetPythonOSPluginPath (const FileSpec &file)
{
    const uint32_t idx = ePropertyPythonOSPluginPath;
    m_collection_sp->SetPropertyAtIndexAsFileSpec(NULL, idx, file);
}


bool
ProcessProperties::GetIgnoreBreakpointsInExpressions () const
{
    const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions;
    return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0);
}
    
void
ProcessProperties::SetIgnoreBreakpointsInExpressions (bool ignore)
{
    const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions;
    m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, ignore);
}

bool
ProcessProperties::GetUnwindOnErrorInExpressions () const
{
    const uint32_t idx = ePropertyUnwindOnErrorInExpressions;
    return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0);
}
    
void
ProcessProperties::SetUnwindOnErrorInExpressions (bool ignore)
{
    const uint32_t idx = ePropertyUnwindOnErrorInExpressions;
    m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, ignore);
}

bool
ProcessProperties::GetStopOnSharedLibraryEvents () const
{
    const uint32_t idx = ePropertyStopOnSharedLibraryEvents;
    return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0);
}
    
void
ProcessProperties::SetStopOnSharedLibraryEvents (bool stop)
{
    const uint32_t idx = ePropertyStopOnSharedLibraryEvents;
    m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, stop);
}

bool
ProcessProperties::GetDetachKeepsStopped () const
{
    const uint32_t idx = ePropertyDetachKeepsStopped;
    return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0);
}
    
void
ProcessProperties::SetDetachKeepsStopped (bool stop)
{
    const uint32_t idx = ePropertyDetachKeepsStopped;
    m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, stop);
}

void
ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const
{
    const char *cstr;
    if (m_pid != LLDB_INVALID_PROCESS_ID)       
        s.Printf ("    pid = %" PRIu64 "\n", m_pid);

    if (m_parent_pid != LLDB_INVALID_PROCESS_ID)
        s.Printf (" parent = %" PRIu64 "\n", m_parent_pid);

    if (m_executable)
    {
        s.Printf ("   name = %s\n", m_executable.GetFilename().GetCString());
        s.PutCString ("   file = ");
        m_executable.Dump(&s);
        s.EOL();
    }
    const uint32_t argc = m_arguments.GetArgumentCount();
    if (argc > 0)
    {
        for (uint32_t i=0; i<argc; i++)
        {
            const char *arg = m_arguments.GetArgumentAtIndex(i);
            if (i < 10)
                s.Printf (" arg[%u] = %s\n", i, arg);
            else
                s.Printf ("arg[%u] = %s\n", i, arg);
        }
    }

    const uint32_t envc = m_environment.GetArgumentCount();
    if (envc > 0)
    {
        for (uint32_t i=0; i<envc; i++)
        {
            const char *env = m_environment.GetArgumentAtIndex(i);
            if (i < 10)
                s.Printf (" env[%u] = %s\n", i, env);
            else
                s.Printf ("env[%u] = %s\n", i, env);
        }
    }

    if (m_arch.IsValid())                       
        s.Printf ("   arch = %s\n", m_arch.GetTriple().str().c_str());

    if (m_uid != UINT32_MAX)
    {
        cstr = platform->GetUserName (m_uid);
        s.Printf ("    uid = %-5u (%s)\n", m_uid, cstr ? cstr : "");
    }
    if (m_gid != UINT32_MAX)
    {
        cstr = platform->GetGroupName (m_gid);
        s.Printf ("    gid = %-5u (%s)\n", m_gid, cstr ? cstr : "");
    }
    if (m_euid != UINT32_MAX)
    {
        cstr = platform->GetUserName (m_euid);
        s.Printf ("   euid = %-5u (%s)\n", m_euid, cstr ? cstr : "");
    }
    if (m_egid != UINT32_MAX)
    {
        cstr = platform->GetGroupName (m_egid);
        s.Printf ("   egid = %-5u (%s)\n", m_egid, cstr ? cstr : "");
    }
}

void
ProcessInstanceInfo::DumpTableHeader (Stream &s, Platform *platform, bool show_args, bool verbose)
{
    const char *label;
    if (show_args || verbose)
        label = "ARGUMENTS";
    else
        label = "NAME";

    if (verbose)
    {
        s.Printf     ("PID    PARENT USER       GROUP      EFF USER   EFF GROUP  TRIPLE                   %s\n", label);
        s.PutCString ("====== ====== ========== ========== ========== ========== ======================== ============================\n");
    }
    else
    {
        s.Printf     ("PID    PARENT USER       TRIPLE                   %s\n", label);
        s.PutCString ("====== ====== ========== ======================== ============================\n");
    }
}

void
ProcessInstanceInfo::DumpAsTableRow (Stream &s, Platform *platform, bool show_args, bool verbose) const
{
    if (m_pid != LLDB_INVALID_PROCESS_ID)
    {
        const char *cstr;
        s.Printf ("%-6" PRIu64 " %-6" PRIu64 " ", m_pid, m_parent_pid);

    
        if (verbose)
        {
            cstr = platform->GetUserName (m_uid);
            if (cstr && cstr[0]) // Watch for empty string that indicates lookup failed
                s.Printf ("%-10s ", cstr);
            else
                s.Printf ("%-10u ", m_uid);

            cstr = platform->GetGroupName (m_gid);
            if (cstr && cstr[0]) // Watch for empty string that indicates lookup failed
                s.Printf ("%-10s ", cstr);
            else
                s.Printf ("%-10u ", m_gid);

            cstr = platform->GetUserName (m_euid);
            if (cstr && cstr[0]) // Watch for empty string that indicates lookup failed
                s.Printf ("%-10s ", cstr);
            else
                s.Printf ("%-10u ", m_euid);
            
            cstr = platform->GetGroupName (m_egid);
            if (cstr && cstr[0]) // Watch for empty string that indicates lookup failed
                s.Printf ("%-10s ", cstr);
            else
                s.Printf ("%-10u ", m_egid);
            s.Printf ("%-24s ", m_arch.IsValid() ? m_arch.GetTriple().str().c_str() : "");
        }
        else
        {
            s.Printf ("%-10s %-24s ",
                      platform->GetUserName (m_euid),
                      m_arch.IsValid() ? m_arch.GetTriple().str().c_str() : "");
        }

        if (verbose || show_args)
        {
            const uint32_t argc = m_arguments.GetArgumentCount();
            if (argc > 0)
            {
                for (uint32_t i=0; i<argc; i++)
                {
                    if (i > 0)
                        s.PutChar (' ');
                    s.PutCString (m_arguments.GetArgumentAtIndex(i));
                }
            }
        }
        else
        {
            s.PutCString (GetName());
        }

        s.EOL();
    }
}

Error
ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
{
    Error error;
    const int short_option = m_getopt_table[option_idx].val;
    
    switch (short_option)
    {
        case 's':   // Stop at program entry point
            launch_info.GetFlags().Set (eLaunchFlagStopAtEntry); 
            break;
            
        case 'i':   // STDIN for read only
        {
            FileAction action;
            if (action.Open(STDIN_FILENO, FileSpec{option_arg, false}, true, false))
                launch_info.AppendFileAction (action);
            break;
        }
            
        case 'o':   // Open STDOUT for write only
        {
            FileAction action;
            if (action.Open(STDOUT_FILENO, FileSpec{option_arg, false}, false, true))
                launch_info.AppendFileAction (action);
            break;
        }

        case 'e':   // STDERR for write only
        {
            FileAction action;
            if (action.Open(STDERR_FILENO, FileSpec{option_arg, false}, false, true))
                launch_info.AppendFileAction (action);
            break;
        }

        case 'p':   // Process plug-in name
            launch_info.SetProcessPluginName (option_arg);    
            break;
            
        case 'n':   // Disable STDIO
        {
            FileAction action;
            const FileSpec dev_null{"/dev/null", false};
            if (action.Open(STDIN_FILENO, dev_null, true, false))
                launch_info.AppendFileAction (action);
            if (action.Open(STDOUT_FILENO, dev_null, false, true))
                launch_info.AppendFileAction (action);
            if (action.Open(STDERR_FILENO, dev_null, false, true))
                launch_info.AppendFileAction (action);
            break;
        }
            
        case 'w': 
            launch_info.SetWorkingDirectory(FileSpec{option_arg, false});
            break;
            
        case 't':   // Open process in new terminal window
            launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY); 
            break;
            
        case 'a':
            if (!launch_info.GetArchitecture().SetTriple (option_arg, m_interpreter.GetPlatform(true).get()))
                launch_info.GetArchitecture().SetTriple (option_arg);
            break;
            
        case 'A':   // Disable ASLR.
        {
            bool success;
            const bool disable_aslr_arg = Args::StringToBoolean (option_arg, true, &success);
            if (success)
                disable_aslr = disable_aslr_arg ? eLazyBoolYes : eLazyBoolNo;
            else
                error.SetErrorStringWithFormat ("Invalid boolean value for disable-aslr option: '%s'", option_arg ? option_arg : "<null>");
            break;
        }

        case 'X':   // shell expand args.
        {
            bool success;
            const bool expand_args = Args::StringToBoolean (option_arg, true, &success);
            if (success)
                launch_info.SetShellExpandArguments(expand_args);
            else
                error.SetErrorStringWithFormat ("Invalid boolean value for shell-expand-args option: '%s'", option_arg ? option_arg : "<null>");
            break;
        }
            
        case 'c':
            if (option_arg && option_arg[0])
                launch_info.SetShell (FileSpec(option_arg, false));
            else
                launch_info.SetShell (HostInfo::GetDefaultShell());
            break;
            
        case 'v':
            launch_info.GetEnvironmentEntries().AppendArgument(option_arg);
            break;

        default:
            error.SetErrorStringWithFormat("unrecognized short option character '%c'", short_option);
            break;
    }
    return error;
}

OptionDefinition
ProcessLaunchCommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone,          "Stop at the entry point of the program when launching a process."},
{ LLDB_OPT_SET_ALL, false, "disable-aslr",  'A', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,          "Set whether to disable address space layout randomization when launching a process."},
{ LLDB_OPT_SET_ALL, false, "plugin",        'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
{ LLDB_OPT_SET_ALL, false, "working-dir",   'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeDirectoryName,          "Set the current working directory to <path> when running the inferior."},
{ LLDB_OPT_SET_ALL, false, "arch",          'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeArchitecture,  "Set the architecture for the process to launch when ambiguous."},
{ LLDB_OPT_SET_ALL, false, "environment",   'v', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone,          "Specify an environment variable name/value string (--environment NAME=VALUE). Can be specified multiple times for subsequent environment entries."},
{ LLDB_OPT_SET_1|LLDB_OPT_SET_2|LLDB_OPT_SET_3, false, "shell",         'c', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeFilename,          "Run the process in a shell (not supported on all platforms)."},

{ LLDB_OPT_SET_1  , false, "stdin",         'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename,    "Redirect stdin for the process to <filename>."},
{ LLDB_OPT_SET_1  , false, "stdout",        'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename,    "Redirect stdout for the process to <filename>."},
{ LLDB_OPT_SET_1  , false, "stderr",        'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename,    "Redirect stderr for the process to <filename>."},

{ LLDB_OPT_SET_2  , false, "tty",           't', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone,    "Start the process in a terminal (not supported on all platforms)."},

{ LLDB_OPT_SET_3  , false, "no-stdio",      'n', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone,    "Do not set up for terminal I/O to go to running process."},
{ LLDB_OPT_SET_4,   false, "shell-expand-args",       'X', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,          "Set whether to shell expand arguments to the process when launching."},
{ 0               , false, NULL,             0,  0,                 NULL, NULL, 0, eArgTypeNone,    NULL }
};



bool
ProcessInstanceInfoMatch::NameMatches (const char *process_name) const
{
    if (m_name_match_type == eNameMatchIgnore || process_name == NULL)
        return true;
    const char *match_name = m_match_info.GetName();
    if (!match_name)
        return true;
    
    return lldb_private::NameMatches (process_name, m_name_match_type, match_name);
}

bool
ProcessInstanceInfoMatch::Matches (const ProcessInstanceInfo &proc_info) const
{
    if (!NameMatches (proc_info.GetName()))
        return false;

    if (m_match_info.ProcessIDIsValid() &&
        m_match_info.GetProcessID() != proc_info.GetProcessID())
        return false;

    if (m_match_info.ParentProcessIDIsValid() &&
        m_match_info.GetParentProcessID() != proc_info.GetParentProcessID())
        return false;

    if (m_match_info.UserIDIsValid () && 
        m_match_info.GetUserID() != proc_info.GetUserID())
        return false;
    
    if (m_match_info.GroupIDIsValid () && 
        m_match_info.GetGroupID() != proc_info.GetGroupID())
        return false;
    
    if (m_match_info.EffectiveUserIDIsValid () && 
        m_match_info.GetEffectiveUserID() != proc_info.GetEffectiveUserID())
        return false;
    
    if (m_match_info.EffectiveGroupIDIsValid () && 
        m_match_info.GetEffectiveGroupID() != proc_info.GetEffectiveGroupID())
        return false;
    
    if (m_match_info.GetArchitecture().IsValid() && 
        !m_match_info.GetArchitecture().IsCompatibleMatch(proc_info.GetArchitecture()))
        return false;
    return true;
}

bool
ProcessInstanceInfoMatch::MatchAllProcesses () const
{
    if (m_name_match_type != eNameMatchIgnore)
        return false;
    
    if (m_match_info.ProcessIDIsValid())
        return false;
    
    if (m_match_info.ParentProcessIDIsValid())
        return false;
    
    if (m_match_info.UserIDIsValid ())
        return false;
    
    if (m_match_info.GroupIDIsValid ())
        return false;
    
    if (m_match_info.EffectiveUserIDIsValid ())
        return false;
    
    if (m_match_info.EffectiveGroupIDIsValid ())
        return false;
    
    if (m_match_info.GetArchitecture().IsValid())
        return false;

    if (m_match_all_users)
        return false;

    return true;

}

void
ProcessInstanceInfoMatch::Clear()
{
    m_match_info.Clear();
    m_name_match_type = eNameMatchIgnore;
    m_match_all_users = false;
}

ProcessSP
Process::FindPlugin (Target &target, const char *plugin_name, Listener &listener, const FileSpec *crash_file_path)
{
    static uint32_t g_process_unique_id = 0;

    ProcessSP process_sp;
    ProcessCreateInstance create_callback = NULL;
    if (plugin_name)
    {
        ConstString const_plugin_name(plugin_name);
        create_callback  = PluginManager::GetProcessCreateCallbackForPluginName (const_plugin_name);
        if (create_callback)
        {
            process_sp = create_callback(target, listener, crash_file_path);
            if (process_sp)
            {
                if (process_sp->CanDebug(target, true))
                {
                    process_sp->m_process_unique_id = ++g_process_unique_id;
                }
                else
                    process_sp.reset();
            }
        }
    }
    else
    {
        for (uint32_t idx = 0; (create_callback = PluginManager::GetProcessCreateCallbackAtIndex(idx)) != NULL; ++idx)
        {
            process_sp = create_callback(target, listener, crash_file_path);
            if (process_sp)
            {
                if (process_sp->CanDebug(target, false))
                {
                    process_sp->m_process_unique_id = ++g_process_unique_id;
                    break;
                }
                else
                    process_sp.reset();
            }
        }
    }
    return process_sp;
}

ConstString &
Process::GetStaticBroadcasterClass ()
{
    static ConstString class_name ("lldb.process");
    return class_name;
}

//----------------------------------------------------------------------
// Process constructor
//----------------------------------------------------------------------
Process::Process(Target &target, Listener &listener) :
    Process(target, listener, Host::GetUnixSignals ())
{
    // This constructor just delegates to the full Process constructor,
    // defaulting to using the Host's UnixSignals.
}

Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_signals_sp) :
    ProcessProperties (this),
    UserID (LLDB_INVALID_PROCESS_ID),
    Broadcaster (&(target.GetDebugger()), Process::GetStaticBroadcasterClass().AsCString()),
    m_target (target),
    m_public_state (eStateUnloaded),
    m_private_state (eStateUnloaded),
    m_private_state_broadcaster (NULL, "lldb.process.internal_state_broadcaster"),
    m_private_state_control_broadcaster (NULL, "lldb.process.internal_state_control_broadcaster"),
    m_private_state_listener ("lldb.process.internal_state_listener"),
    m_private_state_control_wait(),
    m_mod_id (),
    m_process_unique_id(0),
    m_thread_index_id (0),
    m_thread_id_to_index_id_map (),
    m_exit_status (-1),
    m_exit_string (),
    m_exit_status_mutex(),
    m_thread_mutex (Mutex::eMutexTypeRecursive),
    m_thread_list_real (this),
    m_thread_list (this),
    m_extended_thread_list (this),
    m_extended_thread_stop_id (0),
    m_queue_list (this),
    m_queue_list_stop_id (0),
    m_notifications (),
    m_image_tokens (),
    m_listener (listener),
    m_breakpoint_site_list (),
    m_dynamic_checkers_ap (),
    m_unix_signals_sp (unix_signals_sp),
    m_abi_sp (),
    m_process_input_reader (),
    m_stdio_communication ("process.stdio"),
    m_stdio_communication_mutex (Mutex::eMutexTypeRecursive),
    m_stdin_forward (false),
    m_stdout_data (),
    m_stderr_data (),
    m_profile_data_comm_mutex (Mutex::eMutexTypeRecursive),
    m_profile_data (),
    m_iohandler_sync (0),
    m_memory_cache (*this),
    m_allocated_memory_cache (*this),
    m_should_detach (false),
    m_next_event_action_ap(),
    m_public_run_lock (),
    m_private_run_lock (),
    m_currently_handling_event(false),
    m_stop_info_override_callback (NULL),
    m_finalizing (false),
    m_finalize_called (false),
    m_clear_thread_plans_on_stop (false),
    m_force_next_event_delivery (false),
    m_last_broadcast_state (eStateInvalid),
    m_destroy_in_process (false),
    m_can_jit(eCanJITDontKnow)
{
    CheckInWithManager ();

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
    if (log)
        log->Printf ("%p Process::Process()", static_cast<void*>(this));

    if (!m_unix_signals_sp)
        m_unix_signals_sp.reset (new UnixSignals ());

    SetEventName (eBroadcastBitStateChanged, "state-changed");
    SetEventName (eBroadcastBitInterrupt, "interrupt");
    SetEventName (eBroadcastBitSTDOUT, "stdout-available");
    SetEventName (eBroadcastBitSTDERR, "stderr-available");
    SetEventName (eBroadcastBitProfileData, "profile-data-available");
    
    m_private_state_control_broadcaster.SetEventName (eBroadcastInternalStateControlStop  , "control-stop"  );
    m_private_state_control_broadcaster.SetEventName (eBroadcastInternalStateControlPause , "control-pause" );
    m_private_state_control_broadcaster.SetEventName (eBroadcastInternalStateControlResume, "control-resume");

    listener.StartListeningForEvents (this,
                                      eBroadcastBitStateChanged |
                                      eBroadcastBitInterrupt |
                                      eBroadcastBitSTDOUT |
                                      eBroadcastBitSTDERR |
                                      eBroadcastBitProfileData);

    m_private_state_listener.StartListeningForEvents(&m_private_state_broadcaster,
                                                     eBroadcastBitStateChanged |
                                                     eBroadcastBitInterrupt);

    m_private_state_listener.StartListeningForEvents(&m_private_state_control_broadcaster,
                                                     eBroadcastInternalStateControlStop |
                                                     eBroadcastInternalStateControlPause |
                                                     eBroadcastInternalStateControlResume);
    // We need something valid here, even if just the default UnixSignalsSP.
    assert (m_unix_signals_sp && "null m_unix_signals_sp after initialization");
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
Process::~Process()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
    if (log)
        log->Printf ("%p Process::~Process()", static_cast<void*>(this));
    StopPrivateStateThread();

    // ThreadList::Clear() will try to acquire this process's mutex, so
    // explicitly clear the thread list here to ensure that the mutex
    // is not destroyed before the thread list.
    m_thread_list.Clear();
}

const ProcessPropertiesSP &
Process::GetGlobalProperties()
{
    static ProcessPropertiesSP g_settings_sp;
    if (!g_settings_sp)
        g_settings_sp.reset (new ProcessProperties (NULL));
    return g_settings_sp;
}

void
Process::Finalize()
{
    m_finalizing = true;
    
    // Destroy this process if needed
    switch (GetPrivateState())
    {
        case eStateConnected:
        case eStateAttaching:
        case eStateLaunching:
        case eStateStopped:
        case eStateRunning:
        case eStateStepping:
        case eStateCrashed:
        case eStateSuspended:
            Destroy(false);
            break;
            
        case eStateInvalid:
        case eStateUnloaded:
        case eStateDetached:
        case eStateExited:
            break;
    }

    // Clear our broadcaster before we proceed with destroying
    Broadcaster::Clear();

    // Do any cleanup needed prior to being destructed... Subclasses
    // that override this method should call this superclass method as well.
    
    // We need to destroy the loader before the derived Process class gets destroyed
    // since it is very likely that undoing the loader will require access to the real process.
    m_dynamic_checkers_ap.reset();
    m_abi_sp.reset();
    m_os_ap.reset();
    m_system_runtime_ap.reset();
    m_dyld_ap.reset();
    m_jit_loaders_ap.reset();
    m_thread_list_real.Destroy();
    m_thread_list.Destroy();
    m_extended_thread_list.Destroy();
    m_queue_list.Clear();
    m_queue_list_stop_id = 0;
    std::vector<Notifications> empty_notifications;
    m_notifications.swap(empty_notifications);
    m_image_tokens.clear();
    m_memory_cache.Clear();
    m_allocated_memory_cache.Clear();
    m_language_runtimes.clear();
    m_instrumentation_runtimes.clear();
    m_next_event_action_ap.reset();
    m_stop_info_override_callback = NULL;
    // Clear the last natural stop ID since it has a strong
    // reference to this process
    m_mod_id.SetStopEventForLastNaturalStopID(EventSP());
//#ifdef LLDB_CONFIGURATION_DEBUG
//    StreamFile s(stdout, false);
//    EventSP event_sp;
//    while (m_private_state_listener.GetNextEvent(event_sp))
//    {
//        event_sp->Dump (&s);
//        s.EOL();
//    }
//#endif
    // We have to be very careful here as the m_private_state_listener might
    // contain events that have ProcessSP values in them which can keep this
    // process around forever. These events need to be cleared out.
    m_private_state_listener.Clear();
    m_public_run_lock.TrySetRunning(); // This will do nothing if already locked
    m_public_run_lock.SetStopped();
    m_private_run_lock.TrySetRunning(); // This will do nothing if already locked
    m_private_run_lock.SetStopped();
    m_finalize_called = true;
}

void
Process::RegisterNotificationCallbacks (const Notifications& callbacks)
{
    m_notifications.push_back(callbacks);
    if (callbacks.initialize != NULL)
        callbacks.initialize (callbacks.baton, this);
}

bool
Process::UnregisterNotificationCallbacks(const Notifications& callbacks)
{
    std::vector<Notifications>::iterator pos, end = m_notifications.end();
    for (pos = m_notifications.begin(); pos != end; ++pos)
    {
        if (pos->baton == callbacks.baton &&
            pos->initialize == callbacks.initialize &&
            pos->process_state_changed == callbacks.process_state_changed)
        {
            m_notifications.erase(pos);
            return true;
        }
    }
    return false;
}

void
Process::SynchronouslyNotifyStateChanged (StateType state)
{
    std::vector<Notifications>::iterator notification_pos, notification_end = m_notifications.end();
    for (notification_pos = m_notifications.begin(); notification_pos != notification_end; ++notification_pos)
    {
        if (notification_pos->process_state_changed)
            notification_pos->process_state_changed (notification_pos->baton, this, state);
    }
}

// FIXME: We need to do some work on events before the general Listener sees them.
// For instance if we are continuing from a breakpoint, we need to ensure that we do
// the little "insert real insn, step & stop" trick.  But we can't do that when the
// event is delivered by the broadcaster - since that is done on the thread that is
// waiting for new events, so if we needed more than one event for our handling, we would
// stall.  So instead we do it when we fetch the event off of the queue.
//

StateType
Process::GetNextEvent (EventSP &event_sp)
{
    StateType state = eStateInvalid;

    if (m_listener.GetNextEventForBroadcaster (this, event_sp) && event_sp)
        state = Process::ProcessEventData::GetStateFromEvent (event_sp.get());

    return state;
}

void
Process::SyncIOHandler (uint32_t iohandler_id, uint64_t timeout_msec)
{
    // don't sync (potentially context switch) in case where there is no process IO
    if (! m_process_input_reader)
        return;

    TimeValue timeout = TimeValue::Now();
    timeout.OffsetWithMicroSeconds(timeout_msec*1000);
    uint32_t new_iohandler_id = 0;
    m_iohandler_sync.WaitForValueNotEqualTo(iohandler_id, new_iohandler_id, &timeout);

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf("Process::%s waited for m_iohandler_sync to change from %u, new value is %u", __FUNCTION__, iohandler_id, new_iohandler_id);
}

StateType
Process::WaitForProcessToStop (const TimeValue *timeout,
                               EventSP *event_sp_ptr,
                               bool wait_always,
                               Listener *hijack_listener,
                               Stream *stream)
{
    // We can't just wait for a "stopped" event, because the stopped event may have restarted the target.
    // We have to actually check each event, and in the case of a stopped event check the restarted flag
    // on the event.
    if (event_sp_ptr)
        event_sp_ptr->reset();
    StateType state = GetState();
    // If we are exited or detached, we won't ever get back to any
    // other valid state...
    if (state == eStateDetached || state == eStateExited)
        return state;

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf ("Process::%s (timeout = %p)", __FUNCTION__,
                     static_cast<const void*>(timeout));

    if (!wait_always &&
        StateIsStoppedState(state, true) &&
        StateIsStoppedState(GetPrivateState(), true))
    {
        if (log)
            log->Printf("Process::%s returning without waiting for events; process private and public states are already 'stopped'.",
                        __FUNCTION__);
        // We need to toggle the run lock as this won't get done in
        // SetPublicState() if the process is hijacked.
        if (hijack_listener)
            m_public_run_lock.SetStopped();
        return state;
    }

    while (state != eStateInvalid)
    {
        EventSP event_sp;
        state = WaitForStateChangedEvents (timeout, event_sp, hijack_listener);
        if (event_sp_ptr && event_sp)
            *event_sp_ptr = event_sp;

        bool pop_process_io_handler = hijack_listener != NULL;
        Process::HandleProcessStateChangedEvent (event_sp, stream, pop_process_io_handler);

        switch (state)
        {
        case eStateCrashed:
        case eStateDetached:
        case eStateExited:
        case eStateUnloaded:
            // We need to toggle the run lock as this won't get done in
            // SetPublicState() if the process is hijacked.
            if (hijack_listener)
                m_public_run_lock.SetStopped();
            return state;
        case eStateStopped:
            if (Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
                continue;
            else
            {
                // We need to toggle the run lock as this won't get done in
                // SetPublicState() if the process is hijacked.
                if (hijack_listener)
                    m_public_run_lock.SetStopped();
                return state;
            }
        default:
            continue;
        }
    }
    return state;
}

bool
Process::HandleProcessStateChangedEvent (const EventSP &event_sp,
                                         Stream *stream,
                                         bool &pop_process_io_handler)
{
    const bool handle_pop = pop_process_io_handler == true;

    pop_process_io_handler = false;
    ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get());

    if (!process_sp)
        return false;

    StateType event_state = Process::ProcessEventData::GetStateFromEvent (event_sp.get());
    if (event_state == eStateInvalid)
        return false;

    switch (event_state)
    {
        case eStateInvalid:
        case eStateUnloaded:
        case eStateAttaching:
        case eStateLaunching:
        case eStateStepping:
        case eStateDetached:
            {
                if (stream)
                    stream->Printf ("Process %" PRIu64 " %s\n",
                                    process_sp->GetID(),
                                    StateAsCString (event_state));

                if (event_state == eStateDetached)
                    pop_process_io_handler = true;
            }
            break;

        case eStateConnected:
        case eStateRunning:
            // Don't be chatty when we run...
            break;

        case eStateExited:
            if (stream)
                process_sp->GetStatus(*stream);
            pop_process_io_handler = true;
            break;

        case eStateStopped:
        case eStateCrashed:
        case eStateSuspended:
            // Make sure the program hasn't been auto-restarted:
            if (Process::ProcessEventData::GetRestartedFromEvent (event_sp.get()))
            {
                if (stream)
                {
                    size_t num_reasons = Process::ProcessEventData::GetNumRestartedReasons(event_sp.get());
                    if (num_reasons > 0)
                    {
                        // FIXME: Do we want to report this, or would that just be annoyingly chatty?
                        if (num_reasons == 1)
                        {
                            const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), 0);
                            stream->Printf ("Process %" PRIu64 " stopped and restarted: %s\n",
                                            process_sp->GetID(),
                                            reason ? reason : "<UNKNOWN REASON>");
                        }
                        else
                        {
                            stream->Printf ("Process %" PRIu64 " stopped and restarted, reasons:\n",
                                            process_sp->GetID());


                            for (size_t i = 0; i < num_reasons; i++)
                            {
                                const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), i);
                                stream->Printf("\t%s\n", reason ? reason : "<UNKNOWN REASON>");
                            }
                        }
                    }
                }
            }
            else
            {
                // Lock the thread list so it doesn't change on us, this is the scope for the locker:
                {
                    ThreadList &thread_list = process_sp->GetThreadList();
                    Mutex::Locker locker (thread_list.GetMutex());

                    ThreadSP curr_thread (thread_list.GetSelectedThread());
                    ThreadSP thread;
                    StopReason curr_thread_stop_reason = eStopReasonInvalid;
                    if (curr_thread)
                        curr_thread_stop_reason = curr_thread->GetStopReason();
                    if (!curr_thread ||
                        !curr_thread->IsValid() ||
                        curr_thread_stop_reason == eStopReasonInvalid ||
                        curr_thread_stop_reason == eStopReasonNone)
                    {
                        // Prefer a thread that has just completed its plan over another thread as current thread.
                        ThreadSP plan_thread;
                        ThreadSP other_thread;
                        const size_t num_threads = thread_list.GetSize();
                        size_t i;
                        for (i = 0; i < num_threads; ++i)
                        {
                            thread = thread_list.GetThreadAtIndex(i);
                            StopReason thread_stop_reason = thread->GetStopReason();
                            switch (thread_stop_reason)
                            {
                                case eStopReasonInvalid:
                                case eStopReasonNone:
                                    break;

                                case eStopReasonTrace:
                                case eStopReasonBreakpoint:
                                case eStopReasonWatchpoint:
                                case eStopReasonSignal:
                                case eStopReasonException:
                                case eStopReasonExec:
                                case eStopReasonThreadExiting:
                                case eStopReasonInstrumentation:
                                    if (!other_thread)
                                        other_thread = thread;
                                    break;
                                case eStopReasonPlanComplete:
                                    if (!plan_thread)
                                        plan_thread = thread;
                                    break;
                            }
                        }
                        if (plan_thread)
                            thread_list.SetSelectedThreadByID (plan_thread->GetID());
                        else if (other_thread)
                            thread_list.SetSelectedThreadByID (other_thread->GetID());
                        else
                        {
                            if (curr_thread && curr_thread->IsValid())
                                thread = curr_thread;
                            else
                                thread = thread_list.GetThreadAtIndex(0);

                            if (thread)
                                thread_list.SetSelectedThreadByID (thread->GetID());
                        }
                    }
                }
                // Drop the ThreadList mutex by here, since GetThreadStatus below might have to run code,
                // e.g. for Data formatters, and if we hold the ThreadList mutex, then the process is going to
                // have a hard time restarting the process.
                if (stream)
                {
                    Debugger &debugger = process_sp->GetTarget().GetDebugger();
                    if (debugger.GetTargetList().GetSelectedTarget().get() == &process_sp->GetTarget())
                    {
                        const bool only_threads_with_stop_reason = true;
                        const uint32_t start_frame = 0;
                        const uint32_t num_frames = 1;
                        const uint32_t num_frames_with_source = 1;
                        process_sp->GetStatus(*stream);
                        process_sp->GetThreadStatus (*stream,
                                                     only_threads_with_stop_reason,
                                                     start_frame,
                                                     num_frames,
                                                     num_frames_with_source);
                    }
                    else
                    {
                        uint32_t target_idx = debugger.GetTargetList().GetIndexOfTarget(process_sp->GetTarget().shared_from_this());
                        if (target_idx != UINT32_MAX)
                            stream->Printf ("Target %d: (", target_idx);
                        else
                            stream->Printf ("Target <unknown index>: (");
                        process_sp->GetTarget().Dump (stream, eDescriptionLevelBrief);
                        stream->Printf (") stopped.\n");
                    }
                }

                // Pop the process IO handler
                pop_process_io_handler = true;
            }
            break;
    }

    if (handle_pop && pop_process_io_handler)
        process_sp->PopProcessIOHandler();

    return true;
}


StateType
Process::WaitForState
(
    const TimeValue *timeout,
    const StateType *match_states,
    const uint32_t num_match_states
)
{
    EventSP event_sp;
    uint32_t i;
    StateType state = GetState();
    while (state != eStateInvalid)
    {
        // If we are exited or detached, we won't ever get back to any
        // other valid state...
        if (state == eStateDetached || state == eStateExited)
            return state;

        state = WaitForStateChangedEvents (timeout, event_sp, NULL);

        for (i=0; i<num_match_states; ++i)
        {
            if (match_states[i] == state)
                return state;
        }
    }
    return state;
}

bool
Process::HijackProcessEvents (Listener *listener)
{
    if (listener != NULL)
    {
        return HijackBroadcaster(listener, eBroadcastBitStateChanged | eBroadcastBitInterrupt);
    }
    else
        return false;
}

void
Process::RestoreProcessEvents ()
{
    RestoreBroadcaster();
}

bool
Process::HijackPrivateProcessEvents (Listener *listener)
{
    if (listener != NULL)
    {
        return m_private_state_broadcaster.HijackBroadcaster(listener, eBroadcastBitStateChanged | eBroadcastBitInterrupt);
    }
    else
        return false;
}

void
Process::RestorePrivateProcessEvents ()
{
    m_private_state_broadcaster.RestoreBroadcaster();
}

StateType
Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp, Listener *hijack_listener)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    if (log)
        log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__,
                     static_cast<const void*>(timeout));

    Listener *listener = hijack_listener;
    if (listener == NULL)
        listener = &m_listener;

    StateType state = eStateInvalid;
    if (listener->WaitForEventForBroadcasterWithType (timeout,
                                                      this,
                                                      eBroadcastBitStateChanged | eBroadcastBitInterrupt,
                                                      event_sp))
    {
        if (event_sp && event_sp->GetType() == eBroadcastBitStateChanged)
            state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
        else if (log)
            log->Printf ("Process::%s got no event or was interrupted.", __FUNCTION__);
    }

    if (log)
        log->Printf ("Process::%s (timeout = %p, event_sp) => %s",
                     __FUNCTION__, static_cast<const void*>(timeout),
                     StateAsCString(state));
    return state;
}

Event *
Process::PeekAtStateChangedEvents ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    if (log)
        log->Printf ("Process::%s...", __FUNCTION__);

    Event *event_ptr;
    event_ptr = m_listener.PeekAtNextEventForBroadcasterWithType (this,
                                                                  eBroadcastBitStateChanged);
    if (log)
    {
        if (event_ptr)
        {
            log->Printf ("Process::%s (event_ptr) => %s",
                         __FUNCTION__,
                         StateAsCString(ProcessEventData::GetStateFromEvent (event_ptr)));
        }
        else 
        {
            log->Printf ("Process::%s no events found",
                         __FUNCTION__);
        }
    }
    return event_ptr;
}

StateType
Process::WaitForStateChangedEventsPrivate (const TimeValue *timeout, EventSP &event_sp)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    if (log)
        log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__,
                     static_cast<const void*>(timeout));

    StateType state = eStateInvalid;
    if (m_private_state_listener.WaitForEventForBroadcasterWithType (timeout,
                                                                     &m_private_state_broadcaster,
                                                                     eBroadcastBitStateChanged | eBroadcastBitInterrupt,
                                                                     event_sp))
        if (event_sp && event_sp->GetType() == eBroadcastBitStateChanged)
            state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());

    // This is a bit of a hack, but when we wait here we could very well return
    // to the command-line, and that could disable the log, which would render the
    // log we got above invalid.
    if (log)
        log->Printf ("Process::%s (timeout = %p, event_sp) => %s",
                     __FUNCTION__, static_cast<const void *>(timeout),
                     state == eStateInvalid ? "TIMEOUT" : StateAsCString(state));
    return state;
}

bool
Process::WaitForEventsPrivate (const TimeValue *timeout, EventSP &event_sp, bool control_only)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    if (log)
        log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__,
                     static_cast<const void*>(timeout));

    if (control_only)
        return m_private_state_listener.WaitForEventForBroadcaster(timeout, &m_private_state_control_broadcaster, event_sp);
    else
        return m_private_state_listener.WaitForEvent(timeout, event_sp);
}

bool
Process::IsRunning () const
{
    return StateIsRunningState (m_public_state.GetValue());
}

int
Process::GetExitStatus ()
{
    Mutex::Locker locker (m_exit_status_mutex);

    if (m_public_state.GetValue() == eStateExited)
        return m_exit_status;
    return -1;
}


const char *
Process::GetExitDescription ()
{
    Mutex::Locker locker (m_exit_status_mutex);

    if (m_public_state.GetValue() == eStateExited && !m_exit_string.empty())
        return m_exit_string.c_str();
    return NULL;
}

bool
Process::SetExitStatus (int status, const char *cstr)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf("Process::SetExitStatus (status=%i (0x%8.8x), description=%s%s%s)", 
                    status, status,
                    cstr ? "\"" : "",
                    cstr ? cstr : "NULL",
                    cstr ? "\"" : "");

    // We were already in the exited state
    if (m_private_state.GetValue() == eStateExited)
    {
        if (log)
            log->Printf("Process::SetExitStatus () ignoring exit status because state was already set to eStateExited");
        return false;
    }
    
    // use a mutex to protect the status and string during updating
    {
        Mutex::Locker locker (m_exit_status_mutex);

        m_exit_status = status;
        if (cstr)
            m_exit_string = cstr;
        else
            m_exit_string.clear();
    }

    // When we exit, we no longer need to the communication channel
    m_stdio_communication.StopReadThread();
    m_stdio_communication.Disconnect();
    m_stdin_forward = false;

    // And we don't need the input reader anymore as well
    if (m_process_input_reader)
    {
        m_process_input_reader->SetIsDone(true);
        m_process_input_reader->Cancel();
        m_process_input_reader.reset();
    }

    // Clear the last natural stop ID since it has a strong
    // reference to this process
    m_mod_id.SetStopEventForLastNaturalStopID(EventSP());

    SetPrivateState (eStateExited);

    // Allow subclasses to do some cleanup
    DidExit ();

    return true;
}

// This static callback can be used to watch for local child processes on
// the current host. The child process exits, the process will be
// found in the global target list (we want to be completely sure that the
// lldb_private::Process doesn't go away before we can deliver the signal.
bool
Process::SetProcessExitStatus (void *callback_baton,
                               lldb::pid_t pid,
                               bool exited,
                               int signo,          // Zero for no signal
                               int exit_status     // Exit value of process if signal is zero
)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf ("Process::SetProcessExitStatus (baton=%p, pid=%" PRIu64 ", exited=%i, signal=%i, exit_status=%i)\n",
                     callback_baton,
                     pid,
                     exited,
                     signo,
                     exit_status);

    if (exited)
    {
        TargetSP target_sp(Debugger::FindTargetWithProcessID (pid));
        if (target_sp)
        {
            ProcessSP process_sp (target_sp->GetProcessSP());
            if (process_sp)
            {
                const char *signal_cstr = NULL;
                if (signo)
                    signal_cstr = process_sp->GetUnixSignals().GetSignalAsCString (signo);

                process_sp->SetExitStatus (exit_status, signal_cstr);
            }
        }
        return true;
    }
    return false;
}


void
Process::UpdateThreadListIfNeeded ()
{
    const uint32_t stop_id = GetStopID();
    if (m_thread_list.GetSize(false) == 0 || stop_id != m_thread_list.GetStopID())
    {
        const StateType state = GetPrivateState();
        if (StateIsStoppedState (state, true))
        {
            Mutex::Locker locker (m_thread_list.GetMutex ());
            // m_thread_list does have its own mutex, but we need to
            // hold onto the mutex between the call to UpdateThreadList(...)
            // and the os->UpdateThreadList(...) so it doesn't change on us
            ThreadList &old_thread_list = m_thread_list;
            ThreadList real_thread_list(this);
            ThreadList new_thread_list(this);
            // Always update the thread list with the protocol specific
            // thread list, but only update if "true" is returned
            if (UpdateThreadList (m_thread_list_real, real_thread_list))
            {
                // Don't call into the OperatingSystem to update the thread list if we are shutting down, since
                // that may call back into the SBAPI's, requiring the API lock which is already held by whoever is
                // shutting us down, causing a deadlock.
                if (!m_destroy_in_process)
                {
                    OperatingSystem *os = GetOperatingSystem ();
                    if (os)
                    {
                        // Clear any old backing threads where memory threads might have been
                        // backed by actual threads from the lldb_private::Process subclass
                        size_t num_old_threads = old_thread_list.GetSize(false);
                        for (size_t i=0; i<num_old_threads; ++i)
                            old_thread_list.GetThreadAtIndex(i, false)->ClearBackingThread();

                        // Turn off dynamic types to ensure we don't run any expressions. Objective C
                        // can run an expression to determine if a SBValue is a dynamic type or not
                        // and we need to avoid this. OperatingSystem plug-ins can't run expressions
                        // that require running code...

                        Target &target = GetTarget();
                        const lldb::DynamicValueType saved_prefer_dynamic = target.GetPreferDynamicValue ();
                        if (saved_prefer_dynamic != lldb::eNoDynamicValues)
                            target.SetPreferDynamicValue(lldb::eNoDynamicValues);

                        // Now let the OperatingSystem plug-in update the thread list

                        os->UpdateThreadList (old_thread_list,  // Old list full of threads created by OS plug-in
                                              real_thread_list, // The actual thread list full of threads created by each lldb_private::Process subclass
                                              new_thread_list); // The new thread list that we will show to the user that gets filled in

                        if (saved_prefer_dynamic != lldb::eNoDynamicValues)
                            target.SetPreferDynamicValue(saved_prefer_dynamic);
                    }
                    else
                    {
                        // No OS plug-in, the new thread list is the same as the real thread list
                        new_thread_list = real_thread_list;
                    }
                }
                
                m_thread_list_real.Update(real_thread_list);
                m_thread_list.Update (new_thread_list);
                m_thread_list.SetStopID (stop_id);

                if (GetLastNaturalStopID () != m_extended_thread_stop_id)
                {
                    // Clear any extended threads that we may have accumulated previously
                    m_extended_thread_list.Clear();
                    m_extended_thread_stop_id = GetLastNaturalStopID ();

                    m_queue_list.Clear();
                    m_queue_list_stop_id = GetLastNaturalStopID ();
                }
            }
        }
    }
}

void
Process::UpdateQueueListIfNeeded ()
{
    if (m_system_runtime_ap.get())
    {
        if (m_queue_list.GetSize() == 0 || m_queue_list_stop_id != GetLastNaturalStopID())
        {
            const StateType state = GetPrivateState();
            if (StateIsStoppedState (state, true))
            {
                m_system_runtime_ap->PopulateQueueList (m_queue_list);
                m_queue_list_stop_id = GetLastNaturalStopID();
            }
        }
    }
}

ThreadSP
Process::CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context)
{
    OperatingSystem *os = GetOperatingSystem ();
    if (os)
        return os->CreateThread(tid, context);
    return ThreadSP();
}

uint32_t
Process::GetNextThreadIndexID (uint64_t thread_id)
{
    return AssignIndexIDToThread(thread_id);
}

bool
Process::HasAssignedIndexIDToThread(uint64_t thread_id)
{
    std::map<uint64_t, uint32_t>::iterator iterator = m_thread_id_to_index_id_map.find(thread_id);
    if (iterator == m_thread_id_to_index_id_map.end())
    {
        return false;
    }
    else
    {
        return true;
    }
}

uint32_t
Process::AssignIndexIDToThread(uint64_t thread_id)
{
    uint32_t result = 0;
    std::map<uint64_t, uint32_t>::iterator iterator = m_thread_id_to_index_id_map.find(thread_id);
    if (iterator == m_thread_id_to_index_id_map.end())
    {
        result = ++m_thread_index_id;
        m_thread_id_to_index_id_map[thread_id] = result;
    }
    else
    {
        result = iterator->second;
    }
    
    return result;
}

StateType
Process::GetState()
{
    // If any other threads access this we will need a mutex for it
    return m_public_state.GetValue ();
}

bool
Process::StateChangedIsExternallyHijacked()
{
    if (IsHijackedForEvent(eBroadcastBitStateChanged))
    {
        if (strcmp(m_hijacking_listeners.back()->GetName(), "lldb.Process.ResumeSynchronous.hijack"))
            return true;
    }
    return false;
}

void
Process::SetPublicState (StateType new_state, bool restarted)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf("Process::SetPublicState (state = %s, restarted = %i)", StateAsCString(new_state), restarted);
    const StateType old_state = m_public_state.GetValue();
    m_public_state.SetValue (new_state);
    
    // On the transition from Run to Stopped, we unlock the writer end of the
    // run lock.  The lock gets locked in Resume, which is the public API
    // to tell the program to run.
    if (!StateChangedIsExternallyHijacked())
    {
        if (new_state == eStateDetached)
        {
            if (log)
                log->Printf("Process::SetPublicState (%s) -- unlocking run lock for detach", StateAsCString(new_state));
            m_public_run_lock.SetStopped();
        }
        else
        {
            const bool old_state_is_stopped = StateIsStoppedState(old_state, false);
            const bool new_state_is_stopped = StateIsStoppedState(new_state, false);
            if ((old_state_is_stopped != new_state_is_stopped))
            {
                if (new_state_is_stopped && !restarted)
                {
                    if (log)
                        log->Printf("Process::SetPublicState (%s) -- unlocking run lock", StateAsCString(new_state));
                    m_public_run_lock.SetStopped();
                }
            }
        }
    }
}

Error
Process::Resume ()
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf("Process::Resume -- locking run lock");
    if (!m_public_run_lock.TrySetRunning())
    {
        Error error("Resume request failed - process still running.");
        if (log)
            log->Printf ("Process::Resume: -- TrySetRunning failed, not resuming.");
        return error;
    }
    return PrivateResume();
}

Error
Process::ResumeSynchronous (Stream *stream)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf("Process::ResumeSynchronous -- locking run lock");
    if (!m_public_run_lock.TrySetRunning())
    {
        Error error("Resume request failed - process still running.");
        if (log)
            log->Printf ("Process::Resume: -- TrySetRunning failed, not resuming.");
        return error;
    }

    ListenerSP listener_sp (new Listener("lldb.Process.ResumeSynchronous.hijack"));
    HijackProcessEvents(listener_sp.get());

    Error error = PrivateResume();
    if (error.Success())
    {
        StateType state = WaitForProcessToStop (NULL, NULL, true, listener_sp.get(), stream);
        const bool must_be_alive = false; // eStateExited is ok, so this must be false
        if (!StateIsStoppedState(state, must_be_alive))
            error.SetErrorStringWithFormat("process not in stopped state after synchronous resume: %s", StateAsCString(state));
    }

    // Undo the hijacking of process events...
    RestoreProcessEvents();

    return error;
}

StateType
Process::GetPrivateState ()
{
    return m_private_state.GetValue();
}

void
Process::SetPrivateState (StateType new_state)
{
    if (m_finalize_called)
        return;

    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS));
    bool state_changed = false;

    if (log)
        log->Printf("Process::SetPrivateState (%s)", StateAsCString(new_state));

    Mutex::Locker thread_locker(m_thread_list.GetMutex());
    Mutex::Locker locker(m_private_state.GetMutex());

    const StateType old_state = m_private_state.GetValueNoLock ();
    state_changed = old_state != new_state;

    const bool old_state_is_stopped = StateIsStoppedState(old_state, false);
    const bool new_state_is_stopped = StateIsStoppedState(new_state, false);
    if (old_state_is_stopped != new_state_is_stopped)
    {
        if (new_state_is_stopped)
            m_private_run_lock.SetStopped();
        else
            m_private_run_lock.SetRunning();
    }

    if (state_changed)
    {
        m_private_state.SetValueNoLock (new_state);
        EventSP event_sp (new Event (eBroadcastBitStateChanged, new ProcessEventData (shared_from_this(), new_state)));
        if (StateIsStoppedState(new_state, false))
        {
            // Note, this currently assumes that all threads in the list
            // stop when the process stops.  In the future we will want to
            // support a debugging model where some threads continue to run
            // while others are stopped.  When that happens we will either need
            // a way for the thread list to identify which threads are stopping
            // or create a special thread list containing only threads which
            // actually stopped.
            //
            // The process plugin is responsible for managing the actual
            // behavior of the threads and should have stopped any threads
            // that are going to stop before we get here.
            m_thread_list.DidStop();

            m_mod_id.BumpStopID();
            if (!m_mod_id.IsLastResumeForUserExpression())
                m_mod_id.SetStopEventForLastNaturalStopID(event_sp);
            m_memory_cache.Clear();
            if (log)
                log->Printf("Process::SetPrivateState (%s) stop_id = %u", StateAsCString(new_state), m_mod_id.GetStopID());
        }

        // Use our target to get a shared pointer to ourselves...
        if (m_finalize_called && PrivateStateThreadIsValid() == false)
            BroadcastEvent (event_sp);
        else
            m_private_state_broadcaster.BroadcastEvent (event_sp);
    }
    else
    {
        if (log)
            log->Printf("Process::SetPrivateState (%s) state didn't change. Ignoring...", StateAsCString(new_state));
    }
}

void
Process::SetRunningUserExpression (bool on)
{
    m_mod_id.SetRunningUserExpression (on);
}

addr_t
Process::GetImageInfoAddress()
{
    return LLDB_INVALID_ADDRESS;
}

//----------------------------------------------------------------------
// LoadImage
//
// This function provides a default implementation that works for most
// unix variants. Any Process subclasses that need to do shared library
// loading differently should override LoadImage and UnloadImage and
// do what is needed.
//----------------------------------------------------------------------
uint32_t
Process::LoadImage (const FileSpec &image_spec, Error &error)
{
    if (m_finalizing)
    {
        error.SetErrorString("process is tearing itself down");
        return LLDB_INVALID_IMAGE_TOKEN;
    }

    char path[PATH_MAX];
    image_spec.GetPath(path, sizeof(path));

    DynamicLoader *loader = GetDynamicLoader();
    if (loader)
    {
        error = loader->CanLoadImage();
        if (error.Fail())
            return LLDB_INVALID_IMAGE_TOKEN;
    }
    
    if (error.Success())
    {
        ThreadSP thread_sp(GetThreadList ().GetSelectedThread());
        
        if (thread_sp)
        {
            StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex (0));
            
            if (frame_sp)
            {
                ExecutionContext exe_ctx;
                frame_sp->CalculateExecutionContext (exe_ctx);
                EvaluateExpressionOptions expr_options;
                expr_options.SetUnwindOnError(true);
                expr_options.SetIgnoreBreakpoints(true);
                expr_options.SetExecutionPolicy(eExecutionPolicyAlways);
                expr_options.SetResultIsInternal(true);
                
                StreamString expr;
                expr.Printf(R"(
                               struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result;
                               the_result.image_ptr = dlopen ("%s", 2);
                               if (the_result.image_ptr == (void *) 0x0)
                               {
                                   the_result.error_str = dlerror();
                               }
                               else
                               {
                                   the_result.error_str = (const char *) 0x0;
                               }
                               the_result;
                              )",
                              path);
                const char *prefix = R"(
                                        extern "C" void* dlopen (const char *path, int mode);
                                        extern "C" const char *dlerror (void);
                                        )";
                lldb::ValueObjectSP result_valobj_sp;
                Error expr_error;
                ClangUserExpression::Evaluate (exe_ctx,
                                               expr_options,
                                               expr.GetData(),
                                               prefix,
                                               result_valobj_sp,
                                               expr_error);
                if (expr_error.Success())
                {
                    error = result_valobj_sp->GetError();
                    if (error.Success())
                    {
                        Scalar scalar;
                        ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true);
                        if (image_ptr_sp && image_ptr_sp->ResolveValue (scalar))
                        {
                            addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
                            if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS)
                            {
                                uint32_t image_token = m_image_tokens.size();
                                m_image_tokens.push_back (image_ptr);
                                return image_token;
                            }
                            else if (image_ptr == 0)
                            {
                                ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true);
                                if (error_str_sp)
                                {
                                    if (error_str_sp->IsCStringContainer(true))
                                    {
                                        DataBufferSP buffer_sp(new DataBufferHeap(10240,0));
                                        size_t num_chars = error_str_sp->ReadPointedString (buffer_sp, error, 10240);
                                        if (error.Success() && num_chars > 0)
                                        {
                                            error.Clear();
                                            error.SetErrorStringWithFormat("dlopen error: %s", buffer_sp->GetBytes());
                                        }
                                        else
                                        {
                                            error.Clear();
                                            error.SetErrorStringWithFormat("dlopen failed for unknown reasons.");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                    error = expr_error;
            }
        }
    }
    if (!error.AsCString())
        error.SetErrorStringWithFormat("unable to load '%s'", path);
    return LLDB_INVALID_IMAGE_TOKEN;
}

//----------------------------------------------------------------------
// UnloadImage
//
// This function provides a default implementation that works for most
// unix variants. Any Process subclasses that need to do shared library
// loading differently should override LoadImage and UnloadImage and
// do what is needed.
//----------------------------------------------------------------------
Error
Process::UnloadImage (uint32_t image_token)
{
    Error error;

    if (m_finalizing)
    {
        error.SetErrorString("process is tearing itself down");
        return error;
    }

    if (image_token < m_image_tokens.size())
    {
        const addr_t image_addr = m_image_tokens[image_token];
        if (image_addr == LLDB_INVALID_ADDRESS)
        {
            error.SetErrorString("image already unloaded");
        }
        else
        {
            DynamicLoader *loader = GetDynamicLoader();
            if (loader)
                error = loader->CanLoadImage();
            
            if (error.Success())
            {
                ThreadSP thread_sp(GetThreadList ().GetSelectedThread());
                
                if (thread_sp)
                {
                    StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex (0));
                    
                    if (frame_sp)
                    {
                        ExecutionContext exe_ctx;
                        frame_sp->CalculateExecutionContext (exe_ctx);
                        EvaluateExpressionOptions expr_options;
                        expr_options.SetUnwindOnError(true);
                        expr_options.SetIgnoreBreakpoints(true);
                        expr_options.SetExecutionPolicy(eExecutionPolicyAlways);
                        StreamString expr;
                        expr.Printf("dlclose ((void *)0x%" PRIx64 ")", image_addr);
                        const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
                        lldb::ValueObjectSP result_valobj_sp;
                        Error expr_error;
                        ClangUserExpression::Evaluate (exe_ctx,
                                                       expr_options,
                                                       expr.GetData(),
                                                       prefix,
                                                       result_valobj_sp,
                                                       expr_error);
                        if (result_valobj_sp->GetError().Success())
                        {
                            Scalar scalar;
                            if (result_valobj_sp->ResolveValue (scalar))
                            {
                                if (scalar.UInt(1))
                                {
                                    error.SetErrorStringWithFormat("expression failed: \"%s\"", expr.GetData());
                                }
                                else
                                {
                                    m_image_tokens[image_token] = LLDB_INVALID_ADDRESS;
                                }
                            }
                        }
                        else
                        {
                            error = result_valobj_sp->GetError();
                        }
                    }
                }
            }
        }
    }
    else
    {
        error.SetErrorString("invalid image token");
    }
    return error;
}

const lldb::ABISP &
Process::GetABI()
{
    if (!m_abi_sp)
        m_abi_sp = ABI::FindPlugin(m_target.GetArchitecture());
    return m_abi_sp;
}

LanguageRuntime *
Process::GetLanguageRuntime(lldb::LanguageType language, bool retry_if_null)
{
    if (m_finalizing)
        return nullptr;

    LanguageRuntimeCollection::iterator pos;
    pos = m_language_runtimes.find (language);
    if (pos == m_language_runtimes.end() || (retry_if_null && !(*pos).second))
    {
        lldb::LanguageRuntimeSP runtime_sp(LanguageRuntime::FindPlugin(this, language));
        
        m_language_runtimes[language] = runtime_sp;
        return runtime_sp.get();
    }
    else
        return (*pos).second.get();
}

CPPLanguageRuntime *
Process::GetCPPLanguageRuntime (bool retry_if_null)
{
    LanguageRuntime *runtime = GetLanguageRuntime(eLanguageTypeC_plus_plus, retry_if_null);
    if (runtime != NULL && runtime->GetLanguageType() == eLanguageTypeC_plus_plus)
        return static_cast<CPPLanguageRuntime *> (runtime);
    return NULL;
}

ObjCLanguageRuntime *
Process::GetObjCLanguageRuntime (bool retry_if_null)
{
    LanguageRuntime *runtime = GetLanguageRuntime(eLanguageTypeObjC, retry_if_null);
    if (runtime != NULL && runtime->GetLanguageType() == eLanguageTypeObjC)
        return static_cast<ObjCLanguageRuntime *> (runtime);
    return NULL;
}

bool
Process::IsPossibleDynamicValue (ValueObject& in_value)
{
    if (m_finalizing)
        return false;

    if (in_value.IsDynamic())
        return false;
    LanguageType known_type = in_value.GetObjectRuntimeLanguage();

    if (known_type != eLanguageTypeUnknown && known_type != eLanguageTypeC)
    {
        LanguageRuntime *runtime = GetLanguageRuntime (known_type);
        return runtime ? runtime->CouldHaveDynamicValue(in_value) : false;
    }

    LanguageRuntime *cpp_runtime = GetLanguageRuntime (eLanguageTypeC_plus_plus);
    if (cpp_runtime && cpp_runtime->CouldHaveDynamicValue(in_value))
        return true;
    
    LanguageRuntime *objc_runtime = GetLanguageRuntime (eLanguageTypeObjC);
    return objc_runtime ? objc_runtime->CouldHaveDynamicValue(in_value) : false;
}

void
Process::SetDynamicCheckers(DynamicCheckerFunctions *dynamic_checkers)
{
    m_dynamic_checkers_ap.reset(dynamic_checkers);
}

BreakpointSiteList &
Process::GetBreakpointSiteList()
{
    return m_breakpoint_site_list;
}

const BreakpointSiteList &
Process::GetBreakpointSiteList() const
{
    return m_breakpoint_site_list;
}


void
Process::DisableAllBreakpointSites ()
{
    m_breakpoint_site_list.ForEach([this](BreakpointSite *bp_site) -> void {
//        bp_site->SetEnabled(true);
        DisableBreakpointSite(bp_site);
    });
}

Error
Process::ClearBreakpointSiteByID (lldb::user_id_t break_id)
{
    Error error (DisableBreakpointSiteByID (break_id));
    
    if (error.Success())
        m_breakpoint_site_list.Remove(break_id);

    return error;
}

Error
Process::DisableBreakpointSiteByID (lldb::user_id_t break_id)
{
    Error error;
    BreakpointSiteSP bp_site_sp = m_breakpoint_site_list.FindByID (break_id);
    if (bp_site_sp)
    {
        if (bp_site_sp->IsEnabled())
            error = DisableBreakpointSite (bp_site_sp.get());
    }
    else
    {
        error.SetErrorStringWithFormat("invalid breakpoint site ID: %" PRIu64, break_id);
    }

    return error;
}

Error
Process::EnableBreakpointSiteByID (lldb::user_id_t break_id)
{
    Error error;
    BreakpointSiteSP bp_site_sp = m_breakpoint_site_list.FindByID (break_id);
    if (bp_site_sp)
    {
        if (!bp_site_sp->IsEnabled())
            error = EnableBreakpointSite (bp_site_sp.get());
    }
    else
    {
        error.SetErrorStringWithFormat("invalid breakpoint site ID: %" PRIu64, break_id);
    }
    return error;
}

lldb::break_id_t
Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardware)
{
    addr_t load_addr = LLDB_INVALID_ADDRESS;
    
    bool show_error = true;
    switch (GetState())
    {
        case eStateInvalid:
        case eStateUnloaded:
        case eStateConnected:
        case eStateAttaching:
        case eStateLaunching:
        case eStateDetached:
        case eStateExited:
            show_error = false;
            break;
            
        case eStateStopped:
        case eStateRunning:
        case eStateStepping:
        case eStateCrashed:
        case eStateSuspended:
            show_error = IsAlive();
            break;
    }

    // Reset the IsIndirect flag here, in case the location changes from
    // pointing to a indirect symbol to a regular symbol.
    owner->SetIsIndirect (false);
    
    if (owner->ShouldResolveIndirectFunctions())
    {
        Symbol *symbol = owner->GetAddress().CalculateSymbolContextSymbol();
        if (symbol && symbol->IsIndirect())
        {
            Error error;
            load_addr = ResolveIndirectFunction (&symbol->GetAddress(), error);
            if (!error.Success() && show_error)
            {
                m_target.GetDebugger().GetErrorFile()->Printf ("warning: failed to resolve indirect function at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
                                                               symbol->GetAddress().GetLoadAddress(&m_target),
                                                               owner->GetBreakpoint().GetID(),
                                                               owner->GetID(),
                                                               error.AsCString() ? error.AsCString() : "unknown error");
                return LLDB_INVALID_BREAK_ID;
            }
            Address resolved_address(load_addr);
            load_addr = resolved_address.GetOpcodeLoadAddress (&m_target);
            owner->SetIsIndirect(true);
        }
        else
            load_addr = owner->GetAddress().GetOpcodeLoadAddress (&m_target);
    }
    else
        load_addr = owner->GetAddress().GetOpcodeLoadAddress (&m_target);
    
    if (load_addr != LLDB_INVALID_ADDRESS)
    {
        BreakpointSiteSP bp_site_sp;

        // Look up this breakpoint site.  If it exists, then add this new owner, otherwise
        // create a new breakpoint site and add it.

        bp_site_sp = m_breakpoint_site_list.FindByAddress (load_addr);

        if (bp_site_sp)
        {
            bp_site_sp->AddOwner (owner);
            owner->SetBreakpointSite (bp_site_sp);
            return bp_site_sp->GetID();
        }
        else
        {
            bp_site_sp.reset (new BreakpointSite (&m_breakpoint_site_list, owner, load_addr, use_hardware));
            if (bp_site_sp)
            {
                Error error = EnableBreakpointSite (bp_site_sp.get());
                if (error.Success())
                {
                    owner->SetBreakpointSite (bp_site_sp);
                    return m_breakpoint_site_list.Add (bp_site_sp);
                }
                else
                {
                    if (show_error)
                    {
                        // Report error for setting breakpoint...
                        m_target.GetDebugger().GetErrorFile()->Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
                                                                       load_addr,
                                                                       owner->GetBreakpoint().GetID(),
                                                                       owner->GetID(),
                                                                       error.AsCString() ? error.AsCString() : "unknown error");
                    }
                }
            }
        }
    }
    // We failed to enable the breakpoint
    return LLDB_INVALID_BREAK_ID;

}

void
Process::RemoveOwnerFromBreakpointSite (lldb::user_id_t owner_id, lldb::user_id_t owner_loc_id, BreakpointSiteSP &bp_site_sp)
{
    uint32_t num_owners = bp_site_sp->RemoveOwner (owner_id, owner_loc_id);
    if (num_owners == 0)
    {
        // Don't try to disable the site if we don't have a live process anymore.
        if (IsAlive())
            DisableBreakpointSite (bp_site_sp.get());
        m_breakpoint_site_list.RemoveByAddress(bp_site_sp->GetLoadAddress());
    }
}


size_t
Process::RemoveBreakpointOpcodesFromBuffer (addr_t bp_addr, size_t size, uint8_t *buf) const
{
    size_t bytes_removed = 0;
    BreakpointSiteList bp_sites_in_range;

    if (m_breakpoint_site_list.FindInRange (bp_addr, bp_addr + size, bp_sites_in_range))
    {
        bp_sites_in_range.ForEach([bp_addr, size, buf, &bytes_removed](BreakpointSite *bp_site) -> void {
            if (bp_site->GetType() == BreakpointSite::eSoftware)
            {
                addr_t intersect_addr;
                size_t intersect_size;
                size_t opcode_offset;
                if (bp_site->IntersectsRange(bp_addr, size, &intersect_addr, &intersect_size, &opcode_offset))
                {
                    assert(bp_addr <= intersect_addr && intersect_addr < bp_addr + size);
                    assert(bp_addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= bp_addr + size);
                    assert(opcode_offset + intersect_size <= bp_site->GetByteSize());
                    size_t buf_offset = intersect_addr - bp_addr;
                    ::memcpy(buf + buf_offset, bp_site->GetSavedOpcodeBytes() + opcode_offset, intersect_size);
                }
            }
        });
    }
    return bytes_removed;
}



size_t
Process::GetSoftwareBreakpointTrapOpcode (BreakpointSite* bp_site)
{
    PlatformSP platform_sp (m_target.GetPlatform());
    if (platform_sp)
        return platform_sp->GetSoftwareBreakpointTrapOpcode (m_target, bp_site);
    return 0;
}

Error
Process::EnableSoftwareBreakpoint (BreakpointSite *bp_site)
{
    Error error;
    assert (bp_site != NULL);
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
    const addr_t bp_addr = bp_site->GetLoadAddress();
    if (log)
        log->Printf ("Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64, bp_site->GetID(), (uint64_t)bp_addr);
    if (bp_site->IsEnabled())
    {
        if (log)
            log->Printf ("Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 " -- already enabled", bp_site->GetID(), (uint64_t)bp_addr);
        return error;
    }

    if (bp_addr == LLDB_INVALID_ADDRESS)
    {
        error.SetErrorString("BreakpointSite contains an invalid load address.");
        return error;
    }
    // Ask the lldb::Process subclass to fill in the correct software breakpoint
    // trap for the breakpoint site
    const size_t bp_opcode_size = GetSoftwareBreakpointTrapOpcode(bp_site);

    if (bp_opcode_size == 0)
    {
        error.SetErrorStringWithFormat ("Process::GetSoftwareBreakpointTrapOpcode() returned zero, unable to get breakpoint trap for address 0x%" PRIx64, bp_addr);
    }
    else
    {
        const uint8_t * const bp_opcode_bytes = bp_site->GetTrapOpcodeBytes();

        if (bp_opcode_bytes == NULL)
        {
            error.SetErrorString ("BreakpointSite doesn't contain a valid breakpoint trap opcode.");
            return error;
        }

        // Save the original opcode by reading it
        if (DoReadMemory(bp_addr, bp_site->GetSavedOpcodeBytes(), bp_opcode_size, error) == bp_opcode_size)
        {
            // Write a software breakpoint in place of the original opcode
            if (DoWriteMemory(bp_addr, bp_opcode_bytes, bp_opcode_size, error) == bp_opcode_size)
            {
                uint8_t verify_bp_opcode_bytes[64];
                if (DoReadMemory(bp_addr, verify_bp_opcode_bytes, bp_opcode_size, error) == bp_opcode_size)
                {
                    if (::memcmp(bp_opcode_bytes, verify_bp_opcode_bytes, bp_opcode_size) == 0)
                    {
                        bp_site->SetEnabled(true);
                        bp_site->SetType (BreakpointSite::eSoftware);
                        if (log)
                            log->Printf ("Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 " -- SUCCESS",
                                         bp_site->GetID(),
                                         (uint64_t)bp_addr);
                    }
                    else
                        error.SetErrorString("failed to verify the breakpoint trap in memory.");
                }
                else
                    error.SetErrorString("Unable to read memory to verify breakpoint trap.");
            }
            else
                error.SetErrorString("Unable to write breakpoint trap to memory.");
        }
        else
            error.SetErrorString("Unable to read memory at breakpoint address.");
    }
    if (log && error.Fail())
        log->Printf ("Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 " -- FAILED: %s",
                     bp_site->GetID(),
                     (uint64_t)bp_addr,
                     error.AsCString());
    return error;
}

Error
Process::DisableSoftwareBreakpoint (BreakpointSite *bp_site)
{
    Error error;
    assert (bp_site != NULL);
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
    addr_t bp_addr = bp_site->GetLoadAddress();
    lldb::user_id_t breakID = bp_site->GetID();
    if (log)
        log->Printf ("Process::DisableSoftwareBreakpoint (breakID = %" PRIu64 ") addr = 0x%" PRIx64, breakID, (uint64_t)bp_addr);

    if (bp_site->IsHardware())
    {
        error.SetErrorString("Breakpoint site is a hardware breakpoint.");
    }
    else if (bp_site->IsEnabled())
    {
        const size_t break_op_size = bp_site->GetByteSize();
        const uint8_t * const break_op = bp_site->GetTrapOpcodeBytes();
        if (break_op_size > 0)
        {
            // Clear a software breakpoint instruction
            uint8_t curr_break_op[8];
            assert (break_op_size <= sizeof(curr_break_op));
            bool break_op_found = false;

            // Read the breakpoint opcode
            if (DoReadMemory (bp_addr, curr_break_op, break_op_size, error) == break_op_size)
            {
                bool verify = false;
                // Make sure we have the a breakpoint opcode exists at this address
                if (::memcmp (curr_break_op, break_op, break_op_size) == 0)
                {
                    break_op_found = true;
                    // We found a valid breakpoint opcode at this address, now restore
                    // the saved opcode.
                    if (DoWriteMemory (bp_addr, bp_site->GetSavedOpcodeBytes(), break_op_size, error) == break_op_size)
                    {
                        verify = true;
                    }
                    else
                        error.SetErrorString("Memory write failed when restoring original opcode.");
                }
                else
                {
                    error.SetErrorString("Original breakpoint trap is no longer in memory.");
                    // Set verify to true and so we can check if the original opcode has already been restored
                    verify = true;
                }

                if (verify)
                {
                    uint8_t verify_opcode[8];
                    assert (break_op_size < sizeof(verify_opcode));
                    // Verify that our original opcode made it back to the inferior
                    if (DoReadMemory (bp_addr, verify_opcode, break_op_size, error) == break_op_size)
                    {
                        // compare the memory we just read with the original opcode
                        if (::memcmp (bp_site->GetSavedOpcodeBytes(), verify_opcode, break_op_size) == 0)
                        {
                            // SUCCESS
                            bp_site->SetEnabled(false);
                            if (log)
                                log->Printf ("Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 " -- SUCCESS", bp_site->GetID(), (uint64_t)bp_addr);
                            return error;
                        }
                        else
                        {
                            if (break_op_found)
                                error.SetErrorString("Failed to restore original opcode.");
                        }
                    }
                    else
                        error.SetErrorString("Failed to read memory to verify that breakpoint trap was restored.");
                }
            }
            else
                error.SetErrorString("Unable to read memory that should contain the breakpoint trap.");
        }
    }
    else
    {
        if (log)
            log->Printf ("Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 " -- already disabled", bp_site->GetID(), (uint64_t)bp_addr);
        return error;
    }

    if (log)
        log->Printf ("Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 " -- FAILED: %s",
                     bp_site->GetID(),
                     (uint64_t)bp_addr,
                     error.AsCString());
    return error;

}

// Uncomment to verify memory caching works after making changes to caching code
//#define VERIFY_MEMORY_READS

size_t
Process::ReadMemory (addr_t addr, void *buf, size_t size, Error &error)
{
    error.Clear();
    if (!GetDisableMemoryCache())
    {        
#if defined (VERIFY_MEMORY_READS)
        // Memory caching is enabled, with debug verification
        
        if (buf && size)
        {
            // Uncomment the line below to make sure memory caching is working.
            // I ran this through the test suite and got no assertions, so I am 
            // pretty confident this is working well. If any changes are made to
            // memory caching, uncomment the line below and test your changes!
            
            // Verify all memory reads by using the cache first, then redundantly
            // reading the same memory from the inferior and comparing to make sure
            // everything is exactly the same.
            std::string verify_buf (size, '\0');
            assert (verify_buf.size() == size);
            const size_t cache_bytes_read = m_memory_cache.Read (this, addr, buf, size, error);
            Error verify_error;
            const size_t verify_bytes_read = ReadMemoryFromInferior (addr, const_cast<char *>(verify_buf.data()), verify_buf.size(), verify_error);
            assert (cache_bytes_read == verify_bytes_read);
            assert (memcmp(buf, verify_buf.data(), verify_buf.size()) == 0);
            assert (verify_error.Success() == error.Success());
            return cache_bytes_read;
        }
        return 0;
#else // !defined(VERIFY_MEMORY_READS)
        // Memory caching is enabled, without debug verification
        
        return m_memory_cache.Read (addr, buf, size, error);
#endif // defined (VERIFY_MEMORY_READS)
    }
    else
    {
        // Memory caching is disabled
        
        return ReadMemoryFromInferior (addr, buf, size, error);
    }
}
    
size_t
Process::ReadCStringFromMemory (addr_t addr, std::string &out_str, Error &error)
{
    char buf[256];
    out_str.clear();
    addr_t curr_addr = addr;
    while (1)
    {
        size_t length = ReadCStringFromMemory (curr_addr, buf, sizeof(buf), error);
        if (length == 0)
            break;
        out_str.append(buf, length);
        // If we got "length - 1" bytes, we didn't get the whole C string, we
        // need to read some more characters
        if (length == sizeof(buf) - 1)
            curr_addr += length;
        else
            break;
    }
    return out_str.size();
}


size_t
Process::ReadStringFromMemory (addr_t addr, char *dst, size_t max_bytes, Error &error,
                                size_t type_width)
{
    size_t total_bytes_read = 0;
    if (dst && max_bytes && type_width && max_bytes >= type_width)
    {
        // Ensure a null terminator independent of the number of bytes that is read.
        memset (dst, 0, max_bytes);
        size_t bytes_left = max_bytes - type_width;

        const char terminator[4] = {'\0', '\0', '\0', '\0'};
        assert(sizeof(terminator) >= type_width &&
               "Attempting to validate a string with more than 4 bytes per character!");

        addr_t curr_addr = addr;
        const size_t cache_line_size = m_memory_cache.GetMemoryCacheLineSize();
        char *curr_dst = dst;

        error.Clear();
        while (bytes_left > 0 && error.Success())
        {
            addr_t cache_line_bytes_left = cache_line_size - (curr_addr % cache_line_size);
            addr_t bytes_to_read = std::min<addr_t>(bytes_left, cache_line_bytes_left);
            size_t bytes_read = ReadMemory (curr_addr, curr_dst, bytes_to_read, error);

            if (bytes_read == 0)
                break;

            // Search for a null terminator of correct size and alignment in bytes_read
            size_t aligned_start = total_bytes_read - total_bytes_read % type_width;
            for (size_t i = aligned_start; i + type_width <= total_bytes_read + bytes_read; i += type_width)
                if (::strncmp(&dst[i], terminator, type_width) == 0)
                {
                    error.Clear();
                    return i;
                }

            total_bytes_read += bytes_read;
            curr_dst += bytes_read;
            curr_addr += bytes_read;
            bytes_left -= bytes_read;
        }
    }
    else
    {
        if (max_bytes)
            error.SetErrorString("invalid arguments");
    }
    return total_bytes_read;
}

// Deprecated in favor of ReadStringFromMemory which has wchar support and correct code to find
// null terminators.
size_t
Process::ReadCStringFromMemory (addr_t addr, char *dst, size_t dst_max_len, Error &result_error)
{
    size_t total_cstr_len = 0;
    if (dst && dst_max_len)
    {
        result_error.Clear();
        // NULL out everything just to be safe
        memset (dst, 0, dst_max_len);
        Error error;
        addr_t curr_addr = addr;
        const size_t cache_line_size = m_memory_cache.GetMemoryCacheLineSize();
        size_t bytes_left = dst_max_len - 1;
        char *curr_dst = dst;
        
        while (bytes_left > 0)
        {
            addr_t cache_line_bytes_left = cache_line_size - (curr_addr % cache_line_size);
            addr_t bytes_to_read = std::min<addr_t>(bytes_left, cache_line_bytes_left);
            size_t bytes_read = ReadMemory (curr_addr, curr_dst, bytes_to_read, error);
            
            if (bytes_read == 0)
            {
                result_error = error;
                dst[total_cstr_len] = '\0';
                break;
            }
            const size_t len = strlen(curr_dst);

            total_cstr_len += len;

            if (len < bytes_to_read)
                break;

            curr_dst += bytes_read;
            curr_addr += bytes_read;
            bytes_left -= bytes_read;
        }
    }
    else
    {
        if (dst == NULL)
            result_error.SetErrorString("invalid arguments");
        else
            result_error.Clear();
    }
    return total_cstr_len;
}

size_t
Process::ReadMemoryFromInferior (addr_t addr, void *buf, size_t size, Error &error)
{
    if (buf == NULL || size == 0)
        return 0;

    size_t bytes_read = 0;
    uint8_t *bytes = (uint8_t *)buf;
    
    while (bytes_read < size)
    {
        const size_t curr_size = size - bytes_read;
        const size_t curr_bytes_read = DoReadMemory (addr + bytes_read, 
                                                     bytes + bytes_read, 
                                                     curr_size,
                                                     error);
        bytes_read += curr_bytes_read;
        if (curr_bytes_read == curr_size || curr_bytes_read == 0)
            break;
    }

    // Replace any software breakpoint opcodes that fall into this range back
    // into "buf" before we return
    if (bytes_read > 0)
        RemoveBreakpointOpcodesFromBuffer (addr, bytes_read, (uint8_t *)buf);
    return bytes_read;
}

uint64_t
Process::ReadUnsignedIntegerFromMemory (lldb::addr_t vm_addr, size_t integer_byte_size, uint64_t fail_value, Error &error)
{
    Scalar scalar;
    if (ReadScalarIntegerFromMemory(vm_addr, integer_byte_size, false, scalar, error))
        return scalar.ULongLong(fail_value);
    return fail_value;
}

addr_t
Process::ReadPointerFromMemory (lldb::addr_t vm_addr, Error &error)
{
    Scalar scalar;
    if (ReadScalarIntegerFromMemory(vm_addr, GetAddressByteSize(), false, scalar, error))
        return scalar.ULongLong(LLDB_INVALID_ADDRESS);
    return LLDB_INVALID_ADDRESS;
}


bool
Process::WritePointerToMemory (lldb::addr_t vm_addr, 
                               lldb::addr_t ptr_value, 
                               Error &error)
{
    Scalar scalar;
    const uint32_t addr_byte_size = GetAddressByteSize();
    if (addr_byte_size <= 4)
        scalar = (uint32_t)ptr_value;
    else
        scalar = ptr_value;
    return WriteScalarToMemory(vm_addr, scalar, addr_byte_size, error) == addr_byte_size;
}

size_t
Process::WriteMemoryPrivate (addr_t addr, const void *buf, size_t size, Error &error)
{
    size_t bytes_written = 0;
    const uint8_t *bytes = (const uint8_t *)buf;
    
    while (bytes_written < size)
    {
        const size_t curr_size = size - bytes_written;
        const size_t curr_bytes_written = DoWriteMemory (addr + bytes_written, 
                                                         bytes + bytes_written, 
                                                         curr_size,
                                                         error);
        bytes_written += curr_bytes_written;
        if (curr_bytes_written == curr_size || curr_bytes_written == 0)
            break;
    }
    return bytes_written;
}

size_t
Process::WriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
{
#if defined (ENABLE_MEMORY_CACHING)
    m_memory_cache.Flush (addr, size);
#endif

    if (buf == NULL || size == 0)
        return 0;

    m_mod_id.BumpMemoryID();

    // We need to write any data that would go where any current software traps
    // (enabled software breakpoints) any software traps (breakpoints) that we
    // may have placed in our tasks memory.

    BreakpointSiteList bp_sites_in_range;
    
    if (m_breakpoint_site_list.FindInRange (addr, addr + size, bp_sites_in_range))
    {
        // No breakpoint sites overlap
        if (bp_sites_in_range.IsEmpty())
            return WriteMemoryPrivate (addr, buf, size, error);
        else
        {
            const uint8_t *ubuf = (const uint8_t *)buf;
            uint64_t bytes_written = 0;

            bp_sites_in_range.ForEach([this, addr, size, &bytes_written, &ubuf, &error](BreakpointSite *bp) -> void {
                
                if (error.Success())
                {
                    addr_t intersect_addr;
                    size_t intersect_size;
                    size_t opcode_offset;
                    const bool intersects = bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset);
                    assert(intersects);
                    assert(addr <= intersect_addr && intersect_addr < addr + size);
                    assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size);
                    assert(opcode_offset + intersect_size <= bp->GetByteSize());
                    
                    // Check for bytes before this breakpoint
                    const addr_t curr_addr = addr + bytes_written;
                    if (intersect_addr > curr_addr)
                    {
                        // There are some bytes before this breakpoint that we need to
                        // just write to memory
                        size_t curr_size = intersect_addr - curr_addr;
                        size_t curr_bytes_written = WriteMemoryPrivate (curr_addr,
                                                                        ubuf + bytes_written,
                                                                        curr_size,
                                                                        error);
                        bytes_written += curr_bytes_written;
                        if (curr_bytes_written != curr_size)
                        {
                            // We weren't able to write all of the requested bytes, we
                            // are done looping and will return the number of bytes that
                            // we have written so far.
                            if (error.Success())
                                error.SetErrorToGenericError();
                        }
                    }
                    // Now write any bytes that would cover up any software breakpoints
                    // directly into the breakpoint opcode buffer
                    ::memcpy(bp->GetSavedOpcodeBytes() + opcode_offset, ubuf + bytes_written, intersect_size);
                    bytes_written += intersect_size;
                }
            });
            
            if (bytes_written < size)
                WriteMemoryPrivate (addr + bytes_written,
                                    ubuf + bytes_written,
                                    size - bytes_written,
                                    error);
        }
    }
    else
    {
        return WriteMemoryPrivate (addr, buf, size, error);
    }

    // Write any remaining bytes after the last breakpoint if we have any left
    return 0; //bytes_written;
}

size_t
Process::WriteScalarToMemory (addr_t addr, const Scalar &scalar, size_t byte_size, Error &error)
{
    if (byte_size == UINT32_MAX)
        byte_size = scalar.GetByteSize();
    if (byte_size > 0)
    {
        uint8_t buf[32];
        const size_t mem_size = scalar.GetAsMemoryData (buf, byte_size, GetByteOrder(), error);
        if (mem_size > 0)
            return WriteMemory(addr, buf, mem_size, error);
        else
            error.SetErrorString ("failed to get scalar as memory data");
    }
    else
    {
        error.SetErrorString ("invalid scalar value");
    }
    return 0;
}

size_t
Process::ReadScalarIntegerFromMemory (addr_t addr, 
                                      uint32_t byte_size, 
                                      bool is_signed, 
                                      Scalar &scalar, 
                                      Error &error)
{
    uint64_t uval = 0;
    if (byte_size == 0)
    {
        error.SetErrorString ("byte size is zero");
    }
    else if (byte_size & (byte_size - 1))
    {
        error.SetErrorStringWithFormat ("byte size %u is not a power of 2", byte_size);
    }
    else if (byte_size <= sizeof(uval))
    {
        const size_t bytes_read = ReadMemory (addr, &uval, byte_size, error);
        if (bytes_read == byte_size)
        {
            DataExtractor data (&uval, sizeof(uval), GetByteOrder(), GetAddressByteSize());
            lldb::offset_t offset = 0;
            if (byte_size <= 4)
                scalar = data.GetMaxU32 (&offset, byte_size);
            else
                scalar = data.GetMaxU64 (&offset, byte_size);
            if (is_signed)
                scalar.SignExtend(byte_size * 8);
            return bytes_read;
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("byte size of %u is too large for integer scalar type", byte_size);
    }
    return 0;
}

#define USE_ALLOCATE_MEMORY_CACHE 1
addr_t
Process::AllocateMemory(size_t size, uint32_t permissions, Error &error)
{
    if (GetPrivateState() != eStateStopped)
        return LLDB_INVALID_ADDRESS;
        
#if defined (USE_ALLOCATE_MEMORY_CACHE)
    return m_allocated_memory_cache.AllocateMemory(size, permissions, error);
#else
    addr_t allocated_addr = DoAllocateMemory (size, permissions, error);
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf("Process::AllocateMemory(size=%" PRIu64 ", permissions=%s) => 0x%16.16" PRIx64 " (m_stop_id = %u m_memory_id = %u)",
                    (uint64_t)size,
                    GetPermissionsAsCString (permissions),
                    (uint64_t)allocated_addr,
                    m_mod_id.GetStopID(),
                    m_mod_id.GetMemoryID());
    return allocated_addr;
#endif
}

bool
Process::CanJIT ()
{
    if (m_can_jit == eCanJITDontKnow)
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
        Error err;
        
        uint64_t allocated_memory = AllocateMemory(8, 
                                                   ePermissionsReadable | ePermissionsWritable | ePermissionsExecutable, 
                                                   err);
        
        if (err.Success())
        {
            m_can_jit = eCanJITYes;
            if (log)
                log->Printf ("Process::%s pid %" PRIu64 " allocation test passed, CanJIT () is true", __FUNCTION__, GetID ());
        }
        else
        {
            m_can_jit = eCanJITNo;
            if (log)
                log->Printf ("Process::%s pid %" PRIu64 " allocation test failed, CanJIT () is false: %s", __FUNCTION__, GetID (), err.AsCString ());
        }
        
        DeallocateMemory (allocated_memory);
    }
    
    return m_can_jit == eCanJITYes;
}

void
Process::SetCanJIT (bool can_jit)
{
    m_can_jit = (can_jit ? eCanJITYes : eCanJITNo);
}

Error
Process::DeallocateMemory (addr_t ptr)
{
    Error error;
#if defined (USE_ALLOCATE_MEMORY_CACHE)
    if (!m_allocated_memory_cache.DeallocateMemory(ptr))
    {
        error.SetErrorStringWithFormat ("deallocation of memory at 0x%" PRIx64 " failed.", (uint64_t)ptr);
    }
#else
    error = DoDeallocateMemory (ptr);
    
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf("Process::DeallocateMemory(addr=0x%16.16" PRIx64 ") => err = %s (m_stop_id = %u, m_memory_id = %u)",
                    ptr, 
                    error.AsCString("SUCCESS"),
                    m_mod_id.GetStopID(),
                    m_mod_id.GetMemoryID());
#endif
    return error;
}


ModuleSP
Process::ReadModuleFromMemory (const FileSpec& file_spec, 
                               lldb::addr_t header_addr,
                               size_t size_to_read)
{
    ModuleSP module_sp (new Module (file_spec, ArchSpec()));
    if (module_sp)
    {
        Error error;
        ObjectFile *objfile = module_sp->GetMemoryObjectFile (shared_from_this(), header_addr, error, size_to_read);
        if (objfile)
            return module_sp;
    }
    return ModuleSP();
}

bool
Process::GetLoadAddressPermissions (lldb::addr_t load_addr, uint32_t &permissions)
{
    MemoryRegionInfo range_info;
    permissions = 0;
    Error error (GetMemoryRegionInfo (load_addr, range_info));
    if (!error.Success())
        return false;
    if (range_info.GetReadable() == MemoryRegionInfo::eDontKnow 
        || range_info.GetWritable() == MemoryRegionInfo::eDontKnow 
        || range_info.GetExecutable() == MemoryRegionInfo::eDontKnow)
    {
        return false;
    }

    if (range_info.GetReadable() == MemoryRegionInfo::eYes)
        permissions |= lldb::ePermissionsReadable;

    if (range_info.GetWritable() == MemoryRegionInfo::eYes)
        permissions |= lldb::ePermissionsWritable;

    if (range_info.GetExecutable() == MemoryRegionInfo::eYes)
        permissions |= lldb::ePermissionsExecutable;

    return true;
}

Error
Process::EnableWatchpoint (Watchpoint *watchpoint, bool notify)
{
    Error error;
    error.SetErrorString("watchpoints are not supported");
    return error;
}

Error
Process::DisableWatchpoint (Watchpoint *watchpoint, bool notify)
{
    Error error;
    error.SetErrorString("watchpoints are not supported");
    return error;
}

StateType
Process::WaitForProcessStopPrivate (const TimeValue *timeout, EventSP &event_sp)
{
    StateType state;
    // Now wait for the process to launch and return control to us, and then
    // call DidLaunch:
    while (1)
    {
        event_sp.reset();
        state = WaitForStateChangedEventsPrivate (timeout, event_sp);

        if (StateIsStoppedState(state, false))
            break;

        // If state is invalid, then we timed out
        if (state == eStateInvalid)
            break;

        if (event_sp)
            HandlePrivateEvent (event_sp);
    }
    return state;
}

void
Process::LoadOperatingSystemPlugin(bool flush)
{
    if (flush)
        m_thread_list.Clear();
    m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
    if (flush)
        Flush();
}

Error
Process::Launch (ProcessLaunchInfo &launch_info)
{
    Error error;
    m_abi_sp.reset();
    m_dyld_ap.reset();
    m_jit_loaders_ap.reset();
    m_system_runtime_ap.reset();
    m_os_ap.reset();
    m_process_input_reader.reset();
    m_stop_info_override_callback = NULL;

    Module *exe_module = m_target.GetExecutableModulePointer();
    if (exe_module)
    {
        char local_exec_file_path[PATH_MAX];
        char platform_exec_file_path[PATH_MAX];
        exe_module->GetFileSpec().GetPath(local_exec_file_path, sizeof(local_exec_file_path));
        exe_module->GetPlatformFileSpec().GetPath(platform_exec_file_path, sizeof(platform_exec_file_path));
        if (exe_module->GetFileSpec().Exists())
        {
            // Install anything that might need to be installed prior to launching.
            // For host systems, this will do nothing, but if we are connected to a
            // remote platform it will install any needed binaries
            error = GetTarget().Install(&launch_info);
            if (error.Fail())
                return error;

            if (PrivateStateThreadIsValid ())
                PausePrivateStateThread ();
    
            error = WillLaunch (exe_module);
            if (error.Success())
            {
                const bool restarted = false;
                SetPublicState (eStateLaunching, restarted);
                m_should_detach = false;

                if (m_public_run_lock.TrySetRunning())
                {
                    // Now launch using these arguments.
                    error = DoLaunch (exe_module, launch_info);
                }
                else
                {
                    // This shouldn't happen
                    error.SetErrorString("failed to acquire process run lock");
                }

                if (error.Fail())
                {
                    if (GetID() != LLDB_INVALID_PROCESS_ID)
                    {
                        SetID (LLDB_INVALID_PROCESS_ID);
                        const char *error_string = error.AsCString();
                        if (error_string == NULL)
                            error_string = "launch failed";
                        SetExitStatus (-1, error_string);
                    }
                }
                else
                {
                    EventSP event_sp;
                    TimeValue timeout_time;
                    timeout_time = TimeValue::Now();
                    timeout_time.OffsetWithSeconds(10);
                    StateType state = WaitForProcessStopPrivate(&timeout_time, event_sp);

                    if (state == eStateInvalid || event_sp.get() == NULL)
                    {
                        // We were able to launch the process, but we failed to
                        // catch the initial stop.
                        error.SetErrorString ("failed to catch stop after launch");
                        SetExitStatus (0, "failed to catch stop after launch");
                        Destroy(false);
                    }
                    else if (state == eStateStopped || state == eStateCrashed)
                    {

                        DidLaunch ();

                        DynamicLoader *dyld = GetDynamicLoader ();
                        if (dyld)
                            dyld->DidLaunch();

                        GetJITLoaders().DidLaunch();

                        SystemRuntime *system_runtime = GetSystemRuntime ();
                        if (system_runtime)
                            system_runtime->DidLaunch();

                        LoadOperatingSystemPlugin(false);

                        // Note, the stop event was consumed above, but not handled. This was done
                        // to give DidLaunch a chance to run. The target is either stopped or crashed.
                        // Directly set the state.  This is done to prevent a stop message with a bunch
                        // of spurious output on thread status, as well as not pop a ProcessIOHandler.
                        SetPublicState(state, false);

                        if (PrivateStateThreadIsValid ())
                            ResumePrivateStateThread ();
                        else
                            StartPrivateStateThread ();

                        m_stop_info_override_callback = GetTarget().GetArchitecture().GetStopInfoOverrideCallback();

                        // Target was stopped at entry as was intended. Need to notify the listeners
                        // about it.
                        if (state == eStateStopped && launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
                            HandlePrivateEvent(event_sp);
                    }
                    else if (state == eStateExited)
                    {
                        // We exited while trying to launch somehow.  Don't call DidLaunch as that's
                        // not likely to work, and return an invalid pid.
                        HandlePrivateEvent (event_sp);
                    }
                }
            }
        }
        else
        {
            error.SetErrorStringWithFormat("file doesn't exist: '%s'", local_exec_file_path);
        }
    }
    return error;
}


Error
Process::LoadCore ()
{
    Error error = DoLoadCore();
    if (error.Success())
    {
        Listener listener ("lldb.process.load_core_listener");
        HijackProcessEvents(&listener);

        if (PrivateStateThreadIsValid ())
            ResumePrivateStateThread ();
        else
            StartPrivateStateThread ();

        DynamicLoader *dyld = GetDynamicLoader ();
        if (dyld)
            dyld->DidAttach();

        GetJITLoaders().DidAttach();
        
        SystemRuntime *system_runtime = GetSystemRuntime ();
        if (system_runtime)
            system_runtime->DidAttach();

        m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
        // We successfully loaded a core file, now pretend we stopped so we can
        // show all of the threads in the core file and explore the crashed
        // state.
        SetPrivateState (eStateStopped);

        // Wait indefinitely for a stopped event since we just posted one above...
        lldb::EventSP event_sp;
        listener.WaitForEvent (NULL, event_sp);
        StateType state = ProcessEventData::GetStateFromEvent(event_sp.get());

        if (!StateIsStoppedState (state, false))
        {
            Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
            if (log)
                log->Printf("Process::Halt() failed to stop, state is: %s", StateAsCString(state));
            error.SetErrorString ("Did not get stopped event after loading the core file.");
        }
        RestoreProcessEvents ();
    }
    return error;
}

DynamicLoader *
Process::GetDynamicLoader ()
{
    if (m_dyld_ap.get() == NULL)
        m_dyld_ap.reset (DynamicLoader::FindPlugin(this, NULL));
    return m_dyld_ap.get();
}

const lldb::DataBufferSP
Process::GetAuxvData()
{
    return DataBufferSP ();
}

JITLoaderList &
Process::GetJITLoaders ()
{
    if (!m_jit_loaders_ap)
    {
        m_jit_loaders_ap.reset(new JITLoaderList());
        JITLoader::LoadPlugins(this, *m_jit_loaders_ap);
    }
    return *m_jit_loaders_ap;
}

SystemRuntime *
Process::GetSystemRuntime ()
{
    if (m_system_runtime_ap.get() == NULL)
        m_system_runtime_ap.reset (SystemRuntime::FindPlugin(this));
    return m_system_runtime_ap.get();
}

Process::AttachCompletionHandler::AttachCompletionHandler (Process *process, uint32_t exec_count) :
    NextEventAction (process),
    m_exec_count (exec_count)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf ("Process::AttachCompletionHandler::%s process=%p, exec_count=%" PRIu32, __FUNCTION__, static_cast<void*>(process), exec_count);
}

Process::NextEventAction::EventActionResult
Process::AttachCompletionHandler::PerformAction (lldb::EventSP &event_sp)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    StateType state = ProcessEventData::GetStateFromEvent (event_sp.get());
    if (log)
        log->Printf ("Process::AttachCompletionHandler::%s called with state %s (%d)", __FUNCTION__, StateAsCString(state), static_cast<int> (state));

    switch (state)
    {
        case eStateAttaching:
            return eEventActionSuccess;

        case eStateRunning:
        case eStateConnected:
            return eEventActionRetry;
        
        case eStateStopped:
        case eStateCrashed:
            {
                // During attach, prior to sending the eStateStopped event, 
                // lldb_private::Process subclasses must set the new process ID.
                assert (m_process->GetID() != LLDB_INVALID_PROCESS_ID);
                // We don't want these events to be reported, so go set the ShouldReportStop here:
                m_process->GetThreadList().SetShouldReportStop (eVoteNo);
                
                if (m_exec_count > 0)
                {
                    --m_exec_count;

                    if (log)
                        log->Printf ("Process::AttachCompletionHandler::%s state %s: reduced remaining exec count to %" PRIu32 ", requesting resume", __FUNCTION__, StateAsCString(state), m_exec_count);

                    RequestResume();
                    return eEventActionRetry;
                }
                else
                {
                    if (log)
                        log->Printf ("Process::AttachCompletionHandler::%s state %s: no more execs expected to start, continuing with attach", __FUNCTION__, StateAsCString(state));

                    m_process->CompleteAttach ();
                    return eEventActionSuccess;
                }
            }
            break;

        default:
        case eStateExited:   
        case eStateInvalid:
            break;
    }

    m_exit_string.assign ("No valid Process");
    return eEventActionExit;
}

Process::NextEventAction::EventActionResult
Process::AttachCompletionHandler::HandleBeingInterrupted()
{
    return eEventActionSuccess;
}

const char *
Process::AttachCompletionHandler::GetExitString ()
{
    return m_exit_string.c_str();
}

Listener &
ProcessAttachInfo::GetListenerForProcess (Debugger &debugger)
{
    if (m_listener_sp)
        return *m_listener_sp;
    else
        return debugger.GetListener();
}

Error
Process::Attach (ProcessAttachInfo &attach_info)
{
    m_abi_sp.reset();
    m_process_input_reader.reset();
    m_dyld_ap.reset();
    m_jit_loaders_ap.reset();
    m_system_runtime_ap.reset();
    m_os_ap.reset();
    m_stop_info_override_callback = NULL;
    
    lldb::pid_t attach_pid = attach_info.GetProcessID();
    Error error;
    if (attach_pid == LLDB_INVALID_PROCESS_ID)
    {
        char process_name[PATH_MAX];
        
        if (attach_info.GetExecutableFile().GetPath (process_name, sizeof(process_name)))
        {
            const bool wait_for_launch = attach_info.GetWaitForLaunch();
            
            if (wait_for_launch)
            {
                error = WillAttachToProcessWithName(process_name, wait_for_launch);
                if (error.Success())
                {
                    if (m_public_run_lock.TrySetRunning())
                    {
                        m_should_detach = true;
                        const bool restarted = false;
                        SetPublicState (eStateAttaching, restarted);
                        // Now attach using these arguments.
                        error = DoAttachToProcessWithName (process_name, attach_info);
                    }
                    else
                    {
                        // This shouldn't happen
                        error.SetErrorString("failed to acquire process run lock");
                    }

                    if (error.Fail())
                    {
                        if (GetID() != LLDB_INVALID_PROCESS_ID)
                        {
                            SetID (LLDB_INVALID_PROCESS_ID);
                            if (error.AsCString() == NULL)
                                error.SetErrorString("attach failed");
                            
                            SetExitStatus(-1, error.AsCString());
                        }
                    }
                    else
                    {
                        SetNextEventAction(new Process::AttachCompletionHandler(this, attach_info.GetResumeCount()));
                        StartPrivateStateThread();
                    }
                    return error;
                }
            }
            else
            {
                ProcessInstanceInfoList process_infos;
                PlatformSP platform_sp (m_target.GetPlatform ());
                
                if (platform_sp)
                {
                    ProcessInstanceInfoMatch match_info;
                    match_info.GetProcessInfo() = attach_info;
                    match_info.SetNameMatchType (eNameMatchEquals);
                    platform_sp->FindProcesses (match_info, process_infos);
                    const uint32_t num_matches = process_infos.GetSize();
                    if (num_matches == 1)
                    {
                        attach_pid = process_infos.GetProcessIDAtIndex(0);
                        // Fall through and attach using the above process ID
                    }
                    else
                    {
                        match_info.GetProcessInfo().GetExecutableFile().GetPath (process_name, sizeof(process_name));    
                        if (num_matches > 1)
                        {
                            StreamString s;
                            ProcessInstanceInfo::DumpTableHeader (s, platform_sp.get(), true, false);
                            for (size_t i = 0; i < num_matches; i++)
                            {
                                process_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(s, platform_sp.get(), true, false);
                            }
                            error.SetErrorStringWithFormat ("more than one process named %s:\n%s",
                                                            process_name,
                                                            s.GetData());
                        }
                        else
                            error.SetErrorStringWithFormat ("could not find a process named %s", process_name);
                    }
                }
                else
                {        
                    error.SetErrorString ("invalid platform, can't find processes by name");
                    return error;
                }
            }
        }
        else
        {
            error.SetErrorString ("invalid process name");
        }
    }
    
    if (attach_pid != LLDB_INVALID_PROCESS_ID)
    {
        error = WillAttachToProcessWithID(attach_pid);
        if (error.Success())
        {

            if (m_public_run_lock.TrySetRunning())
            {
                // Now attach using these arguments.
                m_should_detach = true;
                const bool restarted = false;
                SetPublicState (eStateAttaching, restarted);
                error = DoAttachToProcessWithID (attach_pid, attach_info);
            }
            else
            {
                // This shouldn't happen
                error.SetErrorString("failed to acquire process run lock");
            }

            if (error.Success())
            {
                
                SetNextEventAction(new Process::AttachCompletionHandler(this, attach_info.GetResumeCount()));
                StartPrivateStateThread();
            }
            else
            {
                if (GetID() != LLDB_INVALID_PROCESS_ID)
                    SetID (LLDB_INVALID_PROCESS_ID);

                const char *error_string = error.AsCString();
                if (error_string == NULL)
                    error_string = "attach failed";

                SetExitStatus(-1, error_string);
            }
        }
    }
    return error;
}

void
Process::CompleteAttach ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf ("Process::%s()", __FUNCTION__);

    // Let the process subclass figure out at much as it can about the process
    // before we go looking for a dynamic loader plug-in.
    ArchSpec process_arch;
    DidAttach(process_arch);
    
    if (process_arch.IsValid())
    {
        m_target.SetArchitecture(process_arch);
        if (log)
        {
            const char *triple_str = process_arch.GetTriple().getTriple().c_str ();
            log->Printf ("Process::%s replacing process architecture with DidAttach() architecture: %s",
                         __FUNCTION__,
                         triple_str ? triple_str : "<null>");
        }
    }

    // We just attached.  If we have a platform, ask it for the process architecture, and if it isn't
    // the same as the one we've already set, switch architectures.
    PlatformSP platform_sp (m_target.GetPlatform ());
    assert (platform_sp.get());
    if (platform_sp)
    {
        const ArchSpec &target_arch = m_target.GetArchitecture();
        if (target_arch.IsValid() && !platform_sp->IsCompatibleArchitecture (target_arch, false, NULL))
        {
            ArchSpec platform_arch;
            platform_sp = platform_sp->GetPlatformForArchitecture (target_arch, &platform_arch);
            if (platform_sp)
            {
                m_target.SetPlatform (platform_sp);
                m_target.SetArchitecture(platform_arch);
                if (log)
                    log->Printf ("Process::%s switching platform to %s and architecture to %s based on info from attach", __FUNCTION__, platform_sp->GetName().AsCString (""), platform_arch.GetTriple().getTriple().c_str ());
            }
        }
        else if (!process_arch.IsValid())
        {
            ProcessInstanceInfo process_info;
            platform_sp->GetProcessInfo (GetID(), process_info);
            const ArchSpec &process_arch = process_info.GetArchitecture();
            if (process_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(process_arch))
            {
                m_target.SetArchitecture (process_arch);
                if (log)
                    log->Printf ("Process::%s switching architecture to %s based on info the platform retrieved for pid %" PRIu64, __FUNCTION__, process_arch.GetTriple().getTriple().c_str (), GetID ());
            }
        }
    }

    // We have completed the attach, now it is time to find the dynamic loader
    // plug-in
    DynamicLoader *dyld = GetDynamicLoader ();
    if (dyld)
    {
        dyld->DidAttach();
        if (log)
        {
            ModuleSP exe_module_sp = m_target.GetExecutableModule ();
            log->Printf ("Process::%s after DynamicLoader::DidAttach(), target executable is %s (using %s plugin)",
                         __FUNCTION__,
                         exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>",
                         dyld->GetPluginName().AsCString ("<unnamed>"));
        }
    }

    GetJITLoaders().DidAttach();

    SystemRuntime *system_runtime = GetSystemRuntime ();
    if (system_runtime)
    {
        system_runtime->DidAttach();
        if (log)
        {
            ModuleSP exe_module_sp = m_target.GetExecutableModule ();
            log->Printf ("Process::%s after SystemRuntime::DidAttach(), target executable is %s (using %s plugin)",
                         __FUNCTION__,
                         exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>",
                         system_runtime->GetPluginName().AsCString("<unnamed>"));
        }
    }

    m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
    // Figure out which one is the executable, and set that in our target:
    const ModuleList &target_modules = m_target.GetImages();
    Mutex::Locker modules_locker(target_modules.GetMutex());
    size_t num_modules = target_modules.GetSize();
    ModuleSP new_executable_module_sp;
    
    for (size_t i = 0; i < num_modules; i++)
    {
        ModuleSP module_sp (target_modules.GetModuleAtIndexUnlocked (i));
        if (module_sp && module_sp->IsExecutable())
        {
            if (m_target.GetExecutableModulePointer() != module_sp.get())
                new_executable_module_sp = module_sp;
            break;
        }
    }
    if (new_executable_module_sp)
    {
        m_target.SetExecutableModule (new_executable_module_sp, false);
        if (log)
        {
            ModuleSP exe_module_sp = m_target.GetExecutableModule ();
            log->Printf ("Process::%s after looping through modules, target executable is %s",
                         __FUNCTION__,
                         exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>");
        }
    }

    m_stop_info_override_callback = process_arch.GetStopInfoOverrideCallback();
}

Error
Process::ConnectRemote (Stream *strm, const char *remote_url)
{
    m_abi_sp.reset();
    m_process_input_reader.reset();
    
    // Find the process and its architecture.  Make sure it matches the architecture
    // of the current Target, and if not adjust it.
    
    Error error (DoConnectRemote (strm, remote_url));
    if (error.Success())
    {
        if (GetID() != LLDB_INVALID_PROCESS_ID)
        {
            EventSP event_sp;
            StateType state = WaitForProcessStopPrivate(NULL, event_sp);
        
            if (state == eStateStopped || state == eStateCrashed)
            {
                // If we attached and actually have a process on the other end, then 
                // this ended up being the equivalent of an attach.
                CompleteAttach ();
                
                // This delays passing the stopped event to listeners till 
                // CompleteAttach gets a chance to complete...
                HandlePrivateEvent (event_sp);
                
            }
        }

        if (PrivateStateThreadIsValid ())
            ResumePrivateStateThread ();
        else
            StartPrivateStateThread ();
    }
    return error;
}


Error
Process::PrivateResume ()
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_STEP));
    if (log)
        log->Printf("Process::PrivateResume() m_stop_id = %u, public state: %s private state: %s", 
                    m_mod_id.GetStopID(),
                    StateAsCString(m_public_state.GetValue()),
                    StateAsCString(m_private_state.GetValue()));

    Error error (WillResume());
    // Tell the process it is about to resume before the thread list
    if (error.Success())
    {
        // Now let the thread list know we are about to resume so it
        // can let all of our threads know that they are about to be
        // resumed. Threads will each be called with
        // Thread::WillResume(StateType) where StateType contains the state
        // that they are supposed to have when the process is resumed
        // (suspended/running/stepping). Threads should also check
        // their resume signal in lldb::Thread::GetResumeSignal()
        // to see if they are supposed to start back up with a signal.
        if (m_thread_list.WillResume())
        {
            // Last thing, do the PreResumeActions.
            if (!RunPreResumeActions())
            {
                error.SetErrorStringWithFormat ("Process::PrivateResume PreResumeActions failed, not resuming.");
            }
            else
            {
                m_mod_id.BumpResumeID();
                error = DoResume();
                if (error.Success())
                {
                    DidResume();
                    m_thread_list.DidResume();
                    if (log)
                        log->Printf ("Process thinks the process has resumed.");
                }
            }
        }
        else
        {
            // Somebody wanted to run without running (e.g. we were faking a step from one frame of a set of inlined
            // frames that share the same PC to another.)  So generate a continue & a stopped event,
            // and let the world handle them.
            if (log)
                log->Printf ("Process::PrivateResume() asked to simulate a start & stop.");
            
            SetPrivateState(eStateRunning);
            SetPrivateState(eStateStopped);
        }
    }
    else if (log)
        log->Printf ("Process::PrivateResume() got an error \"%s\".", error.AsCString("<unknown error>"));
    return error;
}

Error
Process::Halt (bool clear_thread_plans)
{
    // Don't clear the m_clear_thread_plans_on_stop, only set it to true if
    // in case it was already set and some thread plan logic calls halt on its
    // own.
    m_clear_thread_plans_on_stop |= clear_thread_plans;
    
    // First make sure we aren't in the middle of handling an event, or we might restart.  This is pretty weak, since
    // we could just straightaway get another event.  It just narrows the window...
    m_currently_handling_event.WaitForValueEqualTo(false);

    
    // Pause our private state thread so we can ensure no one else eats
    // the stop event out from under us.
    Listener halt_listener ("lldb.process.halt_listener");
    HijackPrivateProcessEvents(&halt_listener);

    EventSP event_sp;
    Error error (WillHalt());
    
    bool restored_process_events = false;
    if (error.Success())
    {
        
        bool caused_stop = false;
        
        // Ask the process subclass to actually halt our process
        error = DoHalt(caused_stop);
        if (error.Success())
        {
            if (m_public_state.GetValue() == eStateAttaching)
            {
                // Don't hijack and eat the eStateExited as the code that was doing
                // the attach will be waiting for this event...
                RestorePrivateProcessEvents();
                restored_process_events = true;
                SetExitStatus(SIGKILL, "Cancelled async attach.");
                Destroy (false);
            }
            else
            {
                // If "caused_stop" is true, then DoHalt stopped the process. If
                // "caused_stop" is false, the process was already stopped.
                // If the DoHalt caused the process to stop, then we want to catch
                // this event and set the interrupted bool to true before we pass
                // this along so clients know that the process was interrupted by
                // a halt command.
                if (caused_stop)
                {
                    // Wait for 1 second for the process to stop.
                    TimeValue timeout_time;
                    timeout_time = TimeValue::Now();
                    timeout_time.OffsetWithSeconds(10);
                    bool got_event = halt_listener.WaitForEvent (&timeout_time, event_sp);
                    StateType state = ProcessEventData::GetStateFromEvent(event_sp.get());
                    
                    if (!got_event || state == eStateInvalid)
                    {
                        // We timeout out and didn't get a stop event...
                        error.SetErrorStringWithFormat ("Halt timed out. State = %s", StateAsCString(GetState()));
                    }
                    else
                    {
                        if (StateIsStoppedState (state, false))
                        {
                            // We caused the process to interrupt itself, so mark this
                            // as such in the stop event so clients can tell an interrupted
                            // process from a natural stop
                            ProcessEventData::SetInterruptedInEvent (event_sp.get(), true);
                        }
                        else
                        {
                            Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
                            if (log)
                                log->Printf("Process::Halt() failed to stop, state is: %s", StateAsCString(state));
                            error.SetErrorString ("Did not get stopped event after halt.");
                        }
                    }
                }
                DidHalt();
            }
        }
    }
    // Resume our private state thread before we post the event (if any)
    if (!restored_process_events)
        RestorePrivateProcessEvents();

    // Post any event we might have consumed. If all goes well, we will have
    // stopped the process, intercepted the event and set the interrupted
    // bool in the event.  Post it to the private event queue and that will end up
    // correctly setting the state.
    if (event_sp)
        m_private_state_broadcaster.BroadcastEvent(event_sp);

    return error;
}

Error
Process::HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp)
{
    Error error;
    if (m_public_state.GetValue() == eStateRunning)
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
        if (log)
            log->Printf("Process::Destroy() About to halt.");
        error = Halt();
        if (error.Success())
        {
            // Consume the halt event.
            TimeValue timeout (TimeValue::Now());
            timeout.OffsetWithSeconds(1);
            StateType state = WaitForProcessToStop (&timeout, &exit_event_sp);
            
            // If the process exited while we were waiting for it to stop, put the exited event into
            // the shared pointer passed in and return.  Our caller doesn't need to do anything else, since
            // they don't have a process anymore...
            
            if (state == eStateExited || m_private_state.GetValue() == eStateExited)
            {
                if (log)
                    log->Printf("Process::HaltForDestroyOrDetach() Process exited while waiting to Halt.");
                return error;
            }
            else
                exit_event_sp.reset(); // It is ok to consume any non-exit stop events
    
            if (state != eStateStopped)
            {
                if (log)
                    log->Printf("Process::HaltForDestroyOrDetach() Halt failed to stop, state is: %s", StateAsCString(state));
                // If we really couldn't stop the process then we should just error out here, but if the
                // lower levels just bobbled sending the event and we really are stopped, then continue on.
                StateType private_state = m_private_state.GetValue();
                if (private_state != eStateStopped)
                {
                    return error;
                }
            }
        }
        else
        {
            if (log)
                log->Printf("Process::HaltForDestroyOrDetach() Halt got error: %s", error.AsCString());
        }
    }
    return error;
}

Error
Process::Detach (bool keep_stopped)
{
    EventSP exit_event_sp;
    Error error;
    m_destroy_in_process = true;
    
    error = WillDetach();

    if (error.Success())
    {
        if (DetachRequiresHalt())
        {
            error = HaltForDestroyOrDetach (exit_event_sp);
            if (!error.Success())
            {
                m_destroy_in_process = false;
                return error;
            }
            else if (exit_event_sp)
            {
                // We shouldn't need to do anything else here.  There's no process left to detach from...
                StopPrivateStateThread();
                m_destroy_in_process = false;
                return error;
            }
        }
    
        m_thread_list.DiscardThreadPlans();
        DisableAllBreakpointSites();

        error = DoDetach(keep_stopped);
        if (error.Success())
        {
            DidDetach();
            StopPrivateStateThread();
        }
        else
        {
            return error;
        }
    }
    m_destroy_in_process = false;
    
    // If we exited when we were waiting for a process to stop, then
    // forward the event here so we don't lose the event
    if (exit_event_sp)
    {
        // Directly broadcast our exited event because we shut down our
        // private state thread above
        BroadcastEvent(exit_event_sp);
    }

    // If we have been interrupted (to kill us) in the middle of running, we may not end up propagating
    // the last events through the event system, in which case we might strand the write lock.  Unlock
    // it here so when we do to tear down the process we don't get an error destroying the lock.
    
    m_public_run_lock.SetStopped();
    return error;
}

Error
Process::Destroy (bool force_kill)
{
    
    // Tell ourselves we are in the process of destroying the process, so that we don't do any unnecessary work
    // that might hinder the destruction.  Remember to set this back to false when we are done.  That way if the attempt
    // failed and the process stays around for some reason it won't be in a confused state.

    if (force_kill)
        m_should_detach = false;
    
    if (GetShouldDetach())
    {
        // FIXME: This will have to be a process setting:
        bool keep_stopped = false;
        Detach(keep_stopped);
    }

    m_destroy_in_process = true;

    Error error (WillDestroy());
    if (error.Success())
    {
        EventSP exit_event_sp;
        if (DestroyRequiresHalt())
        {
            error = HaltForDestroyOrDetach(exit_event_sp);
        }
        
        if (m_public_state.GetValue() != eStateRunning)
        {
            // Ditch all thread plans, and remove all our breakpoints: in case we have to restart the target to
            // kill it, we don't want it hitting a breakpoint...
            // Only do this if we've stopped, however, since if we didn't manage to halt it above, then
            // we're not going to have much luck doing this now.
            m_thread_list.DiscardThreadPlans();
            DisableAllBreakpointSites();
        }

        error = DoDestroy();
        if (error.Success())
        {
            DidDestroy();
            StopPrivateStateThread();
        }
        m_stdio_communication.StopReadThread();
        m_stdio_communication.Disconnect();
        m_stdin_forward = false;

        if (m_process_input_reader)
        {
            m_process_input_reader->SetIsDone(true);
            m_process_input_reader->Cancel();
            m_process_input_reader.reset();
        }

        // If we exited when we were waiting for a process to stop, then
        // forward the event here so we don't lose the event
        if (exit_event_sp)
        {
            // Directly broadcast our exited event because we shut down our
            // private state thread above
            BroadcastEvent(exit_event_sp);
        }

        // If we have been interrupted (to kill us) in the middle of running, we may not end up propagating
        // the last events through the event system, in which case we might strand the write lock.  Unlock
        // it here so when we do to tear down the process we don't get an error destroying the lock.
        m_public_run_lock.SetStopped();
    }
    
    m_destroy_in_process = false;
    
    return error;
}

Error
Process::Signal (int signal)
{
    Error error (WillSignal());
    if (error.Success())
    {
        error = DoSignal(signal);
        if (error.Success())
            DidSignal();
    }
    return error;
}

void
Process::SetUnixSignals (const UnixSignalsSP &signals_sp)
{
    assert (signals_sp && "null signals_sp");
    m_unix_signals_sp = signals_sp;
}

UnixSignals &
Process::GetUnixSignals ()
{
    assert (m_unix_signals_sp && "null m_unix_signals_sp");
    return *m_unix_signals_sp;
}

lldb::ByteOrder
Process::GetByteOrder () const
{
    return m_target.GetArchitecture().GetByteOrder();
}

uint32_t
Process::GetAddressByteSize () const
{
    return m_target.GetArchitecture().GetAddressByteSize();
}


bool
Process::ShouldBroadcastEvent (Event *event_ptr)
{
    const StateType state = Process::ProcessEventData::GetStateFromEvent (event_ptr);
    bool return_value = true;
    Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS | LIBLLDB_LOG_PROCESS));
    
    switch (state)
    {
        case eStateDetached:
        case eStateExited:
        case eStateUnloaded:
            m_stdio_communication.SynchronizeWithReadThread();
            // fall-through
        case eStateConnected:
        case eStateAttaching:
        case eStateLaunching:
            // These events indicate changes in the state of the debugging session, always report them.
            return_value = true;
            break;
        case eStateInvalid:
            // We stopped for no apparent reason, don't report it.
            return_value = false;
            break;
        case eStateRunning:
        case eStateStepping:
            // If we've started the target running, we handle the cases where we
            // are already running and where there is a transition from stopped to
            // running differently.
            // running -> running: Automatically suppress extra running events
            // stopped -> running: Report except when there is one or more no votes
            //     and no yes votes.
            SynchronouslyNotifyStateChanged (state);
            if (m_force_next_event_delivery)
                return_value = true;
            else
            {
                switch (m_last_broadcast_state)
                {
                    case eStateRunning:
                    case eStateStepping:
                        // We always suppress multiple runnings with no PUBLIC stop in between.
                        return_value = false;
                        break;
                    default:
                        // TODO: make this work correctly. For now always report
                        // run if we aren't running so we don't miss any running
                        // events. If I run the lldb/test/thread/a.out file and
                        // break at main.cpp:58, run and hit the breakpoints on
                        // multiple threads, then somehow during the stepping over
                        // of all breakpoints no run gets reported.

                        // This is a transition from stop to run.
                        switch (m_thread_list.ShouldReportRun (event_ptr))
                        {
                            case eVoteYes:
                            case eVoteNoOpinion:
                                return_value = true;
                                break;
                            case eVoteNo:
                                return_value = false;
                                break;
                        }
                        break;
                }
            }
            break;
        case eStateStopped:
        case eStateCrashed:
        case eStateSuspended:
        {
            // We've stopped.  First see if we're going to restart the target.
            // If we are going to stop, then we always broadcast the event.
            // If we aren't going to stop, let the thread plans decide if we're going to report this event.
            // If no thread has an opinion, we don't report it.

            m_stdio_communication.SynchronizeWithReadThread();
            RefreshStateAfterStop ();
            if (ProcessEventData::GetInterruptedFromEvent (event_ptr))
            {
                if (log)
                    log->Printf ("Process::ShouldBroadcastEvent (%p) stopped due to an interrupt, state: %s",
                                 static_cast<void*>(event_ptr),
                                 StateAsCString(state));
                // Even though we know we are going to stop, we should let the threads have a look at the stop,
                // so they can properly set their state.
                m_thread_list.ShouldStop (event_ptr);
                return_value = true;
            }
            else
            {
                bool was_restarted = ProcessEventData::GetRestartedFromEvent (event_ptr);
                bool should_resume = false;

                // It makes no sense to ask "ShouldStop" if we've already been restarted...
                // Asking the thread list is also not likely to go well, since we are running again.
                // So in that case just report the event.

                if (!was_restarted)
                    should_resume = m_thread_list.ShouldStop (event_ptr) == false;

                if (was_restarted || should_resume || m_resume_requested)
                {
                    Vote stop_vote = m_thread_list.ShouldReportStop (event_ptr);
                    if (log)
                        log->Printf ("Process::ShouldBroadcastEvent: should_stop: %i state: %s was_restarted: %i stop_vote: %d.",
                                     should_resume, StateAsCString(state),
                                     was_restarted, stop_vote);

                    switch (stop_vote)
                    {
                        case eVoteYes:
                            return_value = true;
                            break;
                        case eVoteNoOpinion:
                        case eVoteNo:
                            return_value = false;
                            break;
                    }

                    if (!was_restarted)
                    {
                        if (log)
                            log->Printf ("Process::ShouldBroadcastEvent (%p) Restarting process from state: %s",
                                         static_cast<void*>(event_ptr),
                                         StateAsCString(state));
                        ProcessEventData::SetRestartedInEvent(event_ptr, true);
                        PrivateResume ();
                    }

                }
                else
                {
                    return_value = true;
                    SynchronouslyNotifyStateChanged (state);
                }
            }
        }
        break;
    }

    // Forcing the next event delivery is a one shot deal.  So reset it here.
    m_force_next_event_delivery = false;

    // We do some coalescing of events (for instance two consecutive running events get coalesced.)
    // But we only coalesce against events we actually broadcast.  So we use m_last_broadcast_state
    // to track that.  NB - you can't use "m_public_state.GetValue()" for that purpose, as was originally done,
    // because the PublicState reflects the last event pulled off the queue, and there may be several
    // events stacked up on the queue unserviced.  So the PublicState may not reflect the last broadcasted event
    // yet.  m_last_broadcast_state gets updated here.

    if (return_value)
        m_last_broadcast_state = state;

    if (log)
        log->Printf ("Process::ShouldBroadcastEvent (%p) => new state: %s, last broadcast state: %s - %s",
                     static_cast<void*>(event_ptr), StateAsCString(state),
                     StateAsCString(m_last_broadcast_state),
                     return_value ? "YES" : "NO");
    return return_value;
}


bool
Process::StartPrivateStateThread (bool force)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));

    bool already_running = PrivateStateThreadIsValid ();
    if (log)
        log->Printf ("Process::%s()%s ", __FUNCTION__, already_running ? " already running" : " starting private state thread");

    if (!force && already_running)
        return true;

    // Create a thread that watches our internal state and controls which
    // events make it to clients (into the DCProcess event queue).
    char thread_name[1024];

    if (HostInfo::GetMaxThreadNameLength() <= 30)
    {
        // On platforms with abbreviated thread name lengths, choose thread names that fit within the limit.
        if (already_running)
            snprintf(thread_name, sizeof(thread_name), "intern-state-OV");
        else
            snprintf(thread_name, sizeof(thread_name), "intern-state");
    }
    else
    {
        if (already_running)
            snprintf(thread_name, sizeof(thread_name), "<lldb.process.internal-state-override(pid=%" PRIu64 ")>", GetID());
        else
            snprintf(thread_name, sizeof(thread_name), "<lldb.process.internal-state(pid=%" PRIu64 ")>", GetID());
    }

    // Create the private state thread, and start it running.
    m_private_state_thread = ThreadLauncher::LaunchThread(thread_name, Process::PrivateStateThread, this, NULL);
    if (m_private_state_thread.IsJoinable())
    {
        ResumePrivateStateThread();
        return true;
    }
    else
        return false;
}

void
Process::PausePrivateStateThread ()
{
    ControlPrivateStateThread (eBroadcastInternalStateControlPause);
}

void
Process::ResumePrivateStateThread ()
{
    ControlPrivateStateThread (eBroadcastInternalStateControlResume);
}

void
Process::StopPrivateStateThread ()
{
    if (PrivateStateThreadIsValid ())
        ControlPrivateStateThread (eBroadcastInternalStateControlStop);
    else
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
        if (log)
            log->Printf ("Went to stop the private state thread, but it was already invalid.");
    }
}

void
Process::ControlPrivateStateThread (uint32_t signal)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

    assert (signal == eBroadcastInternalStateControlStop ||
            signal == eBroadcastInternalStateControlPause ||
            signal == eBroadcastInternalStateControlResume);

    if (log)
        log->Printf ("Process::%s (signal = %d)", __FUNCTION__, signal);

    // Signal the private state thread. First we should copy this is case the
    // thread starts exiting since the private state thread will NULL this out
    // when it exits
    HostThread private_state_thread(m_private_state_thread);
    if (private_state_thread.IsJoinable())
    {
        TimeValue timeout_time;
        bool timed_out;

        m_private_state_control_broadcaster.BroadcastEvent (signal, NULL);

        timeout_time = TimeValue::Now();
        timeout_time.OffsetWithSeconds(2);
        if (log)
            log->Printf ("Sending control event of type: %d.", signal);
        m_private_state_control_wait.WaitForValueEqualTo (true, &timeout_time, &timed_out);
        m_private_state_control_wait.SetValue (false, eBroadcastNever);

        if (signal == eBroadcastInternalStateControlStop)
        {
            if (timed_out)
            {
                Error error = private_state_thread.Cancel();
                if (log)
                    log->Printf ("Timed out responding to the control event, cancel got error: \"%s\".", error.AsCString());
            }
            else
            {
                if (log)
                    log->Printf ("The control event killed the private state thread without having to cancel.");
            }

            thread_result_t result = NULL;
            private_state_thread.Join(&result);
            m_private_state_thread.Reset();
        }
    }
    else
    {
        if (log)
            log->Printf ("Private state thread already dead, no need to signal it to stop.");
    }
}

void
Process::SendAsyncInterrupt ()
{
    if (PrivateStateThreadIsValid())
        m_private_state_broadcaster.BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
    else
        BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
}

void
Process::HandlePrivateEvent (EventSP &event_sp)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    m_resume_requested = false;
    
    m_currently_handling_event.SetValue(true, eBroadcastNever);
    
    const StateType new_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
    
    // First check to see if anybody wants a shot at this event:
    if (m_next_event_action_ap.get() != NULL)
    {
        NextEventAction::EventActionResult action_result = m_next_event_action_ap->PerformAction(event_sp);
        if (log)
            log->Printf ("Ran next event action, result was %d.", action_result);
        
        switch (action_result)
        {
            case NextEventAction::eEventActionSuccess:
                SetNextEventAction(NULL);
                break;

            case NextEventAction::eEventActionRetry:
                break;

            case NextEventAction::eEventActionExit:
                // Handle Exiting Here.  If we already got an exited event,
                // we should just propagate it.  Otherwise, swallow this event,
                // and set our state to exit so the next event will kill us.
                if (new_state != eStateExited)
                {
                    // FIXME: should cons up an exited event, and discard this one.
                    SetExitStatus(0, m_next_event_action_ap->GetExitString());
                    m_currently_handling_event.SetValue(false, eBroadcastAlways);
                    SetNextEventAction(NULL);
                    return;
                }
                SetNextEventAction(NULL);
                break;
        }
    }
    
    // See if we should broadcast this state to external clients?
    const bool should_broadcast = ShouldBroadcastEvent (event_sp.get());

    if (should_broadcast)
    {
        const bool is_hijacked = IsHijackedForEvent(eBroadcastBitStateChanged);
        if (log)
        {
            log->Printf ("Process::%s (pid = %" PRIu64 ") broadcasting new state %s (old state %s) to %s",
                         __FUNCTION__, 
                         GetID(), 
                         StateAsCString(new_state), 
                         StateAsCString (GetState ()),
                         is_hijacked ? "hijacked" : "public");
        }
        Process::ProcessEventData::SetUpdateStateOnRemoval(event_sp.get());
        if (StateIsRunningState (new_state))
        {
            // Only push the input handler if we aren't fowarding events,
            // as this means the curses GUI is in use...
            // Or don't push it if we are launching since it will come up stopped.
            if (!GetTarget().GetDebugger().IsForwardingEvents() && new_state != eStateLaunching &&
                new_state != eStateAttaching)
            {
                PushProcessIOHandler ();
                m_iohandler_sync.SetValue(m_iohandler_sync.GetValue()+1, eBroadcastAlways);
                if (log)
                    log->Printf("Process::%s updated m_iohandler_sync to %d", __FUNCTION__, m_iohandler_sync.GetValue());
            }
        }
        else if (StateIsStoppedState(new_state, false))
        {
            if (!Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
            {
                // If the lldb_private::Debugger is handling the events, we don't
                // want to pop the process IOHandler here, we want to do it when
                // we receive the stopped event so we can carefully control when
                // the process IOHandler is popped because when we stop we want to
                // display some text stating how and why we stopped, then maybe some
                // process/thread/frame info, and then we want the "(lldb) " prompt
                // to show up. If we pop the process IOHandler here, then we will
                // cause the command interpreter to become the top IOHandler after
                // the process pops off and it will update its prompt right away...
                // See the Debugger.cpp file where it calls the function as
                // "process_sp->PopProcessIOHandler()" to see where I am talking about.
                // Otherwise we end up getting overlapping "(lldb) " prompts and
                // garbled output.
                //
                // If we aren't handling the events in the debugger (which is indicated
                // by "m_target.GetDebugger().IsHandlingEvents()" returning false) or we
                // are hijacked, then we always pop the process IO handler manually.
                // Hijacking happens when the internal process state thread is running
                // thread plans, or when commands want to run in synchronous mode
                // and they call "process->WaitForProcessToStop()". An example of something
                // that will hijack the events is a simple expression:
                //
                //  (lldb) expr (int)puts("hello")
                //
                // This will cause the internal process state thread to resume and halt
                // the process (and _it_ will hijack the eBroadcastBitStateChanged
                // events) and we do need the IO handler to be pushed and popped
                // correctly.
                
                if (is_hijacked || m_target.GetDebugger().IsHandlingEvents() == false)
                    PopProcessIOHandler ();
            }
        }

        BroadcastEvent (event_sp);
    }
    else
    {
        if (log)
        {
            log->Printf ("Process::%s (pid = %" PRIu64 ") suppressing state %s (old state %s): should_broadcast == false",
                         __FUNCTION__, 
                         GetID(), 
                         StateAsCString(new_state), 
                         StateAsCString (GetState ()));
        }
    }
    m_currently_handling_event.SetValue(false, eBroadcastAlways);
}

thread_result_t
Process::PrivateStateThread (void *arg)
{
    Process *proc = static_cast<Process*> (arg);
    thread_result_t result = proc->RunPrivateStateThread();
    return result;
}

thread_result_t
Process::RunPrivateStateThread ()
{
    bool control_only = true;
    m_private_state_control_wait.SetValue (false, eBroadcastNever);

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") thread starting...",
                     __FUNCTION__, static_cast<void*>(this), GetID());

    bool exit_now = false;
    while (!exit_now)
    {
        EventSP event_sp;
        WaitForEventsPrivate (NULL, event_sp, control_only);
        if (event_sp->BroadcasterIs(&m_private_state_control_broadcaster))
        {
            if (log)
                log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") got a control event: %d",
                             __FUNCTION__, static_cast<void*>(this), GetID(),
                             event_sp->GetType());

            switch (event_sp->GetType())
            {
            case eBroadcastInternalStateControlStop:
                exit_now = true;
                break;      // doing any internal state management below

            case eBroadcastInternalStateControlPause:
                control_only = true;
                break;

            case eBroadcastInternalStateControlResume:
                control_only = false;
                break;
            }

            m_private_state_control_wait.SetValue (true, eBroadcastAlways);
            continue;
        }
        else if (event_sp->GetType() == eBroadcastBitInterrupt)
        {
            if (m_public_state.GetValue() == eStateAttaching)
            {
                if (log)
                    log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") woke up with an interrupt while attaching - forwarding interrupt.",
                                 __FUNCTION__, static_cast<void*>(this),
                                 GetID());
                BroadcastEvent (eBroadcastBitInterrupt, NULL);
            }
            else
            {
                if (log)
                    log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") woke up with an interrupt - Halting.",
                                 __FUNCTION__, static_cast<void*>(this),
                                 GetID());
                Halt();
            }
            continue;
        }

        const StateType internal_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());

        if (internal_state != eStateInvalid)
        {
            if (m_clear_thread_plans_on_stop &&
                StateIsStoppedState(internal_state, true))
            {
                m_clear_thread_plans_on_stop = false;
                m_thread_list.DiscardThreadPlans();
            }
            HandlePrivateEvent (event_sp);
        }

        if (internal_state == eStateInvalid || 
            internal_state == eStateExited  ||
            internal_state == eStateDetached )
        {
            if (log)
                log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") about to exit with internal state %s...",
                             __FUNCTION__, static_cast<void*>(this), GetID(),
                             StateAsCString(internal_state));

            break;
        }
    }

    // Verify log is still enabled before attempting to write to it...
    if (log)
        log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") thread exiting...",
                     __FUNCTION__, static_cast<void*>(this), GetID());

    m_public_run_lock.SetStopped();
    m_private_state_control_wait.SetValue (true, eBroadcastAlways);
    m_private_state_thread.Reset();
    return NULL;
}

//------------------------------------------------------------------
// Process Event Data
//------------------------------------------------------------------

Process::ProcessEventData::ProcessEventData () :
    EventData (),
    m_process_wp (),
    m_state (eStateInvalid),
    m_restarted (false),
    m_update_state (0),
    m_interrupted (false)
{
}

Process::ProcessEventData::ProcessEventData (const ProcessSP &process_sp, StateType state) :
    EventData (),
    m_process_wp (),
    m_state (state),
    m_restarted (false),
    m_update_state (0),
    m_interrupted (false)
{
    if (process_sp)
        m_process_wp = process_sp;
}

Process::ProcessEventData::~ProcessEventData()
{
}

const ConstString &
Process::ProcessEventData::GetFlavorString ()
{
    static ConstString g_flavor ("Process::ProcessEventData");
    return g_flavor;
}

const ConstString &
Process::ProcessEventData::GetFlavor () const
{
    return ProcessEventData::GetFlavorString ();
}

void
Process::ProcessEventData::DoOnRemoval (Event *event_ptr)
{
    ProcessSP process_sp(m_process_wp.lock());
    
    if (!process_sp)
        return;
    
    // This function gets called twice for each event, once when the event gets pulled 
    // off of the private process event queue, and then any number of times, first when it gets pulled off of
    // the public event queue, then other times when we're pretending that this is where we stopped at the
    // end of expression evaluation.  m_update_state is used to distinguish these
    // three cases; it is 0 when we're just pulling it off for private handling, 
    // and > 1 for expression evaluation, and we don't want to do the breakpoint command handling then.    
    if (m_update_state != 1)
        return;
    
    process_sp->SetPublicState (m_state, Process::ProcessEventData::GetRestartedFromEvent(event_ptr));
    
    // If this is a halt event, even if the halt stopped with some reason other than a plain interrupt (e.g. we had
    // already stopped for a breakpoint when the halt request came through) don't do the StopInfo actions, as they may
    // end up restarting the process.
    if (m_interrupted)
        return;
    
    // If we're stopped and haven't restarted, then do the StopInfo actions here:
    if (m_state == eStateStopped && ! m_restarted)
    {        
        ThreadList &curr_thread_list = process_sp->GetThreadList();
        uint32_t num_threads = curr_thread_list.GetSize();
        uint32_t idx;

        // The actions might change one of the thread's stop_info's opinions about whether we should
        // stop the process, so we need to query that as we go.
        
        // One other complication here, is that we try to catch any case where the target has run (except for expressions)
        // and immediately exit, but if we get that wrong (which is possible) then the thread list might have changed, and
        // that would cause our iteration here to crash.  We could make a copy of the thread list, but we'd really like
        // to also know if it has changed at all, so we make up a vector of the thread ID's and check what we get back 
        // against this list & bag out if anything differs.
        std::vector<uint32_t> thread_index_array(num_threads);
        for (idx = 0; idx < num_threads; ++idx)
            thread_index_array[idx] = curr_thread_list.GetThreadAtIndex(idx)->GetIndexID();
        
        // Use this to track whether we should continue from here.  We will only continue the target running if
        // no thread says we should stop.  Of course if some thread's PerformAction actually sets the target running,
        // then it doesn't matter what the other threads say...
        
        bool still_should_stop = false;
        
        // Sometimes - for instance if we have a bug in the stub we are talking to, we stop but no thread has a
        // valid stop reason.  In that case we should just stop, because we have no way of telling what the right
        // thing to do is, and it's better to let the user decide than continue behind their backs.
        
        bool does_anybody_have_an_opinion = false;
        
        for (idx = 0; idx < num_threads; ++idx)
        {
            curr_thread_list = process_sp->GetThreadList();
            if (curr_thread_list.GetSize() != num_threads)
            {
                Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS));
                if (log)
                    log->Printf("Number of threads changed from %u to %u while processing event.", num_threads, curr_thread_list.GetSize());
                break;
            }
            
            lldb::ThreadSP thread_sp = curr_thread_list.GetThreadAtIndex(idx);
            
            if (thread_sp->GetIndexID() != thread_index_array[idx])
            {
                Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS));
                if (log)
                    log->Printf("The thread at position %u changed from %u to %u while processing event.", 
                                idx, 
                                thread_index_array[idx],
                                thread_sp->GetIndexID());
                break;
            }
            
            StopInfoSP stop_info_sp = thread_sp->GetStopInfo ();
            if (stop_info_sp && stop_info_sp->IsValid())
            {
                does_anybody_have_an_opinion = true;
                bool this_thread_wants_to_stop;
                if (stop_info_sp->GetOverrideShouldStop())
                {
                    this_thread_wants_to_stop = stop_info_sp->GetOverriddenShouldStopValue();
                }
                else
                {
                    stop_info_sp->PerformAction(event_ptr);
                    // The stop action might restart the target.  If it does, then we want to mark that in the
                    // event so that whoever is receiving it will know to wait for the running event and reflect
                    // that state appropriately.
                    // We also need to stop processing actions, since they aren't expecting the target to be running.
                    
                    // FIXME: we might have run.
                    if (stop_info_sp->HasTargetRunSinceMe())
                    {
                        SetRestarted (true);
                        break;
                    }
                    
                    this_thread_wants_to_stop = stop_info_sp->ShouldStop(event_ptr);
                }
                
                if (still_should_stop == false)
                    still_should_stop = this_thread_wants_to_stop;
            }
        }

        
        if (!GetRestarted())
        {
            if (!still_should_stop && does_anybody_have_an_opinion)
            {
                // We've been asked to continue, so do that here.
                SetRestarted(true);
                // Use the public resume method here, since this is just
                // extending a public resume.
                process_sp->PrivateResume();
            }
            else
            {
                // If we didn't restart, run the Stop Hooks here:
                // They might also restart the target, so watch for that.
                process_sp->GetTarget().RunStopHooks();
                if (process_sp->GetPrivateState() == eStateRunning)
                    SetRestarted(true);
            }
        }
    }
}

void
Process::ProcessEventData::Dump (Stream *s) const
{
    ProcessSP process_sp(m_process_wp.lock());

    if (process_sp)
        s->Printf(" process = %p (pid = %" PRIu64 "), ",
                  static_cast<void*>(process_sp.get()), process_sp->GetID());
    else
        s->PutCString(" process = NULL, ");

    s->Printf("state = %s", StateAsCString(GetState()));
}

const Process::ProcessEventData *
Process::ProcessEventData::GetEventDataFromEvent (const Event *event_ptr)
{
    if (event_ptr)
    {
        const EventData *event_data = event_ptr->GetData();
        if (event_data && event_data->GetFlavor() == ProcessEventData::GetFlavorString())
            return static_cast <const ProcessEventData *> (event_ptr->GetData());
    }
    return NULL;
}

ProcessSP
Process::ProcessEventData::GetProcessFromEvent (const Event *event_ptr)
{
    ProcessSP process_sp;
    const ProcessEventData *data = GetEventDataFromEvent (event_ptr);
    if (data)
        process_sp = data->GetProcessSP();
    return process_sp;
}

StateType
Process::ProcessEventData::GetStateFromEvent (const Event *event_ptr)
{
    const ProcessEventData *data = GetEventDataFromEvent (event_ptr);
    if (data == NULL)
        return eStateInvalid;
    else
        return data->GetState();
}

bool
Process::ProcessEventData::GetRestartedFromEvent (const Event *event_ptr)
{
    const ProcessEventData *data = GetEventDataFromEvent (event_ptr);
    if (data == NULL)
        return false;
    else
        return data->GetRestarted();
}

void
Process::ProcessEventData::SetRestartedInEvent (Event *event_ptr, bool new_value)
{
    ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr));
    if (data != NULL)
        data->SetRestarted(new_value);
}

size_t
Process::ProcessEventData::GetNumRestartedReasons(const Event *event_ptr)
{
    ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr));
    if (data != NULL)
        return data->GetNumRestartedReasons();
    else
        return 0;
}

const char *
Process::ProcessEventData::GetRestartedReasonAtIndex(const Event *event_ptr, size_t idx)
{
    ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr));
    if (data != NULL)
        return data->GetRestartedReasonAtIndex(idx);
    else
        return NULL;
}

void
Process::ProcessEventData::AddRestartedReason (Event *event_ptr, const char *reason)
{
    ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr));
    if (data != NULL)
        data->AddRestartedReason(reason);
}

bool
Process::ProcessEventData::GetInterruptedFromEvent (const Event *event_ptr)
{
    const ProcessEventData *data = GetEventDataFromEvent (event_ptr);
    if (data == NULL)
        return false;
    else
        return data->GetInterrupted ();
}

void
Process::ProcessEventData::SetInterruptedInEvent (Event *event_ptr, bool new_value)
{
    ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr));
    if (data != NULL)
        data->SetInterrupted(new_value);
}

bool
Process::ProcessEventData::SetUpdateStateOnRemoval (Event *event_ptr)
{
    ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr));
    if (data)
    {
        data->SetUpdateStateOnRemoval();
        return true;
    }
    return false;
}

lldb::TargetSP
Process::CalculateTarget ()
{
    return m_target.shared_from_this();
}

void
Process::CalculateExecutionContext (ExecutionContext &exe_ctx)
{
    exe_ctx.SetTargetPtr (&m_target);
    exe_ctx.SetProcessPtr (this);
    exe_ctx.SetThreadPtr(NULL);
    exe_ctx.SetFramePtr (NULL);
}

//uint32_t
//Process::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
//{
//    return 0;
//}
//    
//ArchSpec
//Process::GetArchSpecForExistingProcess (lldb::pid_t pid)
//{
//    return Host::GetArchSpecForExistingProcess (pid);
//}
//
//ArchSpec
//Process::GetArchSpecForExistingProcess (const char *process_name)
//{
//    return Host::GetArchSpecForExistingProcess (process_name);
//}
//
void
Process::AppendSTDOUT (const char * s, size_t len)
{
    Mutex::Locker locker (m_stdio_communication_mutex);
    m_stdout_data.append (s, len);
    BroadcastEventIfUnique (eBroadcastBitSTDOUT, new ProcessEventData (shared_from_this(), GetState()));
}

void
Process::AppendSTDERR (const char * s, size_t len)
{
    Mutex::Locker locker (m_stdio_communication_mutex);
    m_stderr_data.append (s, len);
    BroadcastEventIfUnique (eBroadcastBitSTDERR, new ProcessEventData (shared_from_this(), GetState()));
}

void
Process::BroadcastAsyncProfileData(const std::string &one_profile_data)
{
    Mutex::Locker locker (m_profile_data_comm_mutex);
    m_profile_data.push_back(one_profile_data);
    BroadcastEventIfUnique (eBroadcastBitProfileData, new ProcessEventData (shared_from_this(), GetState()));
}

size_t
Process::GetAsyncProfileData (char *buf, size_t buf_size, Error &error)
{
    Mutex::Locker locker(m_profile_data_comm_mutex);
    if (m_profile_data.empty())
        return 0;
    
    std::string &one_profile_data = m_profile_data.front();
    size_t bytes_available = one_profile_data.size();
    if (bytes_available > 0)
    {
        Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
        if (log)
            log->Printf ("Process::GetProfileData (buf = %p, size = %" PRIu64 ")",
                         static_cast<void*>(buf),
                         static_cast<uint64_t>(buf_size));
        if (bytes_available > buf_size)
        {
            memcpy(buf, one_profile_data.c_str(), buf_size);
            one_profile_data.erase(0, buf_size);
            bytes_available = buf_size;
        }
        else
        {
            memcpy(buf, one_profile_data.c_str(), bytes_available);
            m_profile_data.erase(m_profile_data.begin());
        }
    }
    return bytes_available;
}


//------------------------------------------------------------------
// Process STDIO
//------------------------------------------------------------------

size_t
Process::GetSTDOUT (char *buf, size_t buf_size, Error &error)
{
    Mutex::Locker locker(m_stdio_communication_mutex);
    size_t bytes_available = m_stdout_data.size();
    if (bytes_available > 0)
    {
        Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
        if (log)
            log->Printf ("Process::GetSTDOUT (buf = %p, size = %" PRIu64 ")",
                         static_cast<void*>(buf),
                         static_cast<uint64_t>(buf_size));
        if (bytes_available > buf_size)
        {
            memcpy(buf, m_stdout_data.c_str(), buf_size);
            m_stdout_data.erase(0, buf_size);
            bytes_available = buf_size;
        }
        else
        {
            memcpy(buf, m_stdout_data.c_str(), bytes_available);
            m_stdout_data.clear();
        }
    }
    return bytes_available;
}


size_t
Process::GetSTDERR (char *buf, size_t buf_size, Error &error)
{
    Mutex::Locker locker(m_stdio_communication_mutex);
    size_t bytes_available = m_stderr_data.size();
    if (bytes_available > 0)
    {
        Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
        if (log)
            log->Printf ("Process::GetSTDERR (buf = %p, size = %" PRIu64 ")",
                         static_cast<void*>(buf),
                         static_cast<uint64_t>(buf_size));
        if (bytes_available > buf_size)
        {
            memcpy(buf, m_stderr_data.c_str(), buf_size);
            m_stderr_data.erase(0, buf_size);
            bytes_available = buf_size;
        }
        else
        {
            memcpy(buf, m_stderr_data.c_str(), bytes_available);
            m_stderr_data.clear();
        }
    }
    return bytes_available;
}

void
Process::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len)
{
    Process *process = (Process *) baton;
    process->AppendSTDOUT (static_cast<const char *>(src), src_len);
}

class IOHandlerProcessSTDIO :
    public IOHandler
{
public:
    IOHandlerProcessSTDIO (Process *process,
                           int write_fd) :
    IOHandler(process->GetTarget().GetDebugger(), IOHandler::Type::ProcessIO),
        m_process (process),
        m_read_file (),
        m_write_file (write_fd, false),
        m_pipe ()
    {
        m_pipe.CreateNew(false);
        m_read_file.SetDescriptor(GetInputFD(), false);
    }

    virtual
    ~IOHandlerProcessSTDIO ()
    {
        
    }
    
    // Each IOHandler gets to run until it is done. It should read data
    // from the "in" and place output into "out" and "err and return
    // when done.
    void
    Run () override
    {
        if (!m_read_file.IsValid() || !m_write_file.IsValid() || !m_pipe.CanRead() || !m_pipe.CanWrite())
        {
            SetIsDone(true);
            return;
        }

        SetIsDone(false);
        const int read_fd = m_read_file.GetDescriptor();
        TerminalState terminal_state;
        terminal_state.Save (read_fd, false);
        Terminal terminal(read_fd);
        terminal.SetCanonical(false);
        terminal.SetEcho(false);
// FD_ZERO, FD_SET are not supported on windows
#ifndef _WIN32
        const int pipe_read_fd = m_pipe.GetReadFileDescriptor();
        while (!GetIsDone())
        {
            fd_set read_fdset;
            FD_ZERO (&read_fdset);
            FD_SET (read_fd, &read_fdset);
            FD_SET (pipe_read_fd, &read_fdset);
            const int nfds = std::max<int>(read_fd, pipe_read_fd) + 1;
            int num_set_fds = select (nfds, &read_fdset, NULL, NULL, NULL);
            if (num_set_fds < 0)
            {
                const int select_errno = errno;

                if (select_errno != EINTR)
                    SetIsDone(true);
            }
            else if (num_set_fds > 0)
            {
                char ch = 0;
                size_t n;
                if (FD_ISSET (read_fd, &read_fdset))
                {
                    n = 1;
                    if (m_read_file.Read(&ch, n).Success() && n == 1)
                    {
                        if (m_write_file.Write(&ch, n).Fail() || n != 1)
                            SetIsDone(true);
                    }
                    else
                        SetIsDone(true);
                }
                if (FD_ISSET (pipe_read_fd, &read_fdset))
                {
                    size_t bytes_read;
                    // Consume the interrupt byte
                    Error error = m_pipe.Read(&ch, 1, bytes_read);
                    if (error.Success())
                    {
                        switch (ch)
                        {
                            case 'q':
                                SetIsDone(true);
                                break;
                            case 'i':
                                if (StateIsRunningState(m_process->GetState()))
                                    m_process->Halt();
                                break;
                        }
                    }
                }
            }
        }
#endif
        terminal_state.Restore();
    }
    
    void
    Cancel () override
    {
        char ch = 'q';  // Send 'q' for quit
        size_t bytes_written = 0;
        m_pipe.Write(&ch, 1, bytes_written);
    }

    bool
    Interrupt () override
    {
        // Do only things that are safe to do in an interrupt context (like in
        // a SIGINT handler), like write 1 byte to a file descriptor. This will
        // interrupt the IOHandlerProcessSTDIO::Run() and we can look at the byte
        // that was written to the pipe and then call m_process->Halt() from a
        // much safer location in code.
        if (m_active)
        {
            char ch = 'i'; // Send 'i' for interrupt
            size_t bytes_written = 0;
            Error result = m_pipe.Write(&ch, 1, bytes_written);
            return result.Success();
        }
        else
        {
            // This IOHandler might be pushed on the stack, but not being run currently
            // so do the right thing if we aren't actively watching for STDIN by sending
            // the interrupt to the process. Otherwise the write to the pipe above would
            // do nothing. This can happen when the command interpreter is running and
            // gets a "expression ...". It will be on the IOHandler thread and sending
            // the input is complete to the delegate which will cause the expression to
            // run, which will push the process IO handler, but not run it.
            
            if (StateIsRunningState(m_process->GetState()))
            {
                m_process->SendAsyncInterrupt();
                return true;
            }
        }
        return false;
    }
    
    void
    GotEOF() override
    {
        
    }
    
protected:
    Process *m_process;
    File m_read_file;   // Read from this file (usually actual STDIN for LLDB
    File m_write_file;  // Write to this file (usually the master pty for getting io to debuggee)
    Pipe m_pipe;
};

void
Process::SetSTDIOFileDescriptor (int fd)
{
    // First set up the Read Thread for reading/handling process I/O
    
    std::unique_ptr<ConnectionFileDescriptor> conn_ap (new ConnectionFileDescriptor (fd, true));
    
    if (conn_ap.get())
    {
        m_stdio_communication.SetConnection (conn_ap.release());
        if (m_stdio_communication.IsConnected())
        {
            m_stdio_communication.SetReadThreadBytesReceivedCallback (STDIOReadThreadBytesReceived, this);
            m_stdio_communication.StartReadThread();
            
            // Now read thread is set up, set up input reader.
            
            if (!m_process_input_reader.get())
                m_process_input_reader.reset (new IOHandlerProcessSTDIO (this, fd));
        }
    }
}

bool
Process::ProcessIOHandlerIsActive ()
{
    IOHandlerSP io_handler_sp (m_process_input_reader);
    if (io_handler_sp)
        return m_target.GetDebugger().IsTopIOHandler (io_handler_sp);
    return false;
}
bool
Process::PushProcessIOHandler ()
{
    IOHandlerSP io_handler_sp (m_process_input_reader);
    if (io_handler_sp)
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
        if (log)
            log->Printf("Process::%s pushing IO handler", __FUNCTION__);

        io_handler_sp->SetIsDone(false);
        m_target.GetDebugger().PushIOHandler (io_handler_sp);
        return true;
    }
    return false;
}

bool
Process::PopProcessIOHandler ()
{
    IOHandlerSP io_handler_sp (m_process_input_reader);
    if (io_handler_sp)
        return m_target.GetDebugger().PopIOHandler (io_handler_sp);
    return false;
}

// The process needs to know about installed plug-ins
void
Process::SettingsInitialize ()
{
    Thread::SettingsInitialize ();
}

void
Process::SettingsTerminate ()
{
    Thread::SettingsTerminate ();
}

ExpressionResults
Process::RunThreadPlan (ExecutionContext &exe_ctx,
                        lldb::ThreadPlanSP &thread_plan_sp,
                        const EvaluateExpressionOptions &options,
                        Stream &errors)
{
    ExpressionResults return_value = eExpressionSetupError;

    if (thread_plan_sp.get() == NULL)
    {
        errors.Printf("RunThreadPlan called with empty thread plan.");
        return eExpressionSetupError;
    }

    if (!thread_plan_sp->ValidatePlan(NULL))
    {
        errors.Printf ("RunThreadPlan called with an invalid thread plan.");
        return eExpressionSetupError;
    }

    if (exe_ctx.GetProcessPtr() != this)
    {
        errors.Printf("RunThreadPlan called on wrong process.");
        return eExpressionSetupError;
    }

    Thread *thread = exe_ctx.GetThreadPtr();
    if (thread == NULL)
    {
        errors.Printf("RunThreadPlan called with invalid thread.");
        return eExpressionSetupError;
    }

    // We rely on the thread plan we are running returning "PlanCompleted" if when it successfully completes.
    // For that to be true the plan can't be private - since private plans suppress themselves in the
    // GetCompletedPlan call. 

    bool orig_plan_private = thread_plan_sp->GetPrivate();
    thread_plan_sp->SetPrivate(false);

    if (m_private_state.GetValue() != eStateStopped)
    {
        errors.Printf ("RunThreadPlan called while the private state was not stopped.");
        return eExpressionSetupError;
    }

    // Save the thread & frame from the exe_ctx for restoration after we run
    const uint32_t thread_idx_id = thread->GetIndexID();
    StackFrameSP selected_frame_sp = thread->GetSelectedFrame();
    if (!selected_frame_sp)
    {
        thread->SetSelectedFrame(0);
        selected_frame_sp = thread->GetSelectedFrame();
        if (!selected_frame_sp)
        {
            errors.Printf("RunThreadPlan called without a selected frame on thread %d", thread_idx_id);
            return eExpressionSetupError;
        }
    }

    StackID ctx_frame_id = selected_frame_sp->GetStackID();

    // N.B. Running the target may unset the currently selected thread and frame.  We don't want to do that either, 
    // so we should arrange to reset them as well.

    lldb::ThreadSP selected_thread_sp = GetThreadList().GetSelectedThread();

    uint32_t selected_tid;
    StackID selected_stack_id;
    if (selected_thread_sp)
    {
        selected_tid = selected_thread_sp->GetIndexID();
        selected_stack_id = selected_thread_sp->GetSelectedFrame()->GetStackID();
    }
    else
    {
        selected_tid = LLDB_INVALID_THREAD_ID;
    }

    HostThread backup_private_state_thread;
    lldb::StateType old_state = eStateInvalid;
    lldb::ThreadPlanSP stopper_base_plan_sp;
    
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS));
    if (m_private_state_thread.EqualsThread(Host::GetCurrentThread()))
    {
        // Yikes, we are running on the private state thread!  So we can't wait for public events on this thread, since
        // we are the thread that is generating public events.
        // The simplest thing to do is to spin up a temporary thread to handle private state thread events while
        // we are fielding public events here.
        if (log)
            log->Printf ("Running thread plan on private state thread, spinning up another state thread to handle the events.");

        backup_private_state_thread = m_private_state_thread;

        // One other bit of business: we want to run just this thread plan and anything it pushes, and then stop,
        // returning control here.
        // But in the normal course of things, the plan above us on the stack would be given a shot at the stop
        // event before deciding to stop, and we don't want that.  So we insert a "stopper" base plan on the stack
        // before the plan we want to run.  Since base plans always stop and return control to the user, that will
        // do just what we want.
        stopper_base_plan_sp.reset(new ThreadPlanBase (*thread));
        thread->QueueThreadPlan (stopper_base_plan_sp, false);
        // Have to make sure our public state is stopped, since otherwise the reporting logic below doesn't work correctly.
        old_state = m_public_state.GetValue();
        m_public_state.SetValueNoLock(eStateStopped);

        // Now spin up the private state thread:
        StartPrivateStateThread(true);
    }

    thread->QueueThreadPlan(thread_plan_sp, false); // This used to pass "true" does that make sense?

    if (options.GetDebug())
    {
        // In this case, we aren't actually going to run, we just want to stop right away.
        // Flush this thread so we will refetch the stacks and show the correct backtrace.
        // FIXME: To make this prettier we should invent some stop reason for this, but that
        // is only cosmetic, and this functionality is only of use to lldb developers who can
        // live with not pretty...
        thread->Flush();
        return eExpressionStoppedForDebug;
    }

    Listener listener("lldb.process.listener.run-thread-plan");

    lldb::EventSP event_to_broadcast_sp;

    {
        // This process event hijacker Hijacks the Public events and its destructor makes sure that the process events get
        // restored on exit to the function.
        //
        // If the event needs to propagate beyond the hijacker (e.g., the process exits during execution), then the event
        // is put into event_to_broadcast_sp for rebroadcasting.

        ProcessEventHijacker run_thread_plan_hijacker (*this, &listener);

        if (log)
        {
            StreamString s;
            thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
            log->Printf ("Process::RunThreadPlan(): Resuming thread %u - 0x%4.4" PRIx64 " to run thread plan \"%s\".",
                         thread->GetIndexID(), 
                         thread->GetID(), 
                         s.GetData());
        }

        bool got_event;
        lldb::EventSP event_sp;
        lldb::StateType stop_state = lldb::eStateInvalid;

        TimeValue* timeout_ptr = NULL;
        TimeValue real_timeout;

        bool before_first_timeout = true;  // This is set to false the first time that we have to halt the target.
        bool do_resume = true;
        bool handle_running_event = true;
        const uint64_t default_one_thread_timeout_usec = 250000;

        // This is just for accounting:
        uint32_t num_resumes = 0;

        uint32_t timeout_usec = options.GetTimeoutUsec();
        uint32_t one_thread_timeout_usec;
        uint32_t all_threads_timeout_usec = 0;
        
        // If we are going to run all threads the whole time, or if we are only going to run one thread,
        // then we don't need the first timeout.  So we set the final timeout, and pretend we are after the
        // first timeout already.
        
        if (!options.GetStopOthers() || !options.GetTryAllThreads())
        {
            before_first_timeout = false;
            one_thread_timeout_usec = 0;
            all_threads_timeout_usec = timeout_usec;
        }
        else
        {
            uint32_t option_one_thread_timeout = options.GetOneThreadTimeoutUsec();

            // If the overall wait is forever, then we only need to set the one thread timeout:
            if (timeout_usec == 0)
            {
                if (option_one_thread_timeout != 0)
                    one_thread_timeout_usec = option_one_thread_timeout;
                else
                    one_thread_timeout_usec = default_one_thread_timeout_usec;
            }
            else
            {
                // Otherwise, if the one thread timeout is set, make sure it isn't longer than the overall timeout,
                // and use it, otherwise use half the total timeout, bounded by the default_one_thread_timeout_usec.
                uint64_t computed_one_thread_timeout;
                if (option_one_thread_timeout != 0)
                {
                    if (timeout_usec < option_one_thread_timeout)
                    {
                        errors.Printf("RunThreadPlan called without one thread timeout greater than total timeout");
                        return eExpressionSetupError;
                    }
                    computed_one_thread_timeout = option_one_thread_timeout;
                }
                else
                {
                    computed_one_thread_timeout = timeout_usec / 2;
                    if (computed_one_thread_timeout > default_one_thread_timeout_usec)
                        computed_one_thread_timeout = default_one_thread_timeout_usec;
                }
                one_thread_timeout_usec = computed_one_thread_timeout;
                all_threads_timeout_usec = timeout_usec - one_thread_timeout_usec;
                
            }
        }
        
        if (log)
            log->Printf ("Stop others: %u, try all: %u, before_first: %u, one thread: %" PRIu32 " - all threads: %" PRIu32 ".\n",
                         options.GetStopOthers(),
                         options.GetTryAllThreads(),
                         before_first_timeout,
                         one_thread_timeout_usec,
                         all_threads_timeout_usec);

        // This isn't going to work if there are unfetched events on the queue.
        // Are there cases where we might want to run the remaining events here, and then try to
        // call the function?  That's probably being too tricky for our own good.

        Event *other_events = listener.PeekAtNextEvent();
        if (other_events != NULL)
        {
            errors.Printf("Calling RunThreadPlan with pending events on the queue.");
            return eExpressionSetupError;
        }

        // We also need to make sure that the next event is delivered.  We might be calling a function as part of
        // a thread plan, in which case the last delivered event could be the running event, and we don't want
        // event coalescing to cause us to lose OUR running event...
        ForceNextEventDelivery();

        // This while loop must exit out the bottom, there's cleanup that we need to do when we are done.
        // So don't call return anywhere within it.
        
#ifdef LLDB_RUN_THREAD_HALT_WITH_EVENT
        // It's pretty much impossible to write test cases for things like:
        // One thread timeout expires, I go to halt, but the process already stopped
        // on the function call stop breakpoint.  Turning on this define will make us not
        // fetch the first event till after the halt.  So if you run a quick function, it will have
        // completed, and the completion event will be waiting, when you interrupt for halt.
        // The expression evaluation should still succeed.
        bool miss_first_event = true;
#endif
        TimeValue one_thread_timeout;
        TimeValue final_timeout;
        
        
        while (1)
        {
            // We usually want to resume the process if we get to the top of the loop.
            // The only exception is if we get two running events with no intervening
            // stop, which can happen, we will just wait for then next stop event.
            if (log)
                log->Printf ("Top of while loop: do_resume: %i handle_running_event: %i before_first_timeout: %i.",
                             do_resume,
                             handle_running_event,
                             before_first_timeout);

            if (do_resume || handle_running_event)
            {
                // Do the initial resume and wait for the running event before going further.

                if (do_resume)
                {
                    num_resumes++;
                    Error resume_error = PrivateResume ();
                    if (!resume_error.Success())
                    {
                        errors.Printf("Error resuming inferior the %d time: \"%s\".\n",
                                      num_resumes,
                                      resume_error.AsCString());
                        return_value = eExpressionSetupError;
                        break;
                    }
                }

                TimeValue resume_timeout = TimeValue::Now();
                resume_timeout.OffsetWithMicroSeconds(500000);

                got_event = listener.WaitForEvent(&resume_timeout, event_sp);
                if (!got_event)
                {
                    if (log)
                        log->Printf ("Process::RunThreadPlan(): didn't get any event after resume %d, exiting.",
                                        num_resumes);

                    errors.Printf("Didn't get any event after resume %d, exiting.", num_resumes);
                    return_value = eExpressionSetupError;
                    break;
                }

                stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());

                if (stop_state != eStateRunning)
                {
                    bool restarted = false;

                    if (stop_state == eStateStopped)
                    {
                        restarted = Process::ProcessEventData::GetRestartedFromEvent(event_sp.get());
                        if (log)
                            log->Printf("Process::RunThreadPlan(): didn't get running event after "
                                        "resume %d, got %s instead (restarted: %i, do_resume: %i, handle_running_event: %i).",
                                        num_resumes,
                                        StateAsCString(stop_state),
                                        restarted,
                                        do_resume,
                                        handle_running_event);
                    }

                    if (restarted)
                    {
                        // This is probably an overabundance of caution, I don't think I should ever get a stopped & restarted
                        // event here.  But if I do, the best thing is to Halt and then get out of here.
                        Halt();
                    }

                    errors.Printf("Didn't get running event after initial resume, got %s instead.",
                                  StateAsCString(stop_state));
                    return_value = eExpressionSetupError;
                    break;
                }

                if (log)
                    log->PutCString ("Process::RunThreadPlan(): resuming succeeded.");
                // We need to call the function synchronously, so spin waiting for it to return.
                // If we get interrupted while executing, we're going to lose our context, and
                // won't be able to gather the result at this point.
                // We set the timeout AFTER the resume, since the resume takes some time and we
                // don't want to charge that to the timeout.
            }
            else
            {
                if (log)
                    log->PutCString ("Process::RunThreadPlan(): waiting for next event.");
            }

            if (before_first_timeout)
            {
                if (options.GetTryAllThreads())
                {
                    one_thread_timeout = TimeValue::Now();
                    one_thread_timeout.OffsetWithMicroSeconds(one_thread_timeout_usec);
                    timeout_ptr = &one_thread_timeout;
                }
                else
                {
                    if (timeout_usec == 0)
                        timeout_ptr = NULL;
                    else
                    {
                        final_timeout = TimeValue::Now();
                        final_timeout.OffsetWithMicroSeconds (timeout_usec);
                        timeout_ptr = &final_timeout;
                    }
                }
            }
            else
            {
                if (timeout_usec == 0)
                    timeout_ptr = NULL;
                else
                {
                    final_timeout = TimeValue::Now();
                    final_timeout.OffsetWithMicroSeconds (all_threads_timeout_usec);
                    timeout_ptr = &final_timeout;
                }
            }

            do_resume = true;
            handle_running_event = true;

            // Now wait for the process to stop again:
            event_sp.reset();

            if (log)
            {
                if (timeout_ptr)
                {
                    log->Printf ("Process::RunThreadPlan(): about to wait - now is %" PRIu64 " - endpoint is %" PRIu64,
                                 TimeValue::Now().GetAsMicroSecondsSinceJan1_1970(),
                                 timeout_ptr->GetAsMicroSecondsSinceJan1_1970());
                }
                else
                {
                    log->Printf ("Process::RunThreadPlan(): about to wait forever.");
                }
            }
            
#ifdef LLDB_RUN_THREAD_HALT_WITH_EVENT
            // See comment above...
            if (miss_first_event)
            {
                usleep(1000);
                miss_first_event = false;
                got_event = false;
            }
            else
#endif
            got_event = listener.WaitForEvent (timeout_ptr, event_sp);

            if (got_event)
            {
                if (event_sp.get())
                {
                    bool keep_going = false;
                    if (event_sp->GetType() == eBroadcastBitInterrupt)
                    {
                        Halt();
                        return_value = eExpressionInterrupted;
                        errors.Printf ("Execution halted by user interrupt.");
                        if (log)
                            log->Printf ("Process::RunThreadPlan(): Got  interrupted by eBroadcastBitInterrupted, exiting.");
                        break;
                    }
                    else
                    {
                        stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
                        if (log)
                            log->Printf("Process::RunThreadPlan(): in while loop, got event: %s.", StateAsCString(stop_state));

                        switch (stop_state)
                        {
                        case lldb::eStateStopped:
                            {
                                // We stopped, figure out what we are going to do now.
                                ThreadSP thread_sp = GetThreadList().FindThreadByIndexID (thread_idx_id);
                                if (!thread_sp)
                                {
                                    // Ooh, our thread has vanished.  Unlikely that this was successful execution...
                                    if (log)
                                        log->Printf ("Process::RunThreadPlan(): execution completed but our thread (index-id=%u) has vanished.", thread_idx_id);
                                    return_value = eExpressionInterrupted;
                                }
                                else
                                {
                                    // If we were restarted, we just need to go back up to fetch another event.
                                    if (Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
                                    {
                                        if (log)
                                        {
                                            log->Printf ("Process::RunThreadPlan(): Got a stop and restart, so we'll continue waiting.");
                                        }
                                       keep_going = true;
                                       do_resume = false;
                                       handle_running_event = true;

                                    }
                                    else
                                    {
                                        StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
                                        StopReason stop_reason = eStopReasonInvalid;
                                        if (stop_info_sp)
                                             stop_reason = stop_info_sp->GetStopReason();

                                        // FIXME: We only check if the stop reason is plan complete, should we make sure that
                                        // it is OUR plan that is complete?
                                        if (stop_reason == eStopReasonPlanComplete)
                                        {
                                            if (log)
                                                log->PutCString ("Process::RunThreadPlan(): execution completed successfully.");
                                            // Now mark this plan as private so it doesn't get reported as the stop reason
                                            // after this point.  
                                            if (thread_plan_sp)
                                                thread_plan_sp->SetPrivate (orig_plan_private);
                                            return_value = eExpressionCompleted;
                                        }
                                        else
                                        {
                                            // Something restarted the target, so just wait for it to stop for real.
                                            if (stop_reason == eStopReasonBreakpoint)
                                            {
                                                if (log)
                                                    log->Printf ("Process::RunThreadPlan() stopped for breakpoint: %s.", stop_info_sp->GetDescription());
                                                return_value = eExpressionHitBreakpoint;
                                                if (!options.DoesIgnoreBreakpoints())
                                                {
                                                    event_to_broadcast_sp = event_sp;
                                                }
                                            }
                                            else
                                            {
                                                if (log)
                                                    log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
                                                if (!options.DoesUnwindOnError())
                                                    event_to_broadcast_sp = event_sp;
                                                return_value = eExpressionInterrupted;
                                            }
                                        }
                                    }
                                }
                            }        
                            break;

                        case lldb::eStateRunning:
                            // This shouldn't really happen, but sometimes we do get two running events without an
                            // intervening stop, and in that case we should just go back to waiting for the stop.
                            do_resume = false;
                            keep_going = true;
                            handle_running_event = false;
                            break;

                        default:
                            if (log)
                                log->Printf("Process::RunThreadPlan(): execution stopped with unexpected state: %s.", StateAsCString(stop_state));

                            if (stop_state == eStateExited)
                                event_to_broadcast_sp = event_sp;

                            errors.Printf ("Execution stopped with unexpected state.\n");
                            return_value = eExpressionInterrupted;
                            break;
                        }
                    }

                    if (keep_going)
                        continue;
                    else
                        break;
                } 
                else
                {
                    if (log)
                        log->PutCString ("Process::RunThreadPlan(): got_event was true, but the event pointer was null.  How odd...");
                    return_value = eExpressionInterrupted;
                    break;
                }
            }
            else
            {
                // If we didn't get an event that means we've timed out...
                // We will interrupt the process here.  Depending on what we were asked to do we will
                // either exit, or try with all threads running for the same timeout.

                if (log) {
                    if (options.GetTryAllThreads())
                    {
                        if (before_first_timeout)
                        {
                            if (timeout_usec != 0)
                            {
                                log->Printf ("Process::RunThreadPlan(): Running function with one thread timeout timed out, "
                                             "running for %" PRIu32 " usec with all threads enabled.",
                                             all_threads_timeout_usec);
                            }
                            else
                            {
                                log->Printf ("Process::RunThreadPlan(): Running function with one thread timeout timed out, "
                                             "running forever with all threads enabled.");
                            }
                        }
                        else
                            log->Printf ("Process::RunThreadPlan(): Restarting function with all threads enabled "
                                         "and timeout: %u timed out, abandoning execution.",
                                         timeout_usec);
                    }
                    else
                        log->Printf ("Process::RunThreadPlan(): Running function with timeout: %u timed out, "
                                     "abandoning execution.", 
                                     timeout_usec);
                }

                // It is possible that between the time we issued the Halt, and we get around to calling Halt the target
                // could have stopped.  That's fine, Halt will figure that out and send the appropriate Stopped event.
                // BUT it is also possible that we stopped & restarted (e.g. hit a signal with "stop" set to false.)  In
                // that case, we'll get the stopped & restarted event, and we should go back to waiting for the Halt's
                // stopped event.  That's what this while loop does.

                bool back_to_top = true;
                uint32_t try_halt_again = 0;
                bool do_halt = true;
                const uint32_t num_retries = 5;
                while (try_halt_again < num_retries)
                {
                    Error halt_error;
                    if (do_halt)
                    {
                        if (log)
                            log->Printf ("Process::RunThreadPlan(): Running Halt.");
                        halt_error = Halt();
                    }
                    if (halt_error.Success())
                    {
                        if (log)
                            log->PutCString ("Process::RunThreadPlan(): Halt succeeded.");

                        real_timeout = TimeValue::Now();
                        real_timeout.OffsetWithMicroSeconds(500000);

                        got_event = listener.WaitForEvent(&real_timeout, event_sp);

                        if (got_event)
                        {
                            stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
                            if (log)
                            {
                                log->Printf ("Process::RunThreadPlan(): Stopped with event: %s", StateAsCString(stop_state));
                                if (stop_state == lldb::eStateStopped 
                                    && Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get()))
                                    log->PutCString ("    Event was the Halt interruption event.");
                            }

                            if (stop_state == lldb::eStateStopped)
                            {
                                // Between the time we initiated the Halt and the time we delivered it, the process could have
                                // already finished its job.  Check that here:

                                if (thread->IsThreadPlanDone (thread_plan_sp.get()))
                                {
                                    if (log)
                                        log->PutCString ("Process::RunThreadPlan(): Even though we timed out, the call plan was done.  "
                                                     "Exiting wait loop.");
                                    return_value = eExpressionCompleted;
                                    back_to_top = false;
                                    break;
                                }

                                if (Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
                                {
                                    if (log)
                                        log->PutCString ("Process::RunThreadPlan(): Went to halt but got a restarted event, there must be an un-restarted stopped event so try again...  "
                                                     "Exiting wait loop.");
                                    try_halt_again++;
                                    do_halt = false;
                                    continue;
                                }

                                if (!options.GetTryAllThreads())
                                {
                                    if (log)
                                        log->PutCString ("Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting.");
                                    return_value = eExpressionInterrupted;
                                    back_to_top = false;
                                    break;
                                }

                                if (before_first_timeout)
                                {
                                    // Set all the other threads to run, and return to the top of the loop, which will continue;
                                    before_first_timeout = false;
                                    thread_plan_sp->SetStopOthers (false);
                                    if (log)
                                        log->PutCString ("Process::RunThreadPlan(): about to resume.");

                                    back_to_top = true;
                                    break;
                                }
                                else
                                {
                                    // Running all threads failed, so return Interrupted.
                                    if (log)
                                        log->PutCString("Process::RunThreadPlan(): running all threads timed out.");
                                    return_value = eExpressionInterrupted;
                                    back_to_top = false;
                                    break;
                                }
                            }
                        }
                        else
                        {   if (log)
                                log->PutCString("Process::RunThreadPlan(): halt said it succeeded, but I got no event.  "
                                        "I'm getting out of here passing Interrupted.");
                            return_value = eExpressionInterrupted;
                            back_to_top = false;
                            break;
                        }
                    }
                    else
                    {
                        try_halt_again++;
                        continue;
                    }
                }

                if (!back_to_top || try_halt_again > num_retries)
                    break;
                else
                    continue;
            }
        }  // END WAIT LOOP

        // If we had to start up a temporary private state thread to run this thread plan, shut it down now.
        if (backup_private_state_thread.IsJoinable())
        {
            StopPrivateStateThread();
            Error error;
            m_private_state_thread = backup_private_state_thread;
            if (stopper_base_plan_sp)
            {
                thread->DiscardThreadPlansUpToPlan(stopper_base_plan_sp);
            }
            if (old_state != eStateInvalid)
                m_public_state.SetValueNoLock(old_state);
        }

        // Restore the thread state if we are going to discard the plan execution.  There are three cases where this
        // could happen:
        // 1) The execution successfully completed
        // 2) We hit a breakpoint, and ignore_breakpoints was true
        // 3) We got some other error, and discard_on_error was true
        bool should_unwind = (return_value == eExpressionInterrupted && options.DoesUnwindOnError())
                             || (return_value == eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints());

        if (return_value == eExpressionCompleted
            || should_unwind)
        {
            thread_plan_sp->RestoreThreadState();
        }

        // Now do some processing on the results of the run:
        if (return_value == eExpressionInterrupted || return_value == eExpressionHitBreakpoint)
        {
            if (log)
            {
                StreamString s;
                if (event_sp)
                    event_sp->Dump (&s);
                else
                {
                    log->PutCString ("Process::RunThreadPlan(): Stop event that interrupted us is NULL.");
                }

                StreamString ts;

                const char *event_explanation = NULL;                

                do 
                {
                    if (!event_sp)
                    {
                        event_explanation = "<no event>";
                        break;
                    }
                    else if (event_sp->GetType() == eBroadcastBitInterrupt)
                    {
                        event_explanation = "<user interrupt>";
                        break;
                    }
                    else
                    {
                        const Process::ProcessEventData *event_data = Process::ProcessEventData::GetEventDataFromEvent (event_sp.get());

                        if (!event_data)
                        {
                            event_explanation = "<no event data>";
                            break;
                        }

                        Process *process = event_data->GetProcessSP().get();

                        if (!process)
                        {
                            event_explanation = "<no process>";
                            break;
                        }

                        ThreadList &thread_list = process->GetThreadList();

                        uint32_t num_threads = thread_list.GetSize();
                        uint32_t thread_index;

                        ts.Printf("<%u threads> ", num_threads);

                        for (thread_index = 0;
                             thread_index < num_threads;
                             ++thread_index)
                        {
                            Thread *thread = thread_list.GetThreadAtIndex(thread_index).get();

                            if (!thread)
                            {
                                ts.Printf("<?> ");
                                continue;
                            }

                            ts.Printf("<0x%4.4" PRIx64 " ", thread->GetID());
                            RegisterContext *register_context = thread->GetRegisterContext().get();

                            if (register_context)
                                ts.Printf("[ip 0x%" PRIx64 "] ", register_context->GetPC());
                            else
                                ts.Printf("[ip unknown] ");

                            lldb::StopInfoSP stop_info_sp = thread->GetStopInfo();
                            if (stop_info_sp)
                            {
                                const char *stop_desc = stop_info_sp->GetDescription();
                                if (stop_desc)
                                    ts.PutCString (stop_desc);
                            }
                            ts.Printf(">");
                        }

                        event_explanation = ts.GetData();
                    }
                } while (0);

                if (event_explanation)
                    log->Printf("Process::RunThreadPlan(): execution interrupted: %s %s", s.GetData(), event_explanation);
                else
                    log->Printf("Process::RunThreadPlan(): execution interrupted: %s", s.GetData());
            }

            if (should_unwind)
            {
                if (log)
                    log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.",
                                 static_cast<void*>(thread_plan_sp.get()));
                thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
                thread_plan_sp->SetPrivate (orig_plan_private);
            }
            else
            {
                if (log)
                    log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - for plan: %p not discarding.",
                                 static_cast<void*>(thread_plan_sp.get()));
            }
        }
        else if (return_value == eExpressionSetupError)
        {
            if (log)
                log->PutCString("Process::RunThreadPlan(): execution set up error.");

            if (options.DoesUnwindOnError())
            {
                thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
                thread_plan_sp->SetPrivate (orig_plan_private);
            }
        }
        else
        {
            if (thread->IsThreadPlanDone (thread_plan_sp.get()))
            {
                if (log)
                    log->PutCString("Process::RunThreadPlan(): thread plan is done");
                return_value = eExpressionCompleted;
            }
            else if (thread->WasThreadPlanDiscarded (thread_plan_sp.get()))
            {
                if (log)
                    log->PutCString("Process::RunThreadPlan(): thread plan was discarded");
                return_value = eExpressionDiscarded;
            }
            else
            {
                if (log)
                    log->PutCString("Process::RunThreadPlan(): thread plan stopped in mid course");
                if (options.DoesUnwindOnError() && thread_plan_sp)
                {
                    if (log)
                        log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause unwind_on_error is set.");
                    thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
                    thread_plan_sp->SetPrivate (orig_plan_private);
                }
            }
        }

        // Thread we ran the function in may have gone away because we ran the target
        // Check that it's still there, and if it is put it back in the context.  Also restore the
        // frame in the context if it is still present.
        thread = GetThreadList().FindThreadByIndexID(thread_idx_id, true).get();
        if (thread)
        {
            exe_ctx.SetFrameSP (thread->GetFrameWithStackID (ctx_frame_id));
        }

        // Also restore the current process'es selected frame & thread, since this function calling may
        // be done behind the user's back.

        if (selected_tid != LLDB_INVALID_THREAD_ID)
        {
            if (GetThreadList().SetSelectedThreadByIndexID (selected_tid) && selected_stack_id.IsValid())
            {
                // We were able to restore the selected thread, now restore the frame:
                Mutex::Locker lock(GetThreadList().GetMutex());
                StackFrameSP old_frame_sp = GetThreadList().GetSelectedThread()->GetFrameWithStackID(selected_stack_id);
                if (old_frame_sp)
                    GetThreadList().GetSelectedThread()->SetSelectedFrame(old_frame_sp.get());
            }
        }
    }

    // If the process exited during the run of the thread plan, notify everyone.

    if (event_to_broadcast_sp)
    {
        if (log)
            log->PutCString("Process::RunThreadPlan(): rebroadcasting event.");
        BroadcastEvent(event_to_broadcast_sp);
    }

    return return_value;
}

const char *
Process::ExecutionResultAsCString (ExpressionResults result)
{
    const char *result_name;
    
    switch (result)
    {
        case eExpressionCompleted:
            result_name = "eExpressionCompleted";
            break;
        case eExpressionDiscarded:
            result_name = "eExpressionDiscarded";
            break;
        case eExpressionInterrupted:
            result_name = "eExpressionInterrupted";
            break;
        case eExpressionHitBreakpoint:
            result_name = "eExpressionHitBreakpoint";
            break;
        case eExpressionSetupError:
            result_name = "eExpressionSetupError";
            break;
        case eExpressionParseError:
            result_name = "eExpressionParseError";
            break;
        case eExpressionResultUnavailable:
            result_name = "eExpressionResultUnavailable";
            break;
        case eExpressionTimedOut:
            result_name = "eExpressionTimedOut";
            break;
        case eExpressionStoppedForDebug:
            result_name = "eExpressionStoppedForDebug";
            break;
    }
    return result_name;
}

void
Process::GetStatus (Stream &strm)
{
    const StateType state = GetState();
    if (StateIsStoppedState(state, false))
    {
        if (state == eStateExited)
        {
            int exit_status = GetExitStatus();
            const char *exit_description = GetExitDescription();
            strm.Printf ("Process %" PRIu64 " exited with status = %i (0x%8.8x) %s\n",
                          GetID(),
                          exit_status,
                          exit_status,
                          exit_description ? exit_description : "");
        }
        else
        {
            if (state == eStateConnected)
                strm.Printf ("Connected to remote target.\n");
            else
                strm.Printf ("Process %" PRIu64 " %s\n", GetID(), StateAsCString (state));
        }
    }
    else
    {
        strm.Printf ("Process %" PRIu64 " is running.\n", GetID());
    }
}

size_t
Process::GetThreadStatus (Stream &strm, 
                          bool only_threads_with_stop_reason,
                          uint32_t start_frame, 
                          uint32_t num_frames, 
                          uint32_t num_frames_with_source)
{
    size_t num_thread_infos_dumped = 0;
    
    // You can't hold the thread list lock while calling Thread::GetStatus.  That very well might run code (e.g. if we need it
    // to get return values or arguments.)  For that to work the process has to be able to acquire it.  So instead copy the thread
    // ID's, and look them up one by one:
    
    uint32_t num_threads;
    std::vector<lldb::tid_t> thread_id_array;
    //Scope for thread list locker;
    {
        Mutex::Locker locker (GetThreadList().GetMutex());
        ThreadList &curr_thread_list = GetThreadList();
        num_threads = curr_thread_list.GetSize();
        uint32_t idx;
        thread_id_array.resize(num_threads);
        for (idx = 0; idx < num_threads; ++idx)
            thread_id_array[idx] = curr_thread_list.GetThreadAtIndex(idx)->GetID();
    }
    
    for (uint32_t i = 0; i < num_threads; i++)
    {
        ThreadSP thread_sp(GetThreadList().FindThreadByID(thread_id_array[i]));
        if (thread_sp)
        {
            if (only_threads_with_stop_reason)
            {
                StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
                if (stop_info_sp.get() == NULL || !stop_info_sp->IsValid())
                    continue;
            }
            thread_sp->GetStatus (strm,
                               start_frame, 
                               num_frames, 
                               num_frames_with_source);
            ++num_thread_infos_dumped;
        }
        else
        {
            Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));
            if (log)
                log->Printf("Process::GetThreadStatus - thread 0x" PRIu64 " vanished while running Thread::GetStatus.");
            
        }
    }
    return num_thread_infos_dumped;
}

void
Process::AddInvalidMemoryRegion (const LoadRange &region)
{
    m_memory_cache.AddInvalidRange(region.GetRangeBase(), region.GetByteSize());
}

bool
Process::RemoveInvalidMemoryRange (const LoadRange &region)
{
    return m_memory_cache.RemoveInvalidRange(region.GetRangeBase(), region.GetByteSize());
}

void
Process::AddPreResumeAction (PreResumeActionCallback callback, void *baton)
{
    m_pre_resume_actions.push_back(PreResumeCallbackAndBaton (callback, baton));
}

bool
Process::RunPreResumeActions ()
{
    bool result = true;
    while (!m_pre_resume_actions.empty())
    {
        struct PreResumeCallbackAndBaton action = m_pre_resume_actions.back();
        m_pre_resume_actions.pop_back();
        bool this_result = action.callback (action.baton);
        if (result == true) 
            result = this_result;
    }
    return result;
}

void
Process::ClearPreResumeActions ()
{
    m_pre_resume_actions.clear();
}

ProcessRunLock &
Process::GetRunLock()
{
    if (m_private_state_thread.EqualsThread(Host::GetCurrentThread()))
        return m_private_run_lock;
    else
        return m_public_run_lock;
}

void
Process::Flush ()
{
    m_thread_list.Flush();
    m_extended_thread_list.Flush();
    m_extended_thread_stop_id =  0;
    m_queue_list.Clear();
    m_queue_list_stop_id = 0;
}

void
Process::DidExec ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf ("Process::%s()", __FUNCTION__);

    Target &target = GetTarget();
    target.CleanupProcess ();
    target.ClearModules(false);
    m_dynamic_checkers_ap.reset();
    m_abi_sp.reset();
    m_system_runtime_ap.reset();
    m_os_ap.reset();
    m_dyld_ap.reset();
    m_jit_loaders_ap.reset();
    m_image_tokens.clear();
    m_allocated_memory_cache.Clear();
    m_language_runtimes.clear();
    m_instrumentation_runtimes.clear();
    m_thread_list.DiscardThreadPlans();
    m_memory_cache.Clear(true);
    m_stop_info_override_callback = NULL;
    DoDidExec();
    CompleteAttach ();
    // Flush the process (threads and all stack frames) after running CompleteAttach()
    // in case the dynamic loader loaded things in new locations.
    Flush();
    
    // After we figure out what was loaded/unloaded in CompleteAttach,
    // we need to let the target know so it can do any cleanup it needs to.
    target.DidExec();
}

addr_t
Process::ResolveIndirectFunction(const Address *address, Error &error)
{
    if (address == nullptr)
    {
        error.SetErrorString("Invalid address argument");
        return LLDB_INVALID_ADDRESS;
    }
    
    addr_t function_addr = LLDB_INVALID_ADDRESS;
    
    addr_t addr = address->GetLoadAddress(&GetTarget());
    std::map<addr_t,addr_t>::const_iterator iter = m_resolved_indirect_addresses.find(addr);
    if (iter != m_resolved_indirect_addresses.end())
    {
        function_addr = (*iter).second;
    }
    else
    {
        if (!InferiorCall(this, address, function_addr))
        {
            Symbol *symbol = address->CalculateSymbolContextSymbol();
            error.SetErrorStringWithFormat ("Unable to call resolver for indirect function %s",
                                          symbol ? symbol->GetName().AsCString() : "<UNKNOWN>");
            function_addr = LLDB_INVALID_ADDRESS;
        }
        else
        {
            m_resolved_indirect_addresses.insert(std::pair<addr_t, addr_t>(addr, function_addr));
        }
    }
    return function_addr;
}

void
Process::ModulesDidLoad (ModuleList &module_list)
{
    SystemRuntime *sys_runtime = GetSystemRuntime();
    if (sys_runtime)
    {
        sys_runtime->ModulesDidLoad (module_list);
    }

    GetJITLoaders().ModulesDidLoad (module_list);
    
    // Give runtimes a chance to be created.
    InstrumentationRuntime::ModulesDidLoad(module_list, this, m_instrumentation_runtimes);
    
    // Tell runtimes about new modules.
    for (auto pos = m_instrumentation_runtimes.begin(); pos != m_instrumentation_runtimes.end(); ++pos)
    {
        InstrumentationRuntimeSP runtime = pos->second;
        runtime->ModulesDidLoad(module_list);
    }

    // Let any language runtimes we have already created know
    // about the modules that loaded.
    
    // Iterate over a copy of this language runtime list in case
    // the language runtime ModulesDidLoad somehow causes the language
    // riuntime to be unloaded.
    LanguageRuntimeCollection language_runtimes(m_language_runtimes);
    for (const auto &pair: language_runtimes)
    {
        // We must check language_runtime_sp to make sure it is not
        // NULL as we might cache the fact that we didn't have a
        // language runtime for a language.
        LanguageRuntimeSP language_runtime_sp = pair.second;
        if (language_runtime_sp)
            language_runtime_sp->ModulesDidLoad(module_list);
    }
}

ThreadCollectionSP
Process::GetHistoryThreads(lldb::addr_t addr)
{
    ThreadCollectionSP threads;

    const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(shared_from_this());
    
    if (! memory_history.get()) {
        return threads;
    }
    
    threads.reset(new ThreadCollection(memory_history->GetHistoryThreads(addr)));
    
    return threads;
}

InstrumentationRuntimeSP
Process::GetInstrumentationRuntime(lldb::InstrumentationRuntimeType type)
{
    InstrumentationRuntimeCollection::iterator pos;
    pos = m_instrumentation_runtimes.find (type);
    if (pos == m_instrumentation_runtimes.end())
    {
        return InstrumentationRuntimeSP();
    }
    else
        return (*pos).second;
}

bool
Process::GetModuleSpec(const FileSpec& module_file_spec,
                       const ArchSpec& arch,
                       ModuleSpec& module_spec)
{
    module_spec.Clear();
    return false;
}
