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

// C Includes
// C++ Includes
#include <atomic>
#include <mutex>

// Other libraries and framework includes
// Project includes
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Event.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/DiagnosticManager.h"
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSystem.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/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/InstrumentationRuntime.h"
#include "lldb/Target/JITLoader.h"
#include "lldb/Target/JITLoaderList.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/MemoryHistory.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/OperatingSystem.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/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"

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())
    {
    }
    
    const Property *
    GetPropertyAtIndex(const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const override
    {
        // 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, nullptr, nullptr, "Disable reading and caching of memory in fixed-size units." },
    { "extra-startup-command", OptionValue::eTypeArray  , false, OptionValue::eTypeString, nullptr, nullptr, "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, nullptr, nullptr, "If true, breakpoints will be ignored during expression evaluation." },
    { "unwind-on-error-in-expressions", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "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, nullptr, nullptr, "A path to a python OS plug-in module file that contains a OperatingSystemPlugIn class." },
    { "stop-on-sharedlibrary-events" , OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, stop when a shared library is loaded or unloaded." },
    { "detach-keeps-stopped" , OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, detach will attempt to keep the process stopped." },
    { "memory-cache-line-size" , OptionValue::eTypeUInt64, false, 512, nullptr, nullptr, "The memory cache line size" },
    { "optimization-warnings" , OptionValue::eTypeBoolean, false, true, nullptr, nullptr, "If true, warn when stopped in code that is optimized where stepping and variable availability may not behave as expected." },
    {  nullptr                  , OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr  }
};

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

ProcessProperties::ProcessProperties (lldb_private::Process *process) :
    Properties(),
    m_process(process) // Can be nullptr for global ProcessProperties
{
    if (process == nullptr)
    {
        // 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() = default;

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(nullptr, idx, g_properties[idx].default_uint_value != 0);
}

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

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

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

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

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

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

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

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

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

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

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 = ");
        m_arch.DumpTriple(s);
        s.EOL();
    }

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

        StreamString arch_strm;
        if (m_arch.IsValid())
            m_arch.DumpTriple(arch_strm);

        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 ", arch_strm.GetString().c_str());
        }
        else
        {
            s.Printf ("%-10s %-24s ",
                      platform->GetUserName (m_euid),
                      arch_strm.GetString().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{FileSystem::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,       nullptr, nullptr, 0, eArgTypeNone,          "Stop at the entry point of the program when launching a process." },
{ LLDB_OPT_SET_ALL, false, "disable-aslr",  'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,          "Set whether to disable address space layout randomization when launching a process." },
{ LLDB_OPT_SET_ALL, false, "plugin",        'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin,        "Name of the process plugin you want to use." },
{ LLDB_OPT_SET_ALL, false, "working-dir",   'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeDirectoryName,          "Set the current working directory to <path> when running the inferior." },
{ LLDB_OPT_SET_ALL, false, "arch",          'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture,  "Set the architecture for the process to launch when ambiguous." },
{ LLDB_OPT_SET_ALL, false, "environment",   'v', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeFilename,          "Run the process in a shell (not supported on all platforms)." },

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

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

{ LLDB_OPT_SET_3  , false, "no-stdio",      'n', OptionParser::eNoArgument,       nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeBoolean,          "Set whether to shell expand arguments to the process when launching." },
{ 0               , false, nullptr,             0,  0,                 nullptr, nullptr, 0, eArgTypeNone,    nullptr }
};

bool
ProcessInstanceInfoMatch::NameMatches (const char *process_name) const
{
    if (m_name_match_type == eNameMatchIgnore || process_name == nullptr)
        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 (lldb::TargetSP target_sp, const char *plugin_name, ListenerSP listener_sp, const FileSpec *crash_file_path)
{
    static uint32_t g_process_unique_id = 0;

    ProcessSP process_sp;
    ProcessCreateInstance create_callback = nullptr;
    if (plugin_name)
    {
        ConstString const_plugin_name(plugin_name);
        create_callback  = PluginManager::GetProcessCreateCallbackForPluginName (const_plugin_name);
        if (create_callback)
        {
            process_sp = create_callback(target_sp, listener_sp, crash_file_path);
            if (process_sp)
            {
                if (process_sp->CanDebug(target_sp, 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)) != nullptr; ++idx)
        {
            process_sp = create_callback(target_sp, listener_sp, crash_file_path);
            if (process_sp)
            {
                if (process_sp->CanDebug(target_sp, 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::Process(lldb::TargetSP target_sp, ListenerSP listener_sp) :
    Process(target_sp, listener_sp, UnixSignals::Create(HostInfo::GetArchitecture()))
{
    // This constructor just delegates to the full Process constructor,
    // defaulting to using the Host's UnixSignals.
}

Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, const UnixSignalsSP &unix_signals_sp)
    : ProcessProperties(this),
      UserID(LLDB_INVALID_PROCESS_ID),
      Broadcaster((target_sp->GetDebugger().GetBroadcasterManager()), Process::GetStaticBroadcasterClass().AsCString()),
      m_target_sp(target_sp),
      m_public_state(eStateUnloaded),
      m_private_state(eStateUnloaded),
      m_private_state_broadcaster(nullptr, "lldb.process.internal_state_broadcaster"),
      m_private_state_control_broadcaster(nullptr, "lldb.process.internal_state_control_broadcaster"),
      m_private_state_listener_sp(Listener::MakeListener("lldb.process.internal_state_listener")),
      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(),
      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_sp(listener_sp),
      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(),
      m_stdin_forward(false),
      m_stdout_data(),
      m_stderr_data(),
      m_profile_data_comm_mutex(),
      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_stop_info_override_callback(nullptr),
      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_warnings_issued(),
      m_run_thread_plan_lock(),
      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");

    m_listener_sp->StartListeningForEvents(this, eBroadcastBitStateChanged | eBroadcastBitInterrupt |
                                                     eBroadcastBitSTDOUT | eBroadcastBitSTDERR |
                                                     eBroadcastBitProfileData);

    m_private_state_listener_sp->StartListeningForEvents(&m_private_state_broadcaster,
                                                         eBroadcastBitStateChanged | eBroadcastBitInterrupt);

    m_private_state_listener_sp->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");

    // Allow the platform to override the default cache line size
    OptionValueSP value_sp = m_collection_sp->GetPropertyAtIndex(nullptr, true, ePropertyMemCacheLineSize)->GetValue();
    uint32_t platform_cache_line_size = target_sp->GetPlatform()->GetDefaultMemoryCacheLineSize();
    if (!value_sp->OptionWasSet() && platform_cache_line_size != 0)
        value_sp->SetUInt64Value(platform_cache_line_size);
}

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()
{
    // NOTE: intentional leak so we don't crash if global destructor chain gets
    // called as other threads still use the result of this function
    static ProcessPropertiesSP *g_settings_sp_ptr = nullptr;
    static std::once_flag g_once_flag;
    std::call_once(g_once_flag,  []() {
        g_settings_sp_ptr = new ProcessPropertiesSP(new ProcessProperties(nullptr));
    });
    return *g_settings_sp_ptr;
}

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 = nullptr;
    // 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_sp->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_sp->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 != nullptr)
        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_sp->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,
                               ListenerSP hijack_listener_sp,
                               Stream *stream,
                               bool use_run_lock)
{
    // 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_sp && use_run_lock)
            m_public_run_lock.SetStopped();
        return state;
    }

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

        bool pop_process_io_handler = (hijack_listener_sp.get() != nullptr);
        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_sp && use_run_lock)
                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_sp && use_run_lock)
                    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;

    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();
                    std::lock_guard<std::recursive_mutex> guard(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;
    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, nullptr);

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

bool
Process::HijackProcessEvents (ListenerSP listener_sp)
{
    if (listener_sp)
    {
        return HijackBroadcaster(listener_sp, eBroadcastBitStateChanged | eBroadcastBitInterrupt);
    }
    else
        return false;
}

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

StateType
Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp, ListenerSP hijack_listener_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));

    ListenerSP listener_sp = hijack_listener_sp;
    if (!listener_sp)
        listener_sp = m_listener_sp;

    StateType state = eStateInvalid;
    if (listener_sp->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_sp->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_sp->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_sp->WaitForEventForBroadcaster(timeout, &m_private_state_control_broadcaster, event_sp);
    else
        return m_private_state_listener_sp->WaitForEvent(timeout, event_sp);
}

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

int
Process::GetExitStatus ()
{
    std::lock_guard<std::mutex> guard(m_exit_status_mutex);

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

const char *
Process::GetExitDescription ()
{
    std::lock_guard<std::mutex> guard(m_exit_status_mutex);

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

bool
Process::SetExitStatus (int status, const char *cstr)
{
    // Use a mutex to protect setting the exit status.
    std::lock_guard<std::mutex> guard(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();

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

bool
Process::IsAlive ()
{
    switch (m_private_state.GetValue())
    {
        case eStateConnected:
        case eStateAttaching:
        case eStateLaunching:
        case eStateStopped:
        case eStateRunning:
        case eStateStepping:
        case eStateCrashed:
        case eStateSuspended:
            return true;
        default:
            return false;
    }
}

// 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(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 (pid=%" PRIu64 ", exited=%i, signal=%i, exit_status=%i)\n", 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 = nullptr;
                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))
        {
            std::lock_guard<std::recursive_mutex> guard(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.
                OperatingSystem *os = GetOperatingSystem ();
                if (os && !m_destroy_in_process)
                {
                    // 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)
    {
        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)
{
    return (m_thread_id_to_index_id_map.find(thread_id) != m_thread_id_to_index_id_map.end());
}

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))
    {
        const char *hijacking_name = GetHijackingListenerName();
        if (hijacking_name && strcmp(hijacking_name, "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 (Listener::MakeListener("lldb.Process.ResumeSynchronous.hijack"));
    HijackProcessEvents(listener_sp);

    Error error = PrivateResume();
    if (error.Success())
    {
        StateType state = WaitForProcessToStop (NULL, NULL, true, listener_sp, 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));

    std::lock_guard<std::recursive_mutex> thread_guard(m_thread_list.GetMutex());
    std::lock_guard<std::recursive_mutex> guard(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())
            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;
}

const lldb::ABISP &
Process::GetABI()
{
    if (!m_abi_sp)
        m_abi_sp = ABI::FindPlugin(GetTarget().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 != nullptr && runtime->GetLanguageType() == eLanguageTypeC_plus_plus)
        return static_cast<CPPLanguageRuntime *> (runtime);
    return nullptr;
}

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

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)
            {
                GetTarget().GetDebugger().GetErrorFile()->Printf ("warning: failed to resolve indirect function at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
                                                                   symbol->GetLoadAddress(&GetTarget()),
                                                                   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 (&GetTarget());
            owner->SetIsIndirect(true);
        }
        else
            load_addr = owner->GetAddress().GetOpcodeLoadAddress (&GetTarget());
    }
    else
        load_addr = owner->GetAddress().GetOpcodeLoadAddress (&GetTarget());
    
    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...
                        GetTarget().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 (GetTarget().GetPlatform());
    if (platform_sp)
        return platform_sp->GetSoftwareBreakpointTrapOpcode (GetTarget(), bp_site);
    return 0;
}

Error
Process::EnableSoftwareBreakpoint (BreakpointSite *bp_site)
{
    Error error;
    assert(bp_site != nullptr);
    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 == nullptr)
        {
            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 != nullptr);
    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 (true)
    {
        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 (::memcmp(&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 == nullptr)
            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 == nullptr || 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;
}

int64_t
Process::ReadSignedIntegerFromMemory(lldb::addr_t vm_addr, size_t integer_byte_size, int64_t fail_value, Error &error)
{
    Scalar scalar;
    if (ReadScalarIntegerFromMemory(vm_addr, integer_byte_size, true, scalar, error))
        return scalar.SLongLong(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 == nullptr || 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);
                    UNUSED_IF_ASSERT_DISABLED(intersects);
                    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
}

addr_t
Process::CallocateMemory(size_t size, uint32_t permissions, Error &error)
{
    addr_t return_addr = AllocateMemory(size, permissions, error);
    if (error.Success())
    {
        std::string buffer(size, 0);
        WriteMemory(return_addr, buffer.c_str(), size, error);
    }
    return return_addr;
}

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)
{
    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
    if (log)
    {
        log->Printf ("Process::ReadModuleFromMemory reading %s binary from memory", file_spec.GetPath().c_str());
    }
    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 (true)
    {
        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, nullptr));
    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 = nullptr;

    Module *exe_module = GetTarget().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 == nullptr)
                            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)
                    {
                        // 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())
    {
        ListenerSP listener_sp (Listener::MakeListener("lldb.process.load_core_listener"));
        HijackProcessEvents(listener_sp);

        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, nullptr));
        // 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_sp->WaitForEvent (nullptr, 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)
        m_dyld_ap.reset(DynamicLoader::FindPlugin(this, nullptr));
    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)
        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();
}

ListenerSP
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 = nullptr;
    
    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() == nullptr)
                                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 (GetTarget().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 == nullptr)
                    error_string = "attach failed";

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

void
Process::CompleteAttach ()
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TARGET));
    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())
    {
        GetTarget().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 (GetTarget().GetPlatform ());
    assert(platform_sp);
    if (platform_sp)
    {
        const ArchSpec &target_arch = GetTarget().GetArchitecture();
        if (target_arch.IsValid() && !platform_sp->IsCompatibleArchitecture(target_arch, false, nullptr))
        {
            ArchSpec platform_arch;
            platform_sp = platform_sp->GetPlatformForArchitecture (target_arch, &platform_arch);
            if (platform_sp)
            {
                GetTarget().SetPlatform (platform_sp);
                GetTarget().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;
            GetProcessInfo(process_info);
            const ArchSpec &process_arch = process_info.GetArchitecture();
            if (process_arch.IsValid() && !GetTarget().GetArchitecture().IsExactMatch(process_arch))
            {
                GetTarget().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 = GetTarget().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 = GetTarget().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, nullptr));
    // Figure out which one is the executable, and set that in our target:
    const ModuleList &target_modules = GetTarget().GetImages();
    std::lock_guard<std::recursive_mutex> guard(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 (GetTarget().GetExecutableModulePointer() != module_sp.get())
                new_executable_module_sp = module_sp;
            break;
        }
    }
    if (new_executable_module_sp)
    {
        GetTarget().SetExecutableModule (new_executable_module_sp, false);
        if (log)
        {
            ModuleSP exe_module_sp = GetTarget().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(nullptr, 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, bool use_run_lock)
{
    if (! StateIsRunningState(m_public_state.GetValue()))
        return Error("Process is not running.");

    // 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;
    
    ListenerSP halt_listener_sp (Listener::MakeListener("lldb.process.halt_listener"));
    HijackProcessEvents(halt_listener_sp);

    EventSP event_sp;
    
    SendAsyncInterrupt();

    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...
        RestoreProcessEvents();
        SetExitStatus(SIGKILL, "Cancelled async attach.");
        Destroy (false);
        return Error();
    }

    // Wait for 10 second for the process to stop.
    TimeValue timeout_time;
    timeout_time = TimeValue::Now();
    timeout_time.OffsetWithSeconds(10);
    StateType state = WaitForProcessToStop(&timeout_time, &event_sp, true, halt_listener_sp,
                                           nullptr, use_run_lock);
    RestoreProcessEvents();

    if (state == eStateInvalid || ! event_sp)
    {
        // We timed out and didn't get a stop event...
        return Error("Halt timed out. State = %s", StateAsCString(GetState()));
    }

    BroadcastEvent(event_sp);

    return Error();
}

Error
Process::StopForDestroyOrDetach(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::%s() About to stop.", __FUNCTION__);

        ListenerSP listener_sp (Listener::MakeListener("lldb.Process.StopForDestroyOrDetach.hijack"));
        HijackProcessEvents(listener_sp);

        SendAsyncInterrupt();

        // Consume the interrupt event.
        TimeValue timeout (TimeValue::Now());
        timeout.OffsetWithSeconds(10);

        StateType state = WaitForProcessToStop (&timeout, &exit_event_sp, true, listener_sp);

        RestoreProcessEvents();

        // 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::%s() Process exited while waiting to stop.", __FUNCTION__);
            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::%s() failed to stop, state is: %s", __FUNCTION__, 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("Attempt to stop the target in order to detach timed out. State = %s", StateAsCString(GetState()));
            }
        }
    }
    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 = StopForDestroyOrDetach (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 = StopForDestroyOrDetach(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(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 GetTarget().GetArchitecture().GetByteOrder();
}

uint32_t
Process::GetAddressByteSize () const
{
    return GetTarget().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();
            m_stdio_communication.Disconnect();
            m_stdio_communication.StopReadThread();
            m_stdin_forward = false;

            LLVM_FALLTHROUGH;
        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);

                if (was_restarted || should_resume || m_resume_requested)
                {
                    Vote stop_vote = m_thread_list.ShouldReportStop (event_ptr);
                    if (log)
                        log->Printf ("Process::ShouldBroadcastEvent: should_resume: %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_ptr = new PrivateStateThreadArgs(this, is_secondary_thread);
    m_private_state_thread = ThreadLauncher::LaunchThread(thread_name, Process::PrivateStateThread, (void *) args_ptr, nullptr, 8 * 1024 * 1024);
    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 (m_private_state_thread.IsJoinable ())
        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
    if (m_private_state_thread.IsJoinable())
    {
        // Broadcast the event.
        // It is important to do this outside of the if below, because
        // it's possible that the thread state is invalid but that the
        // thread is waiting on a control event instead of simply being
        // on its way out (this should not happen, but it apparently can).
        if (log)
            log->Printf ("Sending control event of type: %d.", signal);
        std::shared_ptr<EventDataReceipt> event_receipt_sp(new EventDataReceipt());
        m_private_state_control_broadcaster.BroadcastEvent(signal, event_receipt_sp);

        // Wait for the event receipt or for the private state thread to exit
        bool receipt_received = false;
        if (PrivateStateThreadIsValid())
        {
            while (!receipt_received)
            {
                bool timed_out = false;
                TimeValue timeout_time;
                timeout_time = TimeValue::Now();
                timeout_time.OffsetWithSeconds(2);
                // Check for a receipt for 2 seconds and then check if the private state
                // thread is still around.
                receipt_received = event_receipt_sp->WaitForEventReceived (&timeout_time, &timed_out);
                if (!receipt_received)
                {
                    // Check if the private state thread is still around. If it isn't then we are done waiting
                    if (!PrivateStateThreadIsValid())
                        break; // Private state thread exited or is exiting, we are done
                }
            }
        }

        if (signal == eBroadcastInternalStateControlStop)
        {
            thread_result_t result = NULL;
            m_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, nullptr);
    else
        BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr);
}

void
Process::HandlePrivateEvent (EventSP &event_sp)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    m_resume_requested = false;
    
    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)
    {
        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(nullptr);
                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());
                    SetNextEventAction(nullptr);
                    return;
                }
                SetNextEventAction(nullptr);
                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 || !GetTarget().GetDebugger().IsHandlingEvents())
                    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 ()));
        }
    }
}

Error
Process::HaltPrivate()
{
    EventSP event_sp;
    Error error (WillHalt());
    if (error.Fail())
        return error;

    // Ask the process subclass to actually halt our process
    bool caused_stop;
    error = DoHalt(caused_stop);

    DidHalt();
    return error;
}

thread_result_t
Process::PrivateStateThread (void *arg)
{
    PrivateStateThreadArgs real_args = *static_cast<PrivateStateThreadArgs *> (arg);
    free (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;

    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;
    bool interrupt_requested = false;
    while (!exit_now)
    {
        EventSP event_sp;
        WaitForEventsPrivate(nullptr, 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;
            }

            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, nullptr);
            }
            else if(StateIsRunningState(m_last_broadcast_state))
            {
                if (log)
                    log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") woke up with an interrupt - Halting.",
                                 __FUNCTION__, static_cast<void*>(this),
                                 GetID());
                Error error = HaltPrivate();
                if (error.Fail() && log)
                    log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") failed to halt the process: %s",
                                 __FUNCTION__, static_cast<void*>(this),
                                 GetID(), error.AsCString());
                // Halt should generate a stopped event. Make a note of the fact that we were
                // doing the interrupt, so we can set the interrupted flag after we receive the
                // event. We deliberately set this to true even if HaltPrivate failed, so that we
                // can interrupt on the next natural stop.
                interrupt_requested = true;
            }
            else
            {
                // This can happen when someone (e.g. Process::Halt) sees that we are running and
                // sends an interrupt request, but the process actually stops before we receive
                // it. In that case, we can just ignore the request. We use
                // m_last_broadcast_state, because the Stopped event may not have been popped of
                // the event queue yet, which is when the public state gets updated.
                if (log)
                    log->Printf("Process::%s ignoring interrupt as we have already stopped.", __FUNCTION__);
            }
            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();
            }

            if (interrupt_requested)
            {
                if (StateIsStoppedState (internal_state, true))
                {
                    // We requested the interrupt, 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);
                    interrupt_requested = false;
                }
                else if (log)
                {
                    log->Printf("Process::%s interrupt_requested, but a non-stopped state '%s' received.",
                            __FUNCTION__, StateAsCString(internal_state));
                }
            }

            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();
    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() = default;

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)
    {
        // Let process subclasses know we are about to do a public stop and
        // do anything they might need to in order to speed up register and
        // memory accesses.
        process_sp->WillPublicStop();

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

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 == nullptr)
        return eStateInvalid;
    else
        return data->GetState();
}

