//===-- 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/StructuredDataPlugin.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanBase.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/NameMatches.h"
#include "lldb/Utility/SelectHelper.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,
    ExecutionContext *execution_context) {
  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': {
    TargetSP target_sp =
        execution_context ? execution_context->GetTargetSP() : TargetSP();
    PlatformSP platform_sp =
        target_sp ? target_sp->GetPlatform() : PlatformSP();
    if (!launch_info.GetArchitecture().SetTriple(option_arg, platform_sp.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");
  SetEventName(eBroadcastBitStructuredData, "structured-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 | eBroadcastBitStructuredData);

  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;

  uint32_t new_iohandler_id = 0;
  m_iohandler_sync.WaitForValueNotEqualTo(
      iohandler_id, new_iohandler_id, std::chrono::milliseconds(timeout_msec));

  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 std::chrono::microseconds &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 = %llu)", __FUNCTION__,
                static_cast<unsigned long long>(timeout.count()));

  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 {
      StopInfoSP curr_thread_stop_info_sp;
      // 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();
          curr_thread_stop_info_sp = curr_thread->GetStopInfo();
        }
        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);
          if (curr_thread_stop_info_sp) {
            lldb::addr_t crashing_address;
            ValueObjectSP valobj_sp = StopInfo::GetCrashingDereference(
                curr_thread_stop_info_sp, &crashing_address);
            if (valobj_sp) {
              const bool qualify_cxx_base_classes = false;

              const ValueObject::GetExpressionPathFormat format =
                  ValueObject::GetExpressionPathFormat::
                      eGetExpressionPathFormatHonorPointers;
              stream->PutCString("Likely cause: ");
              valobj_sp->GetExpressionPath(*stream, qualify_cxx_base_classes,
                                           format);
              stream->Printf(" accessed 0x%" PRIx64 "\n", crashing_address);
            }
          }
        } 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 std::chrono::microseconds &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 std::chrono::microseconds &timeout,
                                   EventSP &event_sp,
                                   ListenerSP hijack_listener_sp) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  if (log)
    log->Printf("Process::%s (timeout = %llu, event_sp)...", __FUNCTION__,
                static_cast<unsigned long long>(timeout.count()));

  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 = %llu, event_sp) => %s", __FUNCTION__,
                static_cast<unsigned long long>(timeout.count()),
                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 std::chrono::microseconds &timeout, EventSP &event_sp) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  if (log)
    log->Printf("Process::%s (timeout = %llu, event_sp)...", __FUNCTION__,
                static_cast<unsigned long long>(timeout.count()));

  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 = %llu, event_sp) => %s", __FUNCTION__,
                static_cast<unsigned long long>(timeout.count()),
                state == eStateInvalid ? "TIMEOUT" : StateAsCString(state));
  return state;
}

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

  if (log)
    log->Printf("Process::%s (timeout = %llu, event_sp)...", __FUNCTION__,
                static_cast<unsigned long long>(timeout.count()));

  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(std::chrono::microseconds(0), 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 std::chrono::microseconds &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;
          StateType state =
              WaitForProcessStopPrivate(std::chrono::seconds(10), 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(std::chrono::microseconds(0), 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(std::chrono::microseconds(0), 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.
  StateType state =
      WaitForProcessToStop(std::chrono::seconds(10), &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;

  // Check both the public & private states here.  If we're hung evaluating an
  // expression, for instance, then
  // the public state will be stopped, but we still need to interrupt.
  if (m_public_state.GetValue() == eStateRunning ||
      m_private_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.
    StateType state = WaitForProcessToStop(std::chrono::seconds(10),
                                           &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;
        // Check for a receipt for 2 seconds and then check if the private state
        // thread is still around.
        receipt_received = event_receipt_sp->WaitForEventReceived(
            std::chrono::seconds(2), &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) {
  std::unique_ptr<PrivateStateThreadArgs> args_up(
      static_cast<PrivateStateThreadArgs *>(arg));
  thread_result_t result =
      args_up->process->RunPrivateStateThread(args_up->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(std::chrono::microseconds(0), 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()));
}

void Process::BroadcastStructuredData(const StructuredData::ObjectSP &object_sp,
                                      const StructuredDataPluginSP &plugin_sp) {
  BroadcastEvent(
      eBroadcastBitStructuredData,
      new EventDataStructuredData(shared_from_this(), object_sp, plugin_sp));
}

StructuredDataPluginSP
Process::GetStructuredDataPlugin(const ConstString &type_name) const {
  auto find_it = m_structured_data_plugin_map.find(type_name);
  if (find_it != m_structured_data_plugin_map.end())
    return find_it->second;
  else
    return StructuredDataPluginSP();
}

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()) {
      SelectHelper select_helper;
      select_helper.FDSetRead(read_fd);
      select_helper.FDSetRead(pipe_read_fd);
      Error error = select_helper.Select();

      if (error.Fail()) {
        SetIsDone(true);
      } else {
        char ch = 0;
        size_t n;
        if (select_helper.FDIsSetRead(read_fd)) {
          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 (select_helper.FDIsSetRead(pipe_read_fd)) {
          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;

    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;
    std::chrono::microseconds timeout = std::chrono::microseconds(0);

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

        got_event = listener_sp->WaitForEvent(std::chrono::microseconds(500000),
                                              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())
          timeout = std::chrono::microseconds(one_thread_timeout_usec);
        else
          timeout = std::chrono::microseconds(timeout_usec);
      } else {
        if (timeout_usec == 0)
          timeout = std::chrono::microseconds(0);
        else
          timeout = std::chrono::microseconds(all_threads_timeout_usec);
      }

      do_resume = true;
      handle_running_event = true;

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

      if (log) {
        if (timeout.count()) {
          log->Printf(
              "Process::RunThreadPlan(): about to wait - now is %llu - "
              "endpoint is %llu",
              static_cast<unsigned long long>(
                  std::chrono::system_clock::now().time_since_epoch().count()),
              static_cast<unsigned long long>(
                  std::chrono::time_point<std::chrono::system_clock,
                                          std::chrono::microseconds>(timeout)
                      .time_since_epoch()
                      .count()));
        } 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, 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.");

            got_event = listener_sp->WaitForEvent(
                std::chrono::microseconds(500000), 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);

  // Give structured-data plugins a chance to see the modified modules.
  for (auto pair : m_structured_data_plugin_map) {
    if (pair.second)
      pair.second->ModulesDidLoad(*this, module_list);
  }
}

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

Error Process::ConfigureStructuredData(
    const ConstString &type_name, const StructuredData::ObjectSP &config_sp) {
  // If you get this, the Process-derived class needs to implement a method
  // to enable an already-reported asynchronous structured data feature.
  // See ProcessGDBRemote for an example implementation over gdb-remote.
  return Error("unimplemented");
}

void Process::MapSupportedStructuredDataPlugins(
    const StructuredData::Array &supported_type_names) {
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  // Bail out early if there are no type names to map.
  if (supported_type_names.GetSize() == 0) {
    if (log)
      log->Printf("Process::%s(): no structured data types supported",
                  __FUNCTION__);
    return;
  }

  // Convert StructuredData type names to ConstString instances.
  std::set<ConstString> const_type_names;

  if (log)
    log->Printf("Process::%s(): the process supports the following async "
                "structured data types:",
                __FUNCTION__);

  supported_type_names.ForEach(
      [&const_type_names, &log](StructuredData::Object *object) {
        if (!object) {
          // Invalid - shouldn't be null objects in the array.
          return false;
        }

        auto type_name = object->GetAsString();
        if (!type_name) {
          // Invalid format - all type names should be strings.
          return false;
        }

        const_type_names.insert(ConstString(type_name->GetValue()));
        if (log)
          log->Printf("- %s", type_name->GetValue().c_str());
        return true;
      });

  // For each StructuredDataPlugin, if the plugin handles any of the
  // types in the supported_type_names, map that type name to that plugin.
  uint32_t plugin_index = 0;
  for (auto create_instance =
           PluginManager::GetStructuredDataPluginCreateCallbackAtIndex(
               plugin_index);
       create_instance && !const_type_names.empty(); ++plugin_index) {
    // Create the plugin.
    StructuredDataPluginSP plugin_sp = (*create_instance)(*this);
    if (!plugin_sp) {
      // This plugin doesn't think it can work with the process.
      // Move on to the next.
      continue;
    }

    // For any of the remaining type names, map any that this plugin
    // supports.
    std::vector<ConstString> names_to_remove;
    for (auto &type_name : const_type_names) {
      if (plugin_sp->SupportsStructuredDataType(type_name)) {
        m_structured_data_plugin_map.insert(
            std::make_pair(type_name, plugin_sp));
        names_to_remove.push_back(type_name);
        if (log)
          log->Printf("Process::%s(): using plugin %s for type name "
                      "%s",
                      __FUNCTION__, plugin_sp->GetPluginName().GetCString(),
                      type_name.GetCString());
      }
    }

    // Remove the type names that were consumed by this plugin.
    for (auto &type_name : names_to_remove)
      const_type_names.erase(type_name);
  }
}

bool Process::RouteAsyncStructuredData(
    const StructuredData::ObjectSP object_sp) {
  // Nothing to do if there's no data.
  if (!object_sp)
    return false;

  // The contract is this must be a dictionary, so we can look up the
  // routing key via the top-level 'type' string value within the dictionary.
  StructuredData::Dictionary *dictionary = object_sp->GetAsDictionary();
  if (!dictionary)
    return false;

  // Grab the async structured type name (i.e. the feature/plugin name).
  ConstString type_name;
  if (!dictionary->GetValueForKeyAsString("type", type_name))
    return false;

  // Check if there's a plugin registered for this type name.
  auto find_it = m_structured_data_plugin_map.find(type_name);
  if (find_it == m_structured_data_plugin_map.end()) {
    // We don't have a mapping for this structured data type.
    return false;
  }

  // Route the structured data to the plugin.
  find_it->second->HandleArrivalOfStructuredData(*this, type_name, object_sp);
  return true;
}
