//===-- 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, UnixSignals::Create(HostInfo::GetArchitecture()))
{
    // 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_interpret_function_calls(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 = std::make_shared<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 eStopReasonSignal:
                                {
                                    // Don't select a signal thread if we weren't going to stop at that
                                    // signal.  We have to have had another reason for stopping here, and
                                    // the user doesn't want to see this thread.
                                    uint64_t signo = thread->GetStopInfo()->GetValue();
                                    if (process_sp->GetUnixSignals()->GetShouldStop(signo))
                                    {
                                        if (!other_thread)
                                            other_thread = thread;
                                    }
                                    break;
                                }
                                case eStopReasonTrace:
                                case eStopReasonBreakpoint:
                                case eStopReasonWatchpoint:
                                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)
{
    // Use a mutex to protect setting the exit status.
    Mutex::Locker locker (m_exit_status_mutex);

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

    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.Disconnect();
    m_stdio_communication.StopReadThread();
    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;
            Address symbol_address = symbol->GetAddress();
            load_addr = ResolveIndirectFunction (&symbol_address, 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->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 the 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);
}

void
Process::SetCanRunCode (bool can_run_code)
{
    SetCanJIT(can_run_code);
    m_can_interpret_function_calls = can_run_code;
}

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.Disconnect();
        m_stdio_communication.StopReadThread();
        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;
}

const lldb::UnixSignalsSP &
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 is_secondary_thread)
{
    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 (!is_secondary_thread && 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.
    PrivateStateThreadArgs args = {this, is_secondary_thread};
    m_private_state_thread = ThreadLauncher::LaunchThread(thread_name, Process::PrivateStateThread, (void *) &args, 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)
{
    PrivateStateThreadArgs *real_args = static_cast<PrivateStateThreadArgs *> (arg);
    thread_result_t result = real_args->process->RunPrivateStateThread(real_args->is_secondary_thread);
    return result;
}

thread_result_t
Process::RunPrivateStateThread (bool is_secondary_thread)
{
    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());

    // If we are a secondary thread, then the primary thread we are working for will have already
    // acquired the public_run_lock, and isn't done with what it was doing yet, so don't
    // try to change it on the way out.
    if (!is_secondary_thread)
        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;
}