bool
Process::ProcessEventData::GetRestartedFromEvent (const Event *event_ptr)
{
    const ProcessEventData *data = GetEventDataFromEvent (event_ptr);
    if (data == nullptr)
        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 != nullptr)
        data->SetRestarted(new_value);
}

size_t
Process::ProcessEventData::GetNumRestartedReasons(const Event *event_ptr)
{
    ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr));
    if (data != nullptr)
        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 != nullptr)
        return data->GetRestartedReasonAtIndex(idx);
    else
        return nullptr;
}

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

bool
Process::ProcessEventData::GetInterruptedFromEvent (const Event *event_ptr)
{
    const ProcessEventData *data = GetEventDataFromEvent (event_ptr);
    if (data == nullptr)
        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 != nullptr)
        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_sp.lock();
}

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

//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)
{
    std::lock_guard<std::recursive_mutex> guard(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)
{
    std::lock_guard<std::recursive_mutex> guard(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)
{
    std::lock_guard<std::recursive_mutex> guard(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)
{
    std::lock_guard<std::recursive_mutex> guard(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)
{
    std::lock_guard<std::recursive_mutex> guard(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)
{
    std::lock_guard<std::recursive_mutex> gaurd(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);
    }

    ~IOHandlerProcessSTDIO() override = default;

    // 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();
        m_is_running = true;
        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, nullptr, nullptr, nullptr);

            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->SendAsyncInterrupt();
                                break;
                        }
                    }
                }
            }
        }
        m_is_running = false;
#endif
        terminal_state.Restore();
    }
    
    void
    Cancel () override
    {
        SetIsDone(true);
        // Only write to our pipe to cancel if we are in IOHandlerProcessSTDIO::Run().
        // We can end up with a python command that is being run from the command
        // interpreter:
        //
        // (lldb) step_process_thousands_of_times
        //
        // In this case the command interpreter will be in the middle of handling
        // the command and if the process pushes and pops the IOHandler thousands
        // of times, we can end up writing to m_pipe without ever consuming the
        // bytes from the pipe in IOHandlerProcessSTDIO::Run() and end up
        // deadlocking when the pipe gets fed up and blocks until data is consumed.
        if (m_is_running)
        {
            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->SendAsyncInterrupt()
        // 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;
    std::atomic<bool> m_is_running;
};

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)
    {
        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)
                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 GetTarget().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);
        GetTarget().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 GetTarget().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 ();
}

namespace
{
    // RestorePlanState is used to record the "is private", "is master" and "okay to discard" fields of
    // the plan we are running, and reset it on Clean or on destruction.
    // It will only reset the state once, so you can call Clean and then monkey with the state and it
    // won't get reset on you again.
    
    class RestorePlanState
    {
    public:
        RestorePlanState (lldb::ThreadPlanSP thread_plan_sp) :
            m_thread_plan_sp(thread_plan_sp),
            m_already_reset(false)
        {
            if (m_thread_plan_sp)
            {
                m_private = m_thread_plan_sp->GetPrivate();
                m_is_master = m_thread_plan_sp->IsMasterPlan();
                m_okay_to_discard = m_thread_plan_sp->OkayToDiscard();
            }
        }
        
        ~RestorePlanState()
        {
            Clean();
        }
        
        void
        Clean ()
        {
            if (!m_already_reset && m_thread_plan_sp)
            {
                m_already_reset = true;
                m_thread_plan_sp->SetPrivate(m_private);
                m_thread_plan_sp->SetIsMasterPlan (m_is_master);
                m_thread_plan_sp->SetOkayToDiscard(m_okay_to_discard);
            }
        }

    private:
        lldb::ThreadPlanSP m_thread_plan_sp;
        bool m_already_reset;
        bool m_private;
        bool m_is_master;
        bool m_okay_to_discard;
    };
} // anonymous namespace

ExpressionResults
Process::RunThreadPlan(ExecutionContext &exe_ctx, lldb::ThreadPlanSP &thread_plan_sp,
                       const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager)
{
    ExpressionResults return_value = eExpressionSetupError;
    
    std::lock_guard<std::mutex> run_thread_plan_locker(m_run_thread_plan_lock);

    if (!thread_plan_sp)
    {
        diagnostic_manager.PutCString(eDiagnosticSeverityError, "RunThreadPlan called with empty thread plan.");
        return eExpressionSetupError;
    }

    if (!thread_plan_sp->ValidatePlan(nullptr))
    {
        diagnostic_manager.PutCString(eDiagnosticSeverityError, "RunThreadPlan called with an invalid thread plan.");
        return eExpressionSetupError;
    }

    if (exe_ctx.GetProcessPtr() != this)
    {
        diagnostic_manager.PutCString(eDiagnosticSeverityError, "RunThreadPlan called on wrong process.");
        return eExpressionSetupError;
    }

    Thread *thread = exe_ctx.GetThreadPtr();
    if (thread == nullptr)
    {
        diagnostic_manager.PutCString(eDiagnosticSeverityError, "RunThreadPlan called with invalid thread.");
        return eExpressionSetupError;
    }

    // We need to change some of the thread plan attributes for the thread plan runner.  This will restore them
    // when we are done:
        
    RestorePlanState thread_plan_restorer(thread_plan_sp);
    
    // 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. 

    thread_plan_sp->SetPrivate(false);
    
    // The plans run with RunThreadPlan also need to be terminal master plans or when they are done we will end
    // up asking the plan above us whether we should stop, which may give the wrong answer.
    
    thread_plan_sp->SetIsMasterPlan (true);
    thread_plan_sp->SetOkayToDiscard(false);

    if (m_private_state.GetValue() != eStateStopped)
    {
        diagnostic_manager.PutCString(eDiagnosticSeverityError,
                                      "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(nullptr);
        selected_frame_sp = thread->GetSelectedFrame();
        if (!selected_frame_sp)
        {
            diagnostic_manager.Printf(eDiagnosticSeverityError,
                                      "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;
    }

    ListenerSP listener_sp(Listener::MakeListener("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_sp);

        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 = nullptr;
        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)
                    {
                        diagnostic_manager.PutCString(
                            eDiagnosticSeverityError,
                            "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_sp->PeekAtNextEvent();
        if (other_events != nullptr)
        {
            diagnostic_manager.PutCString(eDiagnosticSeverityError,
                                          "RunThreadPlan called 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 (true)
        {
            // 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())
                    {
                        diagnostic_manager.Printf(eDiagnosticSeverityError,
                                                  "couldn't resume inferior the %d time: \"%s\".", num_resumes,
                                                  resume_error.AsCString());
                        return_value = eExpressionSetupError;
                        break;
                    }
                }

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

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

                    diagnostic_manager.Printf(eDiagnosticSeverityError,
                                              "didn't get any event after resume %" PRIu32 ", 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.
                        const bool clear_thread_plans = false;
                        const bool use_run_lock = false;
                        Halt(clear_thread_plans, use_run_lock);
                    }

                    diagnostic_manager.Printf(eDiagnosticSeverityError,
                                              "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 = nullptr;
                    else
                    {
                        final_timeout = TimeValue::Now();
                        final_timeout.OffsetWithMicroSeconds (timeout_usec);
                        timeout_ptr = &final_timeout;
                    }
                }
            }
            else
            {
                if (timeout_usec == 0)
                    timeout_ptr = nullptr;
                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_sp->WaitForEvent (timeout_ptr, event_sp);

            if (got_event)
            {
                if (event_sp)
                {
                    bool keep_going = false;
                    if (event_sp->GetType() == eBroadcastBitInterrupt)
                    {
                        const bool clear_thread_plans = false;
                        const bool use_run_lock = false;
                        Halt(clear_thread_plans, use_run_lock);
                        return_value = eExpressionInterrupted;
                        diagnostic_manager.PutCString(eDiagnosticSeverityRemark, "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.");
                                            
                                            // Restore the plan state so it will get reported as intended when we are done.
                                            thread_plan_restorer.Clean();
                                            
                                            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())
                                                {
                                                    // Restore the plan state and then force Private to false.  We are
                                                    // going to stop because of this plan so we need it to become a public
                                                    // plan or it won't report correctly when we continue to its termination
                                                    // later on.
                                                    thread_plan_restorer.Clean();
                                                    if (thread_plan_sp)
                                                        thread_plan_sp->SetPrivate(false);
                                                    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;

                            diagnostic_manager.PutCString(eDiagnosticSeverityError,
                                                          "execution stopped with unexpected state.");
                            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.");
                        const bool clear_thread_plans = false;
                        const bool use_run_lock = false;
                        Halt(clear_thread_plans, use_run_lock);
                    }
                    if (halt_error.Success())
                    {
                        if (log)
                            log->PutCString ("Process::RunThreadPlan(): Halt succeeded.");

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

                        got_event = listener_sp->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);
        }

        if (return_value != eExpressionCompleted && log)
        {
            // Print a backtrace into the log so we can figure out where we are:
            StreamString s;
            s.PutCString("Thread state after unsuccessful completion: \n");
            thread->GetStackFrameStatus (s,
                                         0,
                                         UINT32_MAX,
                                         true,
                                         UINT32_MAX);
            log->PutCString(s.GetData());

        }
        // 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 = nullptr;                

                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] ");

                            // Show the private stop info here, the public stop info will be from the last natural stop.
                            lldb::StopInfoSP stop_info_sp = thread->GetPrivateStopInfo();
                            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);
            }
            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);
            }
        }
        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 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:
                std::lock_guard<std::recursive_mutex> guard(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;
    {
        std::lock_guard<std::recursive_mutex> guard(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 || !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) 
            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 = nullptr;
    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
        // nullptr 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);
    }

    // If we don't have an operating system plug-in, try to load one since
    // loading shared libraries might cause a new one to try and load
    if (!m_os_ap)
        LoadOperatingSystemPlugin(false);
}

void
Process::PrintWarning (uint64_t warning_type, const void *repeat_key, const char *fmt, ...)
{
    bool print_warning = true;

    StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream();
    if (!stream_sp)
        return;
    if (warning_type == eWarningsOptimization
        && !GetWarningsOptimization())
    {
        return;
    }

    if (repeat_key != nullptr)
    {
        WarningsCollection::iterator it = m_warnings_issued.find (warning_type);
        if (it == m_warnings_issued.end())
        {
            m_warnings_issued[warning_type] = WarningsPointerSet();
            m_warnings_issued[warning_type].insert (repeat_key);
        }
        else
        {
            if (it->second.find (repeat_key) != it->second.end())
            {
                print_warning = false;
            }
            else
            {
                it->second.insert (repeat_key);
            }
        }
    }

    if (print_warning)
    {
        va_list args;
        va_start (args, fmt);
        stream_sp->PrintfVarArg (fmt, args);
        va_end (args);
    }
}

void
Process::PrintWarningOptimization (const SymbolContext &sc)
{
    if (GetWarningsOptimization()
        && sc.module_sp
        && !sc.module_sp->GetFileSpec().GetFilename().IsEmpty()
        && sc.function
        && sc.function->GetIsOptimized())
    {
        PrintWarning (Process::Warnings::eWarningsOptimization, sc.module_sp.get(), "%s was compiled with optimization - stepping may behave oddly; variables may not be available.\n", sc.module_sp->GetFileSpec().GetFilename().GetCString());
    }
}

bool
Process::GetProcessInfo(ProcessInstanceInfo &info)
{
    info.Clear();

    PlatformSP platform_sp = GetTarget().GetPlatform();
    if (! platform_sp)
        return false;

    return platform_sp->GetProcessInfo(GetID(), info);
}

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

    const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(shared_from_this());
    
    if (!memory_history) {
        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;
}

size_t
Process::AddImageToken(lldb::addr_t image_ptr)
{
    m_image_tokens.push_back(image_ptr);
    return m_image_tokens.size() - 1;
}

lldb::addr_t
Process::GetImagePtrFromToken(size_t token) const
{
    if (token < m_image_tokens.size())
        return m_image_tokens[token];
    return LLDB_INVALID_IMAGE_TOKEN;
}

void
Process::ResetImageToken(size_t token)
{
    if (token < m_image_tokens.size())
        m_image_tokens[token] = LLDB_INVALID_IMAGE_TOKEN;
}

Address
Process::AdvanceAddressToNextBranchInstruction (Address default_stop_addr, AddressRange range_bounds)
{
    Target &target = GetTarget();
    DisassemblerSP disassembler_sp;
    InstructionList *insn_list = nullptr;

    Address retval = default_stop_addr;

    if (!target.GetUseFastStepping())
        return retval;
    if (!default_stop_addr.IsValid())
        return retval;

    ExecutionContext exe_ctx (this);
    const char *plugin_name = nullptr;
    const char *flavor = nullptr;
    const bool prefer_file_cache = true;
    disassembler_sp = Disassembler::DisassembleRange(target.GetArchitecture(),
                                                     plugin_name,
                                                     flavor,
                                                     exe_ctx,
                                                     range_bounds,
                                                     prefer_file_cache);
    if (disassembler_sp)
        insn_list = &disassembler_sp->GetInstructionList();

    if (insn_list == nullptr)
    {
        return retval;
    }

    size_t insn_offset = insn_list->GetIndexOfInstructionAtAddress (default_stop_addr);
    if (insn_offset == UINT32_MAX)
    {
        return retval;
    }

    uint32_t branch_index = insn_list->GetIndexOfNextBranchInstruction (insn_offset, target);
    if (branch_index == UINT32_MAX)
    {
        return retval;
    }

    if (branch_index > insn_offset)
    {
        Address next_branch_insn_address = insn_list->GetInstructionAtIndex (branch_index)->GetAddress();
        if (next_branch_insn_address.IsValid() && range_bounds.ContainsFileAddress (next_branch_insn_address))
        {
            retval = next_branch_insn_address;
        }
    }

    return retval;
}

Error
Process::GetMemoryRegions (std::vector<lldb::MemoryRegionInfoSP>& region_list)
{

    Error error;

    lldb::addr_t range_base = 0;
    lldb::addr_t range_end = 0;

    region_list.clear();
    do
    {
        lldb::MemoryRegionInfoSP region_info( new lldb_private::MemoryRegionInfo() );
        error = GetMemoryRegionInfo (range_end, *region_info);
        // GetMemoryRegionInfo should only return an error if it is unimplemented.
        if (error.Fail())
        {
            region_list.clear();
            break;
        }

        range_base = region_info->GetRange().GetRangeBase();
        range_end = region_info->GetRange().GetRangeEnd();
        if( region_info->GetMapped() == MemoryRegionInfo::eYes )
        {
            region_list.push_back(region_info);
        }
    } while (range_end != LLDB_INVALID_ADDRESS);

    return error;

}
