//===-- ProcessGDBRemote.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Host/Config.h"

#include <cerrno>
#include <cstdlib>
#if LLDB_ENABLE_POSIX
#include <netinet/in.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
#include <sys/stat.h>
#if defined(__APPLE__)
#include <sys/sysctl.h>
#endif
#include <ctime>
#include <sys/types.h>

#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Breakpoint/WatchpointAlgorithms.h"
#include "lldb/Breakpoint/WatchpointResource.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Value.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/XML.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/RegisterFlags.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
#include <algorithm>
#include <csignal>
#include <map>
#include <memory>
#include <mutex>
#include <optional>
#include <sstream>
#include <thread>

#include "GDBRemoteRegisterContext.h"
#include "GDBRemoteRegisterFallback.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "Plugins/Process/Utility/StopInfoMachException.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "ThreadGDBRemote.h"
#include "lldb/Host/Host.h"
#include "lldb/Utility/StringExtractorGDBRemote.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorExtras.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"

#if defined(__APPLE__)
#define DEBUGSERVER_BASENAME "debugserver"
#elif defined(_WIN32)
#define DEBUGSERVER_BASENAME "lldb-server.exe"
#else
#define DEBUGSERVER_BASENAME "lldb-server"
#endif

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;

LLDB_PLUGIN_DEFINE(ProcessGDBRemote)

namespace lldb {
// Provide a function that can easily dump the packet history if we know a
// ProcessGDBRemote * value (which we can get from logs or from debugging). We
// need the function in the lldb namespace so it makes it into the final
// executable since the LLDB shared library only exports stuff in the lldb
// namespace. This allows you to attach with a debugger and call this function
// and get the packet history dumped to a file.
void DumpProcessGDBRemotePacketHistory(void *p, const char *path) {
  auto file = FileSystem::Instance().Open(
      FileSpec(path), File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate);
  if (!file) {
    llvm::consumeError(file.takeError());
    return;
  }
  StreamFile stream(std::move(file.get()));
  ((Process *)p)->DumpPluginHistory(stream);
}
} // namespace lldb

namespace {

#define LLDB_PROPERTIES_processgdbremote
#include "ProcessGDBRemoteProperties.inc"

enum {
#define LLDB_PROPERTIES_processgdbremote
#include "ProcessGDBRemotePropertiesEnum.inc"
};

class PluginProperties : public Properties {
public:
  static llvm::StringRef GetSettingName() {
    return ProcessGDBRemote::GetPluginNameStatic();
  }

  PluginProperties() : Properties() {
    m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
    m_collection_sp->Initialize(g_processgdbremote_properties_def);
  }

  ~PluginProperties() override = default;

  uint64_t GetPacketTimeout() {
    const uint32_t idx = ePropertyPacketTimeout;
    return GetPropertyAtIndexAs<uint64_t>(
        idx, g_processgdbremote_properties[idx].default_uint_value);
  }

  bool SetPacketTimeout(uint64_t timeout) {
    const uint32_t idx = ePropertyPacketTimeout;
    return SetPropertyAtIndex(idx, timeout);
  }

  FileSpec GetTargetDefinitionFile() const {
    const uint32_t idx = ePropertyTargetDefinitionFile;
    return GetPropertyAtIndexAs<FileSpec>(idx, {});
  }

  bool GetUseSVR4() const {
    const uint32_t idx = ePropertyUseSVR4;
    return GetPropertyAtIndexAs<bool>(
        idx, g_processgdbremote_properties[idx].default_uint_value != 0);
  }

  bool GetUseGPacketForReading() const {
    const uint32_t idx = ePropertyUseGPacketForReading;
    return GetPropertyAtIndexAs<bool>(idx, true);
  }
};

std::chrono::seconds ResumeTimeout() { return std::chrono::seconds(5); }

} // namespace

static PluginProperties &GetGlobalPluginProperties() {
  static PluginProperties g_settings;
  return g_settings;
}

// TODO Randomly assigning a port is unsafe.  We should get an unused
// ephemeral port from the kernel and make sure we reserve it before passing it
// to debugserver.

#if defined(__APPLE__)
#define LOW_PORT (IPPORT_RESERVED)
#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
#else
#define LOW_PORT (1024u)
#define HIGH_PORT (49151u)
#endif

llvm::StringRef ProcessGDBRemote::GetPluginDescriptionStatic() {
  return "GDB Remote protocol based debugging plug-in.";
}

void ProcessGDBRemote::Terminate() {
  PluginManager::UnregisterPlugin(ProcessGDBRemote::CreateInstance);
}

lldb::ProcessSP ProcessGDBRemote::CreateInstance(
    lldb::TargetSP target_sp, ListenerSP listener_sp,
    const FileSpec *crash_file_path, bool can_connect) {
  if (crash_file_path)
    return nullptr; // Cannot create a GDBRemote process from a crash_file.
  return lldb::ProcessSP(new ProcessGDBRemote(target_sp, listener_sp));
}

void ProcessGDBRemote::DumpPluginHistory(Stream &s) {
  GDBRemoteCommunicationClient &gdb_comm(GetGDBRemote());
  gdb_comm.DumpHistory(s);
}

std::chrono::seconds ProcessGDBRemote::GetPacketTimeout() {
  return std::chrono::seconds(GetGlobalPluginProperties().GetPacketTimeout());
}

ArchSpec ProcessGDBRemote::GetSystemArchitecture() {
  return m_gdb_comm.GetHostArchitecture();
}

bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp,
                                bool plugin_specified_by_name) {
  if (plugin_specified_by_name)
    return true;

  // For now we are just making sure the file exists for a given module
  Module *exe_module = target_sp->GetExecutableModulePointer();
  if (exe_module) {
    ObjectFile *exe_objfile = exe_module->GetObjectFile();
    // We can't debug core files...
    switch (exe_objfile->GetType()) {
    case ObjectFile::eTypeInvalid:
    case ObjectFile::eTypeCoreFile:
    case ObjectFile::eTypeDebugInfo:
    case ObjectFile::eTypeObjectFile:
    case ObjectFile::eTypeSharedLibrary:
    case ObjectFile::eTypeStubLibrary:
    case ObjectFile::eTypeJIT:
      return false;
    case ObjectFile::eTypeExecutable:
    case ObjectFile::eTypeDynamicLinker:
    case ObjectFile::eTypeUnknown:
      break;
    }
    return FileSystem::Instance().Exists(exe_module->GetFileSpec());
  }
  // However, if there is no executable module, we return true since we might
  // be preparing to attach.
  return true;
}

// ProcessGDBRemote constructor
ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
                                   ListenerSP listener_sp)
    : Process(target_sp, listener_sp),
      m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_register_info_sp(nullptr),
      m_async_broadcaster(nullptr, "lldb.process.gdb-remote.async-broadcaster"),
      m_async_listener_sp(
          Listener::MakeListener("lldb.process.gdb-remote.async-listener")),
      m_async_thread_state_mutex(), m_thread_ids(), m_thread_pcs(),
      m_jstopinfo_sp(), m_jthreadsinfo_sp(), m_shared_cache_info_sp(),
      m_shared_cache_info_mutex(), m_continue_c_tids(), m_continue_C_tids(),
      m_continue_s_tids(), m_continue_S_tids(), m_max_memory_size(0),
      m_remote_stub_max_memory_size(0), m_addr_to_mmap_size(),
      m_thread_create_bp_sp(), m_waiting_for_attach(false), m_command_sp(),
      m_breakpoint_pc_offset(0), m_initial_tid(LLDB_INVALID_THREAD_ID),
      m_allow_flash_writes(false), m_erased_flash_ranges(),
      m_vfork_in_progress_count(0) {
  m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
                                   "async thread should exit");
  m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
                                   "async thread continue");
  m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit,
                                   "async thread did exit");

  Log *log = GetLog(GDBRLog::Async);

  const uint32_t async_event_mask =
      eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;

  if (m_async_listener_sp->StartListeningForEvents(
          &m_async_broadcaster, async_event_mask) != async_event_mask) {
    LLDB_LOGF(log,
              "ProcessGDBRemote::%s failed to listen for "
              "m_async_broadcaster events",
              __FUNCTION__);
  }

  const uint64_t timeout_seconds =
      GetGlobalPluginProperties().GetPacketTimeout();
  if (timeout_seconds > 0)
    m_gdb_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds));

  m_use_g_packet_for_reading =
      GetGlobalPluginProperties().GetUseGPacketForReading();
}

// Destructor
ProcessGDBRemote::~ProcessGDBRemote() {
  //  m_mach_process.UnregisterNotificationCallbacks (this);
  Clear();
  // We need to call finalize on the process before destroying ourselves to
  // make sure all of the broadcaster cleanup goes as planned. If we destruct
  // this class, then Process::~Process() might have problems trying to fully
  // destroy the broadcaster.
  Finalize(true /* destructing */);

  // The general Finalize is going to try to destroy the process and that
  // SHOULD shut down the async thread.  However, if we don't kill it it will
  // get stranded and its connection will go away so when it wakes up it will
  // crash.  So kill it for sure here.
  StopAsyncThread();
  KillDebugserverProcess();
}

std::shared_ptr<ThreadGDBRemote>
ProcessGDBRemote::CreateThread(lldb::tid_t tid) {
  return std::make_shared<ThreadGDBRemote>(*this, tid);
}

bool ProcessGDBRemote::ParsePythonTargetDefinition(
    const FileSpec &target_definition_fspec) {
  ScriptInterpreter *interpreter =
      GetTarget().GetDebugger().GetScriptInterpreter();
  Status error;
  StructuredData::ObjectSP module_object_sp(
      interpreter->LoadPluginModule(target_definition_fspec, error));
  if (module_object_sp) {
    StructuredData::DictionarySP target_definition_sp(
        interpreter->GetDynamicSettings(module_object_sp, &GetTarget(),
                                        "gdb-server-target-definition", error));

    if (target_definition_sp) {
      StructuredData::ObjectSP target_object(
          target_definition_sp->GetValueForKey("host-info"));
      if (target_object) {
        if (auto host_info_dict = target_object->GetAsDictionary()) {
          StructuredData::ObjectSP triple_value =
              host_info_dict->GetValueForKey("triple");
          if (auto triple_string_value = triple_value->GetAsString()) {
            std::string triple_string =
                std::string(triple_string_value->GetValue());
            ArchSpec host_arch(triple_string.c_str());
            if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture())) {
              GetTarget().SetArchitecture(host_arch);
            }
          }
        }
      }
      m_breakpoint_pc_offset = 0;
      StructuredData::ObjectSP breakpoint_pc_offset_value =
          target_definition_sp->GetValueForKey("breakpoint-pc-offset");
      if (breakpoint_pc_offset_value) {
        if (auto breakpoint_pc_int_value =
                breakpoint_pc_offset_value->GetAsSignedInteger())
          m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue();
      }

      if (m_register_info_sp->SetRegisterInfo(
              *target_definition_sp, GetTarget().GetArchitecture()) > 0) {
        return true;
      }
    }
  }
  return false;
}

static size_t SplitCommaSeparatedRegisterNumberString(
    const llvm::StringRef &comma_separated_register_numbers,
    std::vector<uint32_t> &regnums, int base) {
  regnums.clear();
  for (llvm::StringRef x : llvm::split(comma_separated_register_numbers, ',')) {
    uint32_t reg;
    if (llvm::to_integer(x, reg, base))
      regnums.push_back(reg);
  }
  return regnums.size();
}

void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
  if (!force && m_register_info_sp)
    return;

  m_register_info_sp = std::make_shared<GDBRemoteDynamicRegisterInfo>();

  // Check if qHostInfo specified a specific packet timeout for this
  // connection. If so then lets update our setting so the user knows what the
  // timeout is and can see it.
  const auto host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout();
  if (host_packet_timeout > std::chrono::seconds(0)) {
    GetGlobalPluginProperties().SetPacketTimeout(host_packet_timeout.count());
  }

  // Register info search order:
  //     1 - Use the target definition python file if one is specified.
  //     2 - If the target definition doesn't have any of the info from the
  //     target.xml (registers) then proceed to read the target.xml.
  //     3 - Fall back on the qRegisterInfo packets.
  //     4 - Use hardcoded defaults if available.

  FileSpec target_definition_fspec =
      GetGlobalPluginProperties().GetTargetDefinitionFile();
  if (!FileSystem::Instance().Exists(target_definition_fspec)) {
    // If the filename doesn't exist, it may be a ~ not having been expanded -
    // try to resolve it.
    FileSystem::Instance().Resolve(target_definition_fspec);
  }
  if (target_definition_fspec) {
    // See if we can get register definitions from a python file
    if (ParsePythonTargetDefinition(target_definition_fspec))
      return;

    Debugger::ReportError("target description file " +
                              target_definition_fspec.GetPath() +
                              " failed to parse",
                          GetTarget().GetDebugger().GetID());
  }

  const ArchSpec &target_arch = GetTarget().GetArchitecture();
  const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture();
  const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();

  // Use the process' architecture instead of the host arch, if available
  ArchSpec arch_to_use;
  if (remote_process_arch.IsValid())
    arch_to_use = remote_process_arch;
  else
    arch_to_use = remote_host_arch;

  if (!arch_to_use.IsValid())
    arch_to_use = target_arch;

  llvm::Error register_info_err = GetGDBServerRegisterInfo(arch_to_use);
  if (!register_info_err) {
    // We got the registers from target XML.
    return;
  }

  Log *log = GetLog(GDBRLog::Process);
  LLDB_LOG_ERROR(log, std::move(register_info_err),
                 "Failed to read register information from target XML: {0}");
  LLDB_LOG(log, "Now trying to use qRegisterInfo instead.");

  char packet[128];
  std::vector<DynamicRegisterInfo::Register> registers;
  uint32_t reg_num = 0;
  for (StringExtractorGDBRemote::ResponseType response_type =
           StringExtractorGDBRemote::eResponse;
       response_type == StringExtractorGDBRemote::eResponse; ++reg_num) {
    const int packet_len =
        ::snprintf(packet, sizeof(packet), "qRegisterInfo%x", reg_num);
    assert(packet_len < (int)sizeof(packet));
    UNUSED_IF_ASSERT_DISABLED(packet_len);
    StringExtractorGDBRemote response;
    if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response) ==
        GDBRemoteCommunication::PacketResult::Success) {
      response_type = response.GetResponseType();
      if (response_type == StringExtractorGDBRemote::eResponse) {
        llvm::StringRef name;
        llvm::StringRef value;
        DynamicRegisterInfo::Register reg_info;

        while (response.GetNameColonValue(name, value)) {
          if (name == "name") {
            reg_info.name.SetString(value);
          } else if (name == "alt-name") {
            reg_info.alt_name.SetString(value);
          } else if (name == "bitsize") {
            if (!value.getAsInteger(0, reg_info.byte_size))
              reg_info.byte_size /= CHAR_BIT;
          } else if (name == "offset") {
            value.getAsInteger(0, reg_info.byte_offset);
          } else if (name == "encoding") {
            const Encoding encoding = Args::StringToEncoding(value);
            if (encoding != eEncodingInvalid)
              reg_info.encoding = encoding;
          } else if (name == "format") {
            if (!OptionArgParser::ToFormat(value.str().c_str(), reg_info.format, nullptr)
                    .Success())
              reg_info.format =
                  llvm::StringSwitch<Format>(value)
                      .Case("boolean", eFormatBoolean)
                      .Case("binary", eFormatBinary)
                      .Case("bytes", eFormatBytes)
                      .Case("bytes-with-ascii", eFormatBytesWithASCII)
                      .Case("char", eFormatChar)
                      .Case("char-printable", eFormatCharPrintable)
                      .Case("complex", eFormatComplex)
                      .Case("cstring", eFormatCString)
                      .Case("decimal", eFormatDecimal)
                      .Case("enum", eFormatEnum)
                      .Case("hex", eFormatHex)
                      .Case("hex-uppercase", eFormatHexUppercase)
                      .Case("float", eFormatFloat)
                      .Case("octal", eFormatOctal)
                      .Case("ostype", eFormatOSType)
                      .Case("unicode16", eFormatUnicode16)
                      .Case("unicode32", eFormatUnicode32)
                      .Case("unsigned", eFormatUnsigned)
                      .Case("pointer", eFormatPointer)
                      .Case("vector-char", eFormatVectorOfChar)
                      .Case("vector-sint64", eFormatVectorOfSInt64)
                      .Case("vector-float16", eFormatVectorOfFloat16)
                      .Case("vector-float64", eFormatVectorOfFloat64)
                      .Case("vector-sint8", eFormatVectorOfSInt8)
                      .Case("vector-uint8", eFormatVectorOfUInt8)
                      .Case("vector-sint16", eFormatVectorOfSInt16)
                      .Case("vector-uint16", eFormatVectorOfUInt16)
                      .Case("vector-sint32", eFormatVectorOfSInt32)
                      .Case("vector-uint32", eFormatVectorOfUInt32)
                      .Case("vector-float32", eFormatVectorOfFloat32)
                      .Case("vector-uint64", eFormatVectorOfUInt64)
                      .Case("vector-uint128", eFormatVectorOfUInt128)
                      .Case("complex-integer", eFormatComplexInteger)
                      .Case("char-array", eFormatCharArray)
                      .Case("address-info", eFormatAddressInfo)
                      .Case("hex-float", eFormatHexFloat)
                      .Case("instruction", eFormatInstruction)
                      .Case("void", eFormatVoid)
                      .Case("unicode8", eFormatUnicode8)
                      .Case("float128", eFormatFloat128)
                      .Default(eFormatInvalid);
          } else if (name == "set") {
            reg_info.set_name.SetString(value);
          } else if (name == "gcc" || name == "ehframe") {
            value.getAsInteger(0, reg_info.regnum_ehframe);
          } else if (name == "dwarf") {
            value.getAsInteger(0, reg_info.regnum_dwarf);
          } else if (name == "generic") {
            reg_info.regnum_generic = Args::StringToGenericRegister(value);
          } else if (name == "container-regs") {
            SplitCommaSeparatedRegisterNumberString(value, reg_info.value_regs, 16);
          } else if (name == "invalidate-regs") {
            SplitCommaSeparatedRegisterNumberString(value, reg_info.invalidate_regs, 16);
          }
        }

        assert(reg_info.byte_size != 0);
        registers.push_back(reg_info);
      } else {
        // Only warn if we were offered Target XML and could not use it, and
        // the qRegisterInfo fallback failed. This is something a user could
        // take action on by getting an lldb with libxml2.
        //
        // It's possible we weren't offered Target XML and qRegisterInfo failed,
        // but there's no much a user can do about that. It may be the intended
        // way the debug stub works, so we do not warn for that case.
        if (response_type == StringExtractorGDBRemote::eUnsupported &&
            m_gdb_comm.GetQXferFeaturesReadSupported() &&
            !XMLDocument::XMLEnabled()) {
          Debugger::ReportWarning(
              "the debug server supports Target Description XML but LLDB does "
              "not have XML parsing enabled. Using \"qRegisterInfo\" was also "
              "not possible. Register information may be incorrect or missing.",
              GetTarget().GetDebugger().GetID());
        }
        break;
      }
    } else {
      break;
    }
  }

  if (registers.empty()) {
    registers = GetFallbackRegisters(arch_to_use);
    if (!registers.empty())
      LLDB_LOG(
          log,
          "All other methods failed, using fallback register information.");
  }

  AddRemoteRegisters(registers, arch_to_use);
}

Status ProcessGDBRemote::DoWillLaunch(lldb_private::Module *module) {
  return WillLaunchOrAttach();
}

Status ProcessGDBRemote::DoWillAttachToProcessWithID(lldb::pid_t pid) {
  return WillLaunchOrAttach();
}

Status ProcessGDBRemote::DoWillAttachToProcessWithName(const char *process_name,
                                                       bool wait_for_launch) {
  return WillLaunchOrAttach();
}

Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) {
  Log *log = GetLog(GDBRLog::Process);

  Status error(WillLaunchOrAttach());
  if (error.Fail())
    return error;

  error = ConnectToDebugserver(remote_url);
  if (error.Fail())
    return error;

  StartAsyncThread();

  lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
  if (pid == LLDB_INVALID_PROCESS_ID) {
    // We don't have a valid process ID, so note that we are connected and
    // could now request to launch or attach, or get remote process listings...
    SetPrivateState(eStateConnected);
  } else {
    // We have a valid process
    SetID(pid);
    GetThreadList();
    StringExtractorGDBRemote response;
    if (m_gdb_comm.GetStopReply(response)) {
      SetLastStopPacket(response);

      Target &target = GetTarget();
      if (!target.GetArchitecture().IsValid()) {
        if (m_gdb_comm.GetProcessArchitecture().IsValid()) {
          target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
        } else {
          if (m_gdb_comm.GetHostArchitecture().IsValid()) {
            target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
          }
        }
      }

      const StateType state = SetThreadStopInfo(response);
      if (state != eStateInvalid) {
        SetPrivateState(state);
      } else
        error = Status::FromErrorStringWithFormat(
            "Process %" PRIu64 " was reported after connecting to "
            "'%s', but state was not stopped: %s",
            pid, remote_url.str().c_str(), StateAsCString(state));
    } else
      error = Status::FromErrorStringWithFormat(
          "Process %" PRIu64 " was reported after connecting to '%s', "
          "but no stop reply packet was received",
          pid, remote_url.str().c_str());
  }

  LLDB_LOGF(log,
            "ProcessGDBRemote::%s pid %" PRIu64
            ": normalizing target architecture initial triple: %s "
            "(GetTarget().GetArchitecture().IsValid() %s, "
            "m_gdb_comm.GetHostArchitecture().IsValid(): %s)",
            __FUNCTION__, GetID(),
            GetTarget().GetArchitecture().GetTriple().getTriple().c_str(),
            GetTarget().GetArchitecture().IsValid() ? "true" : "false",
            m_gdb_comm.GetHostArchitecture().IsValid() ? "true" : "false");

  if (error.Success() && !GetTarget().GetArchitecture().IsValid() &&
      m_gdb_comm.GetHostArchitecture().IsValid()) {
    // Prefer the *process'* architecture over that of the *host*, if
    // available.
    if (m_gdb_comm.GetProcessArchitecture().IsValid())
      GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture());
    else
      GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture());
  }

  LLDB_LOGF(log,
            "ProcessGDBRemote::%s pid %" PRIu64
            ": normalized target architecture triple: %s",
            __FUNCTION__, GetID(),
            GetTarget().GetArchitecture().GetTriple().getTriple().c_str());

  return error;
}

Status ProcessGDBRemote::WillLaunchOrAttach() {
  Status error;
  m_stdio_communication.Clear();
  return error;
}

// Process Control
Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module,
                                  ProcessLaunchInfo &launch_info) {
  Log *log = GetLog(GDBRLog::Process);
  Status error;

  LLDB_LOGF(log, "ProcessGDBRemote::%s() entered", __FUNCTION__);

  uint32_t launch_flags = launch_info.GetFlags().Get();
  FileSpec stdin_file_spec{};
  FileSpec stdout_file_spec{};
  FileSpec stderr_file_spec{};
  FileSpec working_dir = launch_info.GetWorkingDirectory();

  const FileAction *file_action;
  file_action = launch_info.GetFileActionForFD(STDIN_FILENO);
  if (file_action) {
    if (file_action->GetAction() == FileAction::eFileActionOpen)
      stdin_file_spec = file_action->GetFileSpec();
  }
  file_action = launch_info.GetFileActionForFD(STDOUT_FILENO);
  if (file_action) {
    if (file_action->GetAction() == FileAction::eFileActionOpen)
      stdout_file_spec = file_action->GetFileSpec();
  }
  file_action = launch_info.GetFileActionForFD(STDERR_FILENO);
  if (file_action) {
    if (file_action->GetAction() == FileAction::eFileActionOpen)
      stderr_file_spec = file_action->GetFileSpec();
  }

  if (log) {
    if (stdin_file_spec || stdout_file_spec || stderr_file_spec)
      LLDB_LOGF(log,
                "ProcessGDBRemote::%s provided with STDIO paths via "
                "launch_info: stdin=%s, stdout=%s, stderr=%s",
                __FUNCTION__,
                stdin_file_spec ? stdin_file_spec.GetPath().c_str() : "<null>",
                stdout_file_spec ? stdout_file_spec.GetPath().c_str() : "<null>",
                stderr_file_spec ? stderr_file_spec.GetPath().c_str() : "<null>");
    else
      LLDB_LOGF(log,
                "ProcessGDBRemote::%s no STDIO paths given via launch_info",
                __FUNCTION__);
  }

  const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
  if (stdin_file_spec || disable_stdio) {
    // the inferior will be reading stdin from the specified file or stdio is
    // completely disabled
    m_stdin_forward = false;
  } else {
    m_stdin_forward = true;
  }

  //  ::LogSetBitMask (GDBR_LOG_DEFAULT);
  //  ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE |
  //  LLDB_LOG_OPTION_PREPEND_TIMESTAMP |
  //  LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
  //  ::LogSetLogFile ("/dev/stdout");

  error = EstablishConnectionIfNeeded(launch_info);
  if (error.Success()) {
    PseudoTerminal pty;
    const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;

    PlatformSP platform_sp(GetTarget().GetPlatform());
    if (disable_stdio) {
      // set to /dev/null unless redirected to a file above
      if (!stdin_file_spec)
        stdin_file_spec.SetFile(FileSystem::DEV_NULL,
                                FileSpec::Style::native);
      if (!stdout_file_spec)
        stdout_file_spec.SetFile(FileSystem::DEV_NULL,
                                 FileSpec::Style::native);
      if (!stderr_file_spec)
        stderr_file_spec.SetFile(FileSystem::DEV_NULL,
                                 FileSpec::Style::native);
    } else if (platform_sp && platform_sp->IsHost()) {
      // If the debugserver is local and we aren't disabling STDIO, lets use
      // a pseudo terminal to instead of relying on the 'O' packets for stdio
      // since 'O' packets can really slow down debugging if the inferior
      // does a lot of output.
      if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) &&
          !errorToBool(pty.OpenFirstAvailablePrimary(O_RDWR | O_NOCTTY))) {
        FileSpec secondary_name(pty.GetSecondaryName());

        if (!stdin_file_spec)
          stdin_file_spec = secondary_name;

        if (!stdout_file_spec)
          stdout_file_spec = secondary_name;

        if (!stderr_file_spec)
          stderr_file_spec = secondary_name;
      }
      LLDB_LOGF(
          log,
          "ProcessGDBRemote::%s adjusted STDIO paths for local platform "
          "(IsHost() is true) using secondary: stdin=%s, stdout=%s, "
          "stderr=%s",
          __FUNCTION__,
          stdin_file_spec ? stdin_file_spec.GetPath().c_str() : "<null>",
          stdout_file_spec ? stdout_file_spec.GetPath().c_str() : "<null>",
          stderr_file_spec ? stderr_file_spec.GetPath().c_str() : "<null>");
    }

    LLDB_LOGF(log,
              "ProcessGDBRemote::%s final STDIO paths after all "
              "adjustments: stdin=%s, stdout=%s, stderr=%s",
              __FUNCTION__,
              stdin_file_spec ? stdin_file_spec.GetPath().c_str() : "<null>",
              stdout_file_spec ? stdout_file_spec.GetPath().c_str() : "<null>",
              stderr_file_spec ? stderr_file_spec.GetPath().c_str() : "<null>");

    if (stdin_file_spec)
      m_gdb_comm.SetSTDIN(stdin_file_spec);
    if (stdout_file_spec)
      m_gdb_comm.SetSTDOUT(stdout_file_spec);
    if (stderr_file_spec)
      m_gdb_comm.SetSTDERR(stderr_file_spec);

    m_gdb_comm.SetDisableASLR(launch_flags & eLaunchFlagDisableASLR);
    m_gdb_comm.SetDetachOnError(launch_flags & eLaunchFlagDetachOnError);

    m_gdb_comm.SendLaunchArchPacket(
        GetTarget().GetArchitecture().GetArchitectureName());

    const char *launch_event_data = launch_info.GetLaunchEventData();
    if (launch_event_data != nullptr && *launch_event_data != '\0')
      m_gdb_comm.SendLaunchEventDataPacket(launch_event_data);

    if (working_dir) {
      m_gdb_comm.SetWorkingDir(working_dir);
    }

    // Send the environment and the program + arguments after we connect
    m_gdb_comm.SendEnvironment(launch_info.GetEnvironment());

    {
      // Scope for the scoped timeout object
      GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm,
                                                    std::chrono::seconds(10));

      // Since we can't send argv0 separate from the executable path, we need to
      // make sure to use the actual executable path found in the launch_info...
      Args args = launch_info.GetArguments();
      if (FileSpec exe_file = launch_info.GetExecutableFile())
        args.ReplaceArgumentAtIndex(0, exe_file.GetPath(false));
      if (llvm::Error err = m_gdb_comm.LaunchProcess(args)) {
        error = Status::FromErrorStringWithFormatv(
            "Cannot launch '{0}': {1}", args.GetArgumentAtIndex(0),
            llvm::fmt_consume(std::move(err)));
      } else {
        SetID(m_gdb_comm.GetCurrentProcessID());
      }
    }

    if (GetID() == LLDB_INVALID_PROCESS_ID) {
      LLDB_LOGF(log, "failed to connect to debugserver: %s",
                error.AsCString());
      KillDebugserverProcess();
      return error;
    }

    StringExtractorGDBRemote response;
    if (m_gdb_comm.GetStopReply(response)) {
      SetLastStopPacket(response);

      const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture();

      if (process_arch.IsValid()) {
        GetTarget().MergeArchitecture(process_arch);
      } else {
        const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();
        if (host_arch.IsValid())
          GetTarget().MergeArchitecture(host_arch);
      }

      SetPrivateState(SetThreadStopInfo(response));

      if (!disable_stdio) {
        if (pty.GetPrimaryFileDescriptor() != PseudoTerminal::invalid_fd)
          SetSTDIOFileDescriptor(pty.ReleasePrimaryFileDescriptor());
      }
    }
  } else {
    LLDB_LOGF(log, "failed to connect to debugserver: %s", error.AsCString());
  }
  return error;
}

Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) {
  Status error;
  // Only connect if we have a valid connect URL
  Log *log = GetLog(GDBRLog::Process);

  if (!connect_url.empty()) {
    LLDB_LOGF(log, "ProcessGDBRemote::%s Connecting to %s", __FUNCTION__,
              connect_url.str().c_str());
    std::unique_ptr<ConnectionFileDescriptor> conn_up(
        new ConnectionFileDescriptor());
    if (conn_up) {
      const uint32_t max_retry_count = 50;
      uint32_t retry_count = 0;
      while (!m_gdb_comm.IsConnected()) {
        if (conn_up->Connect(connect_url, &error) == eConnectionStatusSuccess) {
          m_gdb_comm.SetConnection(std::move(conn_up));
          break;
        }

        retry_count++;

        if (retry_count >= max_retry_count)
          break;

        std::this_thread::sleep_for(std::chrono::milliseconds(100));
      }
    }
  }

  if (!m_gdb_comm.IsConnected()) {
    if (error.Success())
      error = Status::FromErrorString("not connected to remote gdb server");
    return error;
  }

  // We always seem to be able to open a connection to a local port so we need
  // to make sure we can then send data to it. If we can't then we aren't
  // actually connected to anything, so try and do the handshake with the
  // remote GDB server and make sure that goes alright.
  if (!m_gdb_comm.HandshakeWithServer(&error)) {
    m_gdb_comm.Disconnect();
    if (error.Success())
      error = Status::FromErrorString("not connected to remote gdb server");
    return error;
  }

  m_gdb_comm.GetEchoSupported();
  m_gdb_comm.GetThreadSuffixSupported();
  m_gdb_comm.GetListThreadsInStopReplySupported();
  m_gdb_comm.GetHostInfo();
  m_gdb_comm.GetVContSupported("c");
  m_gdb_comm.GetVAttachOrWaitSupported();
  m_gdb_comm.EnableErrorStringInPacket();

  // First dispatch any commands from the platform:
  auto handle_cmds = [&] (const Args &args) ->  void {
    for (const Args::ArgEntry &entry : args) {
      StringExtractorGDBRemote response;
      m_gdb_comm.SendPacketAndWaitForResponse(
          entry.c_str(), response);
    }
  };

  PlatformSP platform_sp = GetTarget().GetPlatform();
  if (platform_sp) {
    handle_cmds(platform_sp->GetExtraStartupCommands());
  }

  // Then dispatch any process commands:
  handle_cmds(GetExtraStartupCommands());

  return error;
}

void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
  Log *log = GetLog(GDBRLog::Process);
  BuildDynamicRegisterInfo(false);

  // See if the GDB server supports qHostInfo or qProcessInfo packets. Prefer
  // qProcessInfo as it will be more specific to our process.

  const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
  if (remote_process_arch.IsValid()) {
    process_arch = remote_process_arch;
    LLDB_LOG(log, "gdb-remote had process architecture, using {0} {1}",
             process_arch.GetArchitectureName(),
             process_arch.GetTriple().getTriple());
  } else {
    process_arch = m_gdb_comm.GetHostArchitecture();
    LLDB_LOG(log,
             "gdb-remote did not have process architecture, using gdb-remote "
             "host architecture {0} {1}",
             process_arch.GetArchitectureName(),
             process_arch.GetTriple().getTriple());
  }

  AddressableBits addressable_bits = m_gdb_comm.GetAddressableBits();
  SetAddressableBitMasks(addressable_bits);

  if (process_arch.IsValid()) {
    const ArchSpec &target_arch = GetTarget().GetArchitecture();
    if (target_arch.IsValid()) {
      LLDB_LOG(log, "analyzing target arch, currently {0} {1}",
               target_arch.GetArchitectureName(),
               target_arch.GetTriple().getTriple());

      // If the remote host is ARM and we have apple as the vendor, then
      // ARM executables and shared libraries can have mixed ARM
      // architectures.
      // You can have an armv6 executable, and if the host is armv7, then the
      // system will load the best possible architecture for all shared
      // libraries it has, so we really need to take the remote host
      // architecture as our defacto architecture in this case.

      if ((process_arch.GetMachine() == llvm::Triple::arm ||
           process_arch.GetMachine() == llvm::Triple::thumb) &&
          process_arch.GetTriple().getVendor() == llvm::Triple::Apple) {
        GetTarget().SetArchitecture(process_arch);
        LLDB_LOG(log,
                 "remote process is ARM/Apple, "
                 "setting target arch to {0} {1}",
                 process_arch.GetArchitectureName(),
                 process_arch.GetTriple().getTriple());
      } else {
        // Fill in what is missing in the triple
        const llvm::Triple &remote_triple = process_arch.GetTriple();
        llvm::Triple new_target_triple = target_arch.GetTriple();
        if (new_target_triple.getVendorName().size() == 0) {
          new_target_triple.setVendor(remote_triple.getVendor());

          if (new_target_triple.getOSName().size() == 0) {
            new_target_triple.setOS(remote_triple.getOS());

            if (new_target_triple.getEnvironmentName().size() == 0)
              new_target_triple.setEnvironment(remote_triple.getEnvironment());
          }

          ArchSpec new_target_arch = target_arch;
          new_target_arch.SetTriple(new_target_triple);
          GetTarget().SetArchitecture(new_target_arch);
        }
      }

      LLDB_LOG(log,
               "final target arch after adjustments for remote architecture: "
               "{0} {1}",
               target_arch.GetArchitectureName(),
               target_arch.GetTriple().getTriple());
    } else {
      // The target doesn't have a valid architecture yet, set it from the
      // architecture we got from the remote GDB server
      GetTarget().SetArchitecture(process_arch);
    }
  }

  // Target and Process are reasonably initailized;
  // load any binaries we have metadata for / set load address.
  LoadStubBinaries();
  MaybeLoadExecutableModule();

  // Find out which StructuredDataPlugins are supported by the debug monitor.
  // These plugins transmit data over async $J packets.
  if (StructuredData::Array *supported_packets =
          m_gdb_comm.GetSupportedStructuredDataPlugins())
    MapSupportedStructuredDataPlugins(*supported_packets);

  // If connected to LLDB ("native-signals+"), use signal defs for
  // the remote platform.  If connected to GDB, just use the standard set.
  if (!m_gdb_comm.UsesNativeSignals()) {
    SetUnixSignals(std::make_shared<GDBRemoteSignals>());
  } else {
    PlatformSP platform_sp = GetTarget().GetPlatform();
    if (platform_sp && platform_sp->IsConnected())
      SetUnixSignals(platform_sp->GetUnixSignals());
    else
      SetUnixSignals(UnixSignals::Create(GetTarget().GetArchitecture()));
  }
}

void ProcessGDBRemote::LoadStubBinaries() {
  // The remote stub may know about the "main binary" in
  // the context of a firmware debug session, and can
  // give us a UUID and an address/slide of where the
  // binary is loaded in memory.
  UUID standalone_uuid;
  addr_t standalone_value;
  bool standalone_value_is_offset;
  if (m_gdb_comm.GetProcessStandaloneBinary(standalone_uuid, standalone_value,
                                            standalone_value_is_offset)) {
    ModuleSP module_sp;

    if (standalone_uuid.IsValid()) {
      const bool force_symbol_search = true;
      const bool notify = true;
      const bool set_address_in_target = true;
      const bool allow_memory_image_last_resort = false;
      DynamicLoader::LoadBinaryWithUUIDAndAddress(
          this, "", standalone_uuid, standalone_value,
          standalone_value_is_offset, force_symbol_search, notify,
          set_address_in_target, allow_memory_image_last_resort);
    }
  }

  // The remote stub may know about a list of binaries to
  // force load into the process -- a firmware type situation
  // where multiple binaries are present in virtual memory,
  // and we are only given the addresses of the binaries.
  // Not intended for use with userland debugging, when we use
  // a DynamicLoader plugin that knows how to find the loaded
  // binaries, and will track updates as binaries are added.

  std::vector<addr_t> bin_addrs = m_gdb_comm.GetProcessStandaloneBinaries();
  if (bin_addrs.size()) {
    UUID uuid;
    const bool value_is_slide = false;
    for (addr_t addr : bin_addrs) {
      const bool notify = true;
      // First see if this is a special platform
      // binary that may determine the DynamicLoader and
      // Platform to be used in this Process and Target.
      if (GetTarget()
              .GetDebugger()
              .GetPlatformList()
              .LoadPlatformBinaryAndSetup(this, addr, notify))
        continue;

      const bool force_symbol_search = true;
      const bool set_address_in_target = true;
      const bool allow_memory_image_last_resort = false;
      // Second manually load this binary into the Target.
      DynamicLoader::LoadBinaryWithUUIDAndAddress(
          this, llvm::StringRef(), uuid, addr, value_is_slide,
          force_symbol_search, notify, set_address_in_target,
          allow_memory_image_last_resort);
    }
  }
}

void ProcessGDBRemote::MaybeLoadExecutableModule() {
  ModuleSP module_sp = GetTarget().GetExecutableModule();
  if (!module_sp)
    return;

  std::optional<QOffsets> offsets = m_gdb_comm.GetQOffsets();
  if (!offsets)
    return;

  bool is_uniform =
      size_t(llvm::count(offsets->offsets, offsets->offsets[0])) ==
      offsets->offsets.size();
  if (!is_uniform)
    return; // TODO: Handle non-uniform responses.

  bool changed = false;
  module_sp->SetLoadAddress(GetTarget(), offsets->offsets[0],
                            /*value_is_offset=*/true, changed);
  if (changed) {
    ModuleList list;
    list.Append(module_sp);
    m_process->GetTarget().ModulesDidLoad(list);
  }
}

void ProcessGDBRemote::DidLaunch() {
  ArchSpec process_arch;
  DidLaunchOrAttach(process_arch);
}

Status ProcessGDBRemote::DoAttachToProcessWithID(
    lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) {
  Log *log = GetLog(GDBRLog::Process);
  Status error;

  LLDB_LOGF(log, "ProcessGDBRemote::%s()", __FUNCTION__);

  // Clear out and clean up from any current state
  Clear();
  if (attach_pid != LLDB_INVALID_PROCESS_ID) {
    error = EstablishConnectionIfNeeded(attach_info);
    if (error.Success()) {
      m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());

      char packet[64];
      const int packet_len =
          ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid);
      SetID(attach_pid);
      auto data_sp =
          std::make_shared<EventDataBytes>(llvm::StringRef(packet, packet_len));
      m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue, data_sp);
    } else
      SetExitStatus(-1, error.AsCString());
  }

  return error;
}

Status ProcessGDBRemote::DoAttachToProcessWithName(
    const char *process_name, const ProcessAttachInfo &attach_info) {
  Status error;
  // Clear out and clean up from any current state
  Clear();

  if (process_name && process_name[0]) {
    error = EstablishConnectionIfNeeded(attach_info);
    if (error.Success()) {
      StreamString packet;

      m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());

      if (attach_info.GetWaitForLaunch()) {
        if (!m_gdb_comm.GetVAttachOrWaitSupported()) {
          packet.PutCString("vAttachWait");
        } else {
          if (attach_info.GetIgnoreExisting())
            packet.PutCString("vAttachWait");
          else
            packet.PutCString("vAttachOrWait");
        }
      } else
        packet.PutCString("vAttachName");
      packet.PutChar(';');
      packet.PutBytesAsRawHex8(process_name, strlen(process_name),
                               endian::InlHostByteOrder(),
                               endian::InlHostByteOrder());

      auto data_sp = std::make_shared<EventDataBytes>(packet.GetString());
      m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue, data_sp);

    } else
      SetExitStatus(-1, error.AsCString());
  }
  return error;
}

llvm::Expected<TraceSupportedResponse> ProcessGDBRemote::TraceSupported() {
  return m_gdb_comm.SendTraceSupported(GetInterruptTimeout());
}

llvm::Error ProcessGDBRemote::TraceStop(const TraceStopRequest &request) {
  return m_gdb_comm.SendTraceStop(request, GetInterruptTimeout());
}

llvm::Error ProcessGDBRemote::TraceStart(const llvm::json::Value &request) {
  return m_gdb_comm.SendTraceStart(request, GetInterruptTimeout());
}

llvm::Expected<std::string>
ProcessGDBRemote::TraceGetState(llvm::StringRef type) {
  return m_gdb_comm.SendTraceGetState(type, GetInterruptTimeout());
}

llvm::Expected<std::vector<uint8_t>>
ProcessGDBRemote::TraceGetBinaryData(const TraceGetBinaryDataRequest &request) {
  return m_gdb_comm.SendTraceGetBinaryData(request, GetInterruptTimeout());
}

void ProcessGDBRemote::DidExit() {
  // When we exit, disconnect from the GDB server communications
  m_gdb_comm.Disconnect();
}

void ProcessGDBRemote::DidAttach(ArchSpec &process_arch) {
  // If you can figure out what the architecture is, fill it in here.
  process_arch.Clear();
  DidLaunchOrAttach(process_arch);
}

Status ProcessGDBRemote::WillResume() {
  m_continue_c_tids.clear();
  m_continue_C_tids.clear();
  m_continue_s_tids.clear();
  m_continue_S_tids.clear();
  m_jstopinfo_sp.reset();
  m_jthreadsinfo_sp.reset();
  m_shared_cache_info_sp.reset();
  return Status();
}

bool ProcessGDBRemote::SupportsReverseDirection() {
  return m_gdb_comm.GetReverseStepSupported() ||
         m_gdb_comm.GetReverseContinueSupported();
}

Status ProcessGDBRemote::DoResume(RunDirection direction) {
  Status error;
  Log *log = GetLog(GDBRLog::Process);
  LLDB_LOGF(log, "ProcessGDBRemote::Resume(%s)",
            direction == RunDirection::eRunForward ? "" : "reverse");

  ListenerSP listener_sp(
      Listener::MakeListener("gdb-remote.resume-packet-sent"));
  if (listener_sp->StartListeningForEvents(
          &m_gdb_comm, GDBRemoteClientBase::eBroadcastBitRunPacketSent)) {
    listener_sp->StartListeningForEvents(
        &m_async_broadcaster,
        ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit);

    const size_t num_threads = GetThreadList().GetSize();

    StreamString continue_packet;
    bool continue_packet_error = false;
    // Number of threads continuing with "c", i.e. continuing without a signal
    // to deliver.
    const size_t num_continue_c_tids = m_continue_c_tids.size();
    // Number of threads continuing with "C", i.e. continuing with a signal to
    // deliver.
    const size_t num_continue_C_tids = m_continue_C_tids.size();
    // Number of threads continuing with "s", i.e. single-stepping.
    const size_t num_continue_s_tids = m_continue_s_tids.size();
    // Number of threads continuing with "S", i.e. single-stepping with a signal
    // to deliver.
    const size_t num_continue_S_tids = m_continue_S_tids.size();
    if (direction == RunDirection::eRunForward &&
        m_gdb_comm.HasAnyVContSupport()) {
      std::string pid_prefix;
      if (m_gdb_comm.GetMultiprocessSupported())
        pid_prefix = llvm::formatv("p{0:x-}.", GetID());

      if (num_continue_c_tids == num_threads ||
          (m_continue_c_tids.empty() && m_continue_C_tids.empty() &&
           m_continue_s_tids.empty() && m_continue_S_tids.empty())) {
        // All threads are continuing
        if (m_gdb_comm.GetMultiprocessSupported())
          continue_packet.Format("vCont;c:{0}-1", pid_prefix);
        else
          continue_packet.PutCString("c");
      } else {
        continue_packet.PutCString("vCont");

        if (!m_continue_c_tids.empty()) {
          if (m_gdb_comm.GetVContSupported("c")) {
            for (tid_collection::const_iterator
                     t_pos = m_continue_c_tids.begin(),
                     t_end = m_continue_c_tids.end();
                 t_pos != t_end; ++t_pos)
              continue_packet.Format(";c:{0}{1:x-}", pid_prefix, *t_pos);
          } else
            continue_packet_error = true;
        }

        if (!continue_packet_error && !m_continue_C_tids.empty()) {
          if (m_gdb_comm.GetVContSupported("C")) {
            for (tid_sig_collection::const_iterator
                     s_pos = m_continue_C_tids.begin(),
                     s_end = m_continue_C_tids.end();
                 s_pos != s_end; ++s_pos)
              continue_packet.Format(";C{0:x-2}:{1}{2:x-}", s_pos->second,
                                     pid_prefix, s_pos->first);
          } else
            continue_packet_error = true;
        }

        if (!continue_packet_error && !m_continue_s_tids.empty()) {
          if (m_gdb_comm.GetVContSupported("s")) {
            for (tid_collection::const_iterator
                     t_pos = m_continue_s_tids.begin(),
                     t_end = m_continue_s_tids.end();
                 t_pos != t_end; ++t_pos)
              continue_packet.Format(";s:{0}{1:x-}", pid_prefix, *t_pos);
          } else
            continue_packet_error = true;
        }

        if (!continue_packet_error && !m_continue_S_tids.empty()) {
          if (m_gdb_comm.GetVContSupported("S")) {
            for (tid_sig_collection::const_iterator
                     s_pos = m_continue_S_tids.begin(),
                     s_end = m_continue_S_tids.end();
                 s_pos != s_end; ++s_pos)
              continue_packet.Format(";S{0:x-2}:{1}{2:x-}", s_pos->second,
                                     pid_prefix, s_pos->first);
          } else
            continue_packet_error = true;
        }

        if (continue_packet_error)
          continue_packet.Clear();
      }
    } else
      continue_packet_error = true;

    if (direction == RunDirection::eRunForward && continue_packet_error) {
      // Either no vCont support, or we tried to use part of the vCont packet
      // that wasn't supported by the remote GDB server. We need to try and
      // make a simple packet that can do our continue.
      if (num_continue_c_tids > 0) {
        if (num_continue_c_tids == num_threads) {
          // All threads are resuming...
          m_gdb_comm.SetCurrentThreadForRun(-1);
          continue_packet.PutChar('c');
          continue_packet_error = false;
        } else if (num_continue_c_tids == 1 && num_continue_C_tids == 0 &&
                   num_continue_s_tids == 0 && num_continue_S_tids == 0) {
          // Only one thread is continuing
          m_gdb_comm.SetCurrentThreadForRun(m_continue_c_tids.front());
          continue_packet.PutChar('c');
          continue_packet_error = false;
        }
      }

      if (continue_packet_error && num_continue_C_tids > 0) {
        if ((num_continue_C_tids + num_continue_c_tids) == num_threads &&
            num_continue_C_tids > 0 && num_continue_s_tids == 0 &&
            num_continue_S_tids == 0) {
          const int continue_signo = m_continue_C_tids.front().second;
          // Only one thread is continuing
          if (num_continue_C_tids > 1) {
            // More that one thread with a signal, yet we don't have vCont
            // support and we are being asked to resume each thread with a
            // signal, we need to make sure they are all the same signal, or we
            // can't issue the continue accurately with the current support...
            if (num_continue_C_tids > 1) {
              continue_packet_error = false;
              for (size_t i = 1; i < m_continue_C_tids.size(); ++i) {
                if (m_continue_C_tids[i].second != continue_signo)
                  continue_packet_error = true;
              }
            }
            if (!continue_packet_error)
              m_gdb_comm.SetCurrentThreadForRun(-1);
          } else {
            // Set the continue thread ID
            continue_packet_error = false;
            m_gdb_comm.SetCurrentThreadForRun(m_continue_C_tids.front().first);
          }
          if (!continue_packet_error) {
            // Add threads continuing with the same signo...
            continue_packet.Printf("C%2.2x", continue_signo);
          }
        }
      }

      if (continue_packet_error && num_continue_s_tids > 0) {
        if (num_continue_s_tids == num_threads) {
          // All threads are resuming...
          m_gdb_comm.SetCurrentThreadForRun(-1);

          continue_packet.PutChar('s');

          continue_packet_error = false;
        } else if (num_continue_c_tids == 0 && num_continue_C_tids == 0 &&
                   num_continue_s_tids == 1 && num_continue_S_tids == 0) {
          // Only one thread is stepping
          m_gdb_comm.SetCurrentThreadForRun(m_continue_s_tids.front());
          continue_packet.PutChar('s');
          continue_packet_error = false;
        }
      }

      if (!continue_packet_error && num_continue_S_tids > 0) {
        if (num_continue_S_tids == num_threads) {
          const int step_signo = m_continue_S_tids.front().second;
          // Are all threads trying to step with the same signal?
          continue_packet_error = false;
          if (num_continue_S_tids > 1) {
            for (size_t i = 1; i < num_threads; ++i) {
              if (m_continue_S_tids[i].second != step_signo)
                continue_packet_error = true;
            }
          }
          if (!continue_packet_error) {
            // Add threads stepping with the same signo...
            m_gdb_comm.SetCurrentThreadForRun(-1);
            continue_packet.Printf("S%2.2x", step_signo);
          }
        } else if (num_continue_c_tids == 0 && num_continue_C_tids == 0 &&
                   num_continue_s_tids == 0 && num_continue_S_tids == 1) {
          // Only one thread is stepping with signal
          m_gdb_comm.SetCurrentThreadForRun(m_continue_S_tids.front().first);
          continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second);
          continue_packet_error = false;
        }
      }
    }

    if (direction == RunDirection::eRunReverse) {
      if (num_continue_s_tids > 0 || num_continue_S_tids > 0) {
        if (!m_gdb_comm.GetReverseStepSupported()) {
          LLDB_LOGF(log, "ProcessGDBRemote::DoResume: target does not "
                         "support reverse-stepping");
          return Status::FromErrorString(
              "target does not support reverse-stepping");
        }

        if (num_continue_S_tids > 0) {
          LLDB_LOGF(
              log,
              "ProcessGDBRemote::DoResume: Signals not supported in reverse");
          return Status::FromErrorString(
              "can't deliver signals while running in reverse");
        }

        if (num_continue_s_tids > 1) {
          LLDB_LOGF(log, "ProcessGDBRemote::DoResume: can't step multiple "
                         "threads in reverse");
          return Status::FromErrorString(
              "can't step multiple threads while reverse-stepping");
        }

        m_gdb_comm.SetCurrentThreadForRun(m_continue_s_tids.front());
        continue_packet.PutCString("bs");
      } else {
        if (!m_gdb_comm.GetReverseContinueSupported()) {
          LLDB_LOGF(log, "ProcessGDBRemote::DoResume: target does not "
                         "support reverse-continue");
          return Status::FromErrorString(
              "target does not support reverse execution of processes");
        }

        if (num_continue_C_tids > 0) {
          LLDB_LOGF(
              log,
              "ProcessGDBRemote::DoResume: Signals not supported in reverse");
          return Status::FromErrorString(
              "can't deliver signals while running in reverse");
        }

        // All threads continue whether requested or not ---
        // we can't change how threads ran in the past.
        continue_packet.PutCString("bc");
      }

      continue_packet_error = false;
    }

    if (continue_packet_error) {
      return Status::FromErrorString(
          "can't make continue packet for this resume");
    } else {
      EventSP event_sp;
      if (!m_async_thread.IsJoinable()) {
        error = Status::FromErrorString(
            "Trying to resume but the async thread is dead.");
        LLDB_LOGF(log, "ProcessGDBRemote::DoResume: Trying to resume but the "
                       "async thread is dead.");
        return error;
      }

      auto data_sp =
          std::make_shared<EventDataBytes>(continue_packet.GetString());
      m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue, data_sp);

      if (!listener_sp->GetEvent(event_sp, ResumeTimeout())) {
        error = Status::FromErrorString("Resume timed out.");
        LLDB_LOGF(log, "ProcessGDBRemote::DoResume: Resume timed out.");
      } else if (event_sp->BroadcasterIs(&m_async_broadcaster)) {
        error = Status::FromErrorString(
            "Broadcast continue, but the async thread was "
            "killed before we got an ack back.");
        LLDB_LOGF(log,
                  "ProcessGDBRemote::DoResume: Broadcast continue, but the "
                  "async thread was killed before we got an ack back.");
        return error;
      }
    }
  }

  return error;
}

void ProcessGDBRemote::ClearThreadIDList() {
  std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
  m_thread_ids.clear();
  m_thread_pcs.clear();
}

size_t ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(
    llvm::StringRef value) {
  m_thread_ids.clear();
  lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
  StringExtractorGDBRemote thread_ids{value};

  do {
    auto pid_tid = thread_ids.GetPidTid(pid);
    if (pid_tid && pid_tid->first == pid) {
      lldb::tid_t tid = pid_tid->second;
      if (tid != LLDB_INVALID_THREAD_ID &&
          tid != StringExtractorGDBRemote::AllProcesses)
        m_thread_ids.push_back(tid);
    }
  } while (thread_ids.GetChar() == ',');

  return m_thread_ids.size();
}

size_t ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue(
    llvm::StringRef value) {
  m_thread_pcs.clear();
  for (llvm::StringRef x : llvm::split(value, ',')) {
    lldb::addr_t pc;
    if (llvm::to_integer(x, pc, 16))
      m_thread_pcs.push_back(pc);
  }
  return m_thread_pcs.size();
}

bool ProcessGDBRemote::UpdateThreadIDList() {
  std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());

  if (m_jthreadsinfo_sp) {
    // If we have the JSON threads info, we can get the thread list from that
    StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
    if (thread_infos && thread_infos->GetSize() > 0) {
      m_thread_ids.clear();
      m_thread_pcs.clear();
      thread_infos->ForEach([this](StructuredData::Object *object) -> bool {
        StructuredData::Dictionary *thread_dict = object->GetAsDictionary();
        if (thread_dict) {
          // Set the thread stop info from the JSON dictionary
          SetThreadStopInfo(thread_dict);
          lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
          if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid))
            m_thread_ids.push_back(tid);
        }
        return true; // Keep iterating through all thread_info objects
      });
    }
    if (!m_thread_ids.empty())
      return true;
  } else {
    // See if we can get the thread IDs from the current stop reply packets
    // that might contain a "threads" key/value pair

    if (m_last_stop_packet) {
      // Get the thread stop info
      StringExtractorGDBRemote &stop_info = *m_last_stop_packet;
      const llvm::StringRef stop_info_str = stop_info.GetStringRef();

      m_thread_pcs.clear();
      const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:");
      if (thread_pcs_pos != llvm::StringRef::npos) {
        const size_t start = thread_pcs_pos + strlen(";thread-pcs:");
        const size_t end = stop_info_str.find(';', start);
        if (end != llvm::StringRef::npos) {
          llvm::StringRef value = stop_info_str.substr(start, end - start);
          UpdateThreadPCsFromStopReplyThreadsValue(value);
        }
      }

      const size_t threads_pos = stop_info_str.find(";threads:");
      if (threads_pos != llvm::StringRef::npos) {
        const size_t start = threads_pos + strlen(";threads:");
        const size_t end = stop_info_str.find(';', start);
        if (end != llvm::StringRef::npos) {
          llvm::StringRef value = stop_info_str.substr(start, end - start);
          if (UpdateThreadIDsFromStopReplyThreadsValue(value))
            return true;
        }
      }
    }
  }

  bool sequence_mutex_unavailable = false;
  m_gdb_comm.GetCurrentThreadIDs(m_thread_ids, sequence_mutex_unavailable);
  if (sequence_mutex_unavailable) {
    return false; // We just didn't get the list
  }
  return true;
}

bool ProcessGDBRemote::DoUpdateThreadList(ThreadList &old_thread_list,
                                          ThreadList &new_thread_list) {
  // locker will keep a mutex locked until it goes out of scope
  Log *log = GetLog(GDBRLog::Thread);
  LLDB_LOGV(log, "pid = {0}", GetID());

  size_t num_thread_ids = m_thread_ids.size();
  // The "m_thread_ids" thread ID list should always be updated after each stop
  // reply packet, but in case it isn't, update it here.
  if (num_thread_ids == 0) {
    if (!UpdateThreadIDList())
      return false;
    num_thread_ids = m_thread_ids.size();
  }

  ThreadList old_thread_list_copy(old_thread_list);
  if (num_thread_ids > 0) {
    for (size_t i = 0; i < num_thread_ids; ++i) {
      lldb::tid_t tid = m_thread_ids[i];
      ThreadSP thread_sp(
          old_thread_list_copy.RemoveThreadByProtocolID(tid, false));
      if (!thread_sp) {
        thread_sp = CreateThread(tid);
        LLDB_LOGV(log, "Making new thread: {0} for thread ID: {1:x}.",
                  thread_sp.get(), thread_sp->GetID());
      } else {
        LLDB_LOGV(log, "Found old thread: {0} for thread ID: {1:x}.",
                  thread_sp.get(), thread_sp->GetID());
      }

      SetThreadPc(thread_sp, i);
      new_thread_list.AddThreadSortedByIndexID(thread_sp);
    }
  }

  // Whatever that is left in old_thread_list_copy are not present in
  // new_thread_list. Remove non-existent threads from internal id table.
  size_t old_num_thread_ids = old_thread_list_copy.GetSize(false);
  for (size_t i = 0; i < old_num_thread_ids; i++) {
    ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false));
    if (old_thread_sp) {
      lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID();
      m_thread_id_to_index_id_map.erase(old_thread_id);
    }
  }

  return true;
}

void ProcessGDBRemote::SetThreadPc(const ThreadSP &thread_sp, uint64_t index) {
  if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() &&
      GetByteOrder() != eByteOrderInvalid) {
    ThreadGDBRemote *gdb_thread =
        static_cast<ThreadGDBRemote *>(thread_sp.get());
    RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
    if (reg_ctx_sp) {
      uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
          eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
      if (pc_regnum != LLDB_INVALID_REGNUM) {
        gdb_thread->PrivateSetRegisterValue(pc_regnum, m_thread_pcs[index]);
      }
    }
  }
}

bool ProcessGDBRemote::GetThreadStopInfoFromJSON(
    ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp) {
  // See if we got thread stop infos for all threads via the "jThreadsInfo"
  // packet
  if (thread_infos_sp) {
    StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray();
    if (thread_infos) {
      lldb::tid_t tid;
      const size_t n = thread_infos->GetSize();
      for (size_t i = 0; i < n; ++i) {
        StructuredData::Dictionary *thread_dict =
            thread_infos->GetItemAtIndex(i)->GetAsDictionary();
        if (thread_dict) {
          if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>(
                  "tid", tid, LLDB_INVALID_THREAD_ID)) {
            if (tid == thread->GetID())
              return (bool)SetThreadStopInfo(thread_dict);
          }
        }
      }
    }
  }
  return false;
}

bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) {
  // See if we got thread stop infos for all threads via the "jThreadsInfo"
  // packet
  if (GetThreadStopInfoFromJSON(thread, m_jthreadsinfo_sp))
    return true;

  // See if we got thread stop info for any threads valid stop info reasons
  // threads via the "jstopinfo" packet stop reply packet key/value pair?
  if (m_jstopinfo_sp) {
    // If we have "jstopinfo" then we have stop descriptions for all threads
    // that have stop reasons, and if there is no entry for a thread, then it
    // has no stop reason.
    if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp))
      thread->SetStopInfo(StopInfoSP());
    return true;
  }

  // Fall back to using the qThreadStopInfo packet
  StringExtractorGDBRemote stop_packet;
  if (GetGDBRemote().GetThreadStopInfo(thread->GetProtocolID(), stop_packet))
    return SetThreadStopInfo(stop_packet) == eStateStopped;
  return false;
}

void ProcessGDBRemote::ParseExpeditedRegisters(
    ExpeditedRegisterMap &expedited_register_map, ThreadSP thread_sp) {
  ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *>(thread_sp.get());
  RegisterContextSP gdb_reg_ctx_sp(gdb_thread->GetRegisterContext());

  for (const auto &pair : expedited_register_map) {
    StringExtractor reg_value_extractor(pair.second);
    WritableDataBufferSP buffer_sp(
        new DataBufferHeap(reg_value_extractor.GetStringRef().size() / 2, 0));
    reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc');
    uint32_t lldb_regnum = gdb_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
        eRegisterKindProcessPlugin, pair.first);
    gdb_thread->PrivateSetRegisterValue(lldb_regnum, buffer_sp->GetData());
  }
}

ThreadSP ProcessGDBRemote::SetThreadStopInfo(
    lldb::tid_t tid, ExpeditedRegisterMap &expedited_register_map,
    uint8_t signo, const std::string &thread_name, const std::string &reason,
    const std::string &description, uint32_t exc_type,
    const std::vector<addr_t> &exc_data, addr_t thread_dispatch_qaddr,
    bool queue_vars_valid, // Set to true if queue_name, queue_kind and
                           // queue_serial are valid
    LazyBool associated_with_dispatch_queue, addr_t dispatch_queue_t,
    std::string &queue_name, QueueKind queue_kind, uint64_t queue_serial) {

  if (tid == LLDB_INVALID_THREAD_ID)
    return nullptr;

  ThreadSP thread_sp;
  // Scope for "locker" below
  {
    // m_thread_list_real does have its own mutex, but we need to hold onto the
    // mutex between the call to m_thread_list_real.FindThreadByID(...) and the
    // m_thread_list_real.AddThread(...) so it doesn't change on us
    std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
    thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false);

    if (!thread_sp) {
      // Create the thread if we need to
      thread_sp = CreateThread(tid);
      m_thread_list_real.AddThread(thread_sp);
    }
  }

  ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *>(thread_sp.get());
  RegisterContextSP reg_ctx_sp(gdb_thread->GetRegisterContext());

  reg_ctx_sp->InvalidateIfNeeded(true);

  auto iter = llvm::find(m_thread_ids, tid);
  if (iter != m_thread_ids.end())
    SetThreadPc(thread_sp, iter - m_thread_ids.begin());

  ParseExpeditedRegisters(expedited_register_map, thread_sp);

  if (reg_ctx_sp->ReconfigureRegisterInfo()) {
    // Now we have changed the offsets of all the registers, so the values
    // will be corrupted.
    reg_ctx_sp->InvalidateAllRegisters();
    // Expedited registers values will never contain registers that would be
    // resized by a reconfigure. So we are safe to continue using these
    // values.
    ParseExpeditedRegisters(expedited_register_map, thread_sp);
  }

  thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str());

  gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr);
  // Check if the GDB server was able to provide the queue name, kind and serial
  // number
  if (queue_vars_valid)
    gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial,
                             dispatch_queue_t, associated_with_dispatch_queue);
  else
    gdb_thread->ClearQueueInfo();

  gdb_thread->SetAssociatedWithLibdispatchQueue(associated_with_dispatch_queue);

  if (dispatch_queue_t != LLDB_INVALID_ADDRESS)
    gdb_thread->SetQueueLibdispatchQueueAddress(dispatch_queue_t);

  // Make sure we update our thread stop reason just once, but don't overwrite
  // the stop info for threads that haven't moved:
  StopInfoSP current_stop_info_sp = thread_sp->GetPrivateStopInfo(false);
  if (thread_sp->GetTemporaryResumeState() == eStateSuspended &&
      current_stop_info_sp) {
    thread_sp->SetStopInfo(current_stop_info_sp);
    return thread_sp;
  }

  if (!thread_sp->StopInfoIsUpToDate()) {
    thread_sp->SetStopInfo(StopInfoSP());

    addr_t pc = thread_sp->GetRegisterContext()->GetPC();
    BreakpointSiteSP bp_site_sp =
        thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
    if (bp_site_sp && bp_site_sp->IsEnabled())
      thread_sp->SetThreadStoppedAtUnexecutedBP(pc);

    if (exc_type != 0) {
      // For thread plan async interrupt, creating stop info on the
      // original async interrupt request thread instead. If interrupt thread
      // does not exist anymore we fallback to current signal receiving thread
      // instead.
      ThreadSP interrupt_thread;
      if (m_interrupt_tid != LLDB_INVALID_THREAD_ID)
        interrupt_thread = HandleThreadAsyncInterrupt(signo, description);
      if (interrupt_thread)
        thread_sp = interrupt_thread;
      else {
        const size_t exc_data_size = exc_data.size();
        thread_sp->SetStopInfo(
            StopInfoMachException::CreateStopReasonWithMachException(
                *thread_sp, exc_type, exc_data_size,
                exc_data_size >= 1 ? exc_data[0] : 0,
                exc_data_size >= 2 ? exc_data[1] : 0,
                exc_data_size >= 3 ? exc_data[2] : 0));
      }
    } else {
      bool handled = false;
      bool did_exec = false;
      // debugserver can send reason = "none" which is equivalent
      // to no reason.
      if (!reason.empty() && reason != "none") {
        if (reason == "trace") {
          thread_sp->SetStopInfo(StopInfo::CreateStopReasonToTrace(*thread_sp));
          handled = true;
        } else if (reason == "breakpoint") {
          thread_sp->SetThreadHitBreakpointSite();
          if (bp_site_sp) {
            // If the breakpoint is for this thread, then we'll report the hit,
            // but if it is for another thread, we can just report no reason.
            // We don't need to worry about stepping over the breakpoint here,
            // that will be taken care of when the thread resumes and notices
            // that there's a breakpoint under the pc.
            handled = true;
            if (bp_site_sp->ValidForThisThread(*thread_sp)) {
              thread_sp->SetStopInfo(
                  StopInfo::CreateStopReasonWithBreakpointSiteID(
                      *thread_sp, bp_site_sp->GetID()));
            } else {
              StopInfoSP invalid_stop_info_sp;
              thread_sp->SetStopInfo(invalid_stop_info_sp);
            }
          }
        } else if (reason == "trap") {
          // Let the trap just use the standard signal stop reason below...
        } else if (reason == "watchpoint") {
          // We will have between 1 and 3 fields in the description.
          //
          // \a wp_addr which is the original start address that
          // lldb requested be watched, or an address that the
          // hardware reported.  This address should be within the
          // range of a currently active watchpoint region - lldb
          // should be able to find a watchpoint with this address.
          //
          // \a wp_index is the hardware watchpoint register number.
          //
          // \a wp_hit_addr is the actual address reported by the hardware,
          // which may be outside the range of a region we are watching.
          //
          // On MIPS, we may get a false watchpoint exception where an
          // access to the same 8 byte granule as a watchpoint will trigger,
          // even if the access was not within the range of the watched
          // region. When we get a \a wp_hit_addr outside the range of any
          // set watchpoint, continue execution without making it visible to
          // the user.
          //
          // On ARM, a related issue where a large access that starts
          // before the watched region (and extends into the watched
          // region) may report a hit address before the watched region.
          // lldb will not find the "nearest" watchpoint to
          // disable/step/re-enable it, so one of the valid watchpoint
          // addresses should be provided as \a wp_addr.
          StringExtractor desc_extractor(description.c_str());
          // FIXME NativeThreadLinux::SetStoppedByWatchpoint sends this
          // up as
          //  <address within wp range> <wp hw index> <actual accessed addr>
          // but this is not reading the <wp hw index>.  Seems like it
          // wouldn't work on MIPS, where that third field is important.
          addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
          addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
          watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
          bool silently_continue = false;
          WatchpointResourceSP wp_resource_sp;
          if (wp_hit_addr != LLDB_INVALID_ADDRESS) {
            wp_resource_sp =
                m_watchpoint_resource_list.FindByAddress(wp_hit_addr);
            // On MIPS, \a wp_hit_addr outside the range of a watched
            // region means we should silently continue, it is a false hit.
            ArchSpec::Core core = GetTarget().GetArchitecture().GetCore();
            if (!wp_resource_sp && core >= ArchSpec::kCore_mips_first &&
                core <= ArchSpec::kCore_mips_last)
              silently_continue = true;
          }
          if (!wp_resource_sp && wp_addr != LLDB_INVALID_ADDRESS)
            wp_resource_sp = m_watchpoint_resource_list.FindByAddress(wp_addr);
          if (!wp_resource_sp) {
            Log *log(GetLog(GDBRLog::Watchpoints));
            LLDB_LOGF(log, "failed to find watchpoint");
            watch_id = LLDB_INVALID_SITE_ID;
          } else {
            // LWP_TODO: This is hardcoding a single Watchpoint in a
            // Resource, need to add
            // StopInfo::CreateStopReasonWithWatchpointResource which
            // represents all watchpoints that were tripped at this stop.
            watch_id = wp_resource_sp->GetConstituentAtIndex(0)->GetID();
          }
          thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID(
              *thread_sp, watch_id, silently_continue));
          handled = true;
        } else if (reason == "exception") {
          thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException(
              *thread_sp, description.c_str()));
          handled = true;
        } else if (reason == "history boundary") {
          thread_sp->SetStopInfo(StopInfo::CreateStopReasonHistoryBoundary(
              *thread_sp, description.c_str()));
          handled = true;
        } else if (reason == "exec") {
          did_exec = true;
          thread_sp->SetStopInfo(
              StopInfo::CreateStopReasonWithExec(*thread_sp));
          handled = true;
        } else if (reason == "processor trace") {
          thread_sp->SetStopInfo(StopInfo::CreateStopReasonProcessorTrace(
              *thread_sp, description.c_str()));
        } else if (reason == "fork") {
          StringExtractor desc_extractor(description.c_str());
          lldb::pid_t child_pid =
              desc_extractor.GetU64(LLDB_INVALID_PROCESS_ID);
          lldb::tid_t child_tid = desc_extractor.GetU64(LLDB_INVALID_THREAD_ID);
          thread_sp->SetStopInfo(
              StopInfo::CreateStopReasonFork(*thread_sp, child_pid, child_tid));
          handled = true;
        } else if (reason == "vfork") {
          StringExtractor desc_extractor(description.c_str());
          lldb::pid_t child_pid =
              desc_extractor.GetU64(LLDB_INVALID_PROCESS_ID);
          lldb::tid_t child_tid = desc_extractor.GetU64(LLDB_INVALID_THREAD_ID);
          thread_sp->SetStopInfo(StopInfo::CreateStopReasonVFork(
              *thread_sp, child_pid, child_tid));
          handled = true;
        } else if (reason == "vforkdone") {
          thread_sp->SetStopInfo(
              StopInfo::CreateStopReasonVForkDone(*thread_sp));
          handled = true;
        }
      }

      if (!handled && signo && !did_exec) {
        if (signo == SIGTRAP) {
          // Currently we are going to assume SIGTRAP means we are either
          // hitting a breakpoint or hardware single stepping.

          // We can't disambiguate between stepping-to-a-breakpointsite and
          // hitting-a-breakpointsite.
          //
          // A user can instruction-step, and be stopped at a BreakpointSite.
          // Or a user can be sitting at a BreakpointSite,
          // instruction-step which hits the breakpoint and the pc does not
          // advance.
          //
          // In both cases, we're at a BreakpointSite when stopped, and
          // the resume state was eStateStepping.

          // Assume if we're at a BreakpointSite, we hit it.
          handled = true;
          addr_t pc =
              thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset;
          BreakpointSiteSP bp_site_sp =
              thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(
                  pc);

          // We can't know if we hit it or not. So if we are stopped at
          // a BreakpointSite, assume we hit it, and should step past the
          // breakpoint when we resume. This is contrary to how we handle
          // BreakpointSites in any other location, but we can't know for
          // sure what happened so it's a reasonable default.
          if (bp_site_sp) {
            if (bp_site_sp->IsEnabled())
              thread_sp->SetThreadHitBreakpointSite();

            if (bp_site_sp->ValidForThisThread(*thread_sp)) {
              if (m_breakpoint_pc_offset != 0)
                thread_sp->GetRegisterContext()->SetPC(pc);
              thread_sp->SetStopInfo(
                  StopInfo::CreateStopReasonWithBreakpointSiteID(
                      *thread_sp, bp_site_sp->GetID()));
            } else {
              StopInfoSP invalid_stop_info_sp;
              thread_sp->SetStopInfo(invalid_stop_info_sp);
            }
          } else {
            // If we were stepping then assume the stop was the result of the
            // trace.  If we were not stepping then report the SIGTRAP.
            if (thread_sp->GetTemporaryResumeState() == eStateStepping)
              thread_sp->SetStopInfo(
                  StopInfo::CreateStopReasonToTrace(*thread_sp));
            else
              thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal(
                  *thread_sp, signo, description.c_str()));
          }
        }
        if (!handled) {
          // For thread plan async interrupt, creating stop info on the
          // original async interrupt request thread instead. If interrupt
          // thread does not exist anymore we fallback to current signal
          // receiving thread instead.
          ThreadSP interrupt_thread;
          if (m_interrupt_tid != LLDB_INVALID_THREAD_ID)
            interrupt_thread = HandleThreadAsyncInterrupt(signo, description);
          if (interrupt_thread)
            thread_sp = interrupt_thread;
          else
            thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal(
                *thread_sp, signo, description.c_str()));
        }
      }

      if (!description.empty()) {
        lldb::StopInfoSP stop_info_sp(thread_sp->GetStopInfo());
        if (stop_info_sp) {
          const char *stop_info_desc = stop_info_sp->GetDescription();
          if (!stop_info_desc || !stop_info_desc[0])
            stop_info_sp->SetDescription(description.c_str());
        } else {
          thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException(
              *thread_sp, description.c_str()));
        }
      }
    }
  }
  return thread_sp;
}

ThreadSP
ProcessGDBRemote::HandleThreadAsyncInterrupt(uint8_t signo,
                                             const std::string &description) {
  ThreadSP thread_sp;
  {
    std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
    thread_sp = m_thread_list_real.FindThreadByProtocolID(m_interrupt_tid,
                                                          /*can_update=*/false);
  }
  if (thread_sp)
    thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithInterrupt(
        *thread_sp, signo, description.c_str()));
  // Clear m_interrupt_tid regardless we can find original interrupt thread or
  // not.
  m_interrupt_tid = LLDB_INVALID_THREAD_ID;
  return thread_sp;
}

lldb::ThreadSP
ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) {
  static constexpr llvm::StringLiteral g_key_tid("tid");
  static constexpr llvm::StringLiteral g_key_name("name");
  static constexpr llvm::StringLiteral g_key_reason("reason");
  static constexpr llvm::StringLiteral g_key_metype("metype");
  static constexpr llvm::StringLiteral g_key_medata("medata");
  static constexpr llvm::StringLiteral g_key_qaddr("qaddr");
  static constexpr llvm::StringLiteral g_key_dispatch_queue_t(
      "dispatch_queue_t");
  static constexpr llvm::StringLiteral g_key_associated_with_dispatch_queue(
      "associated_with_dispatch_queue");
  static constexpr llvm::StringLiteral g_key_queue_name("qname");
  static constexpr llvm::StringLiteral g_key_queue_kind("qkind");
  static constexpr llvm::StringLiteral g_key_queue_serial_number("qserialnum");
  static constexpr llvm::StringLiteral g_key_registers("registers");
  static constexpr llvm::StringLiteral g_key_memory("memory");
  static constexpr llvm::StringLiteral g_key_description("description");
  static constexpr llvm::StringLiteral g_key_signal("signal");

  // Stop with signal and thread info
  lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
  uint8_t signo = 0;
  std::string thread_name;
  std::string reason;
  std::string description;
  uint32_t exc_type = 0;
  std::vector<addr_t> exc_data;
  addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
  ExpeditedRegisterMap expedited_register_map;
  bool queue_vars_valid = false;
  addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
  LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
  std::string queue_name;
  QueueKind queue_kind = eQueueKindUnknown;
  uint64_t queue_serial_number = 0;
  // Iterate through all of the thread dictionary key/value pairs from the
  // structured data dictionary

  // FIXME: we're silently ignoring invalid data here
  thread_dict->ForEach([this, &tid, &expedited_register_map, &thread_name,
                        &signo, &reason, &description, &exc_type, &exc_data,
                        &thread_dispatch_qaddr, &queue_vars_valid,
                        &associated_with_dispatch_queue, &dispatch_queue_t,
                        &queue_name, &queue_kind, &queue_serial_number](
                           llvm::StringRef key,
                           StructuredData::Object *object) -> bool {
    if (key == g_key_tid) {
      // thread in big endian hex
      tid = object->GetUnsignedIntegerValue(LLDB_INVALID_THREAD_ID);
    } else if (key == g_key_metype) {
      // exception type in big endian hex
      exc_type = object->GetUnsignedIntegerValue(0);
    } else if (key == g_key_medata) {
      // exception data in big endian hex
      StructuredData::Array *array = object->GetAsArray();
      if (array) {
        array->ForEach([&exc_data](StructuredData::Object *object) -> bool {
          exc_data.push_back(object->GetUnsignedIntegerValue());
          return true; // Keep iterating through all array items
        });
      }
    } else if (key == g_key_name) {
      thread_name = std::string(object->GetStringValue());
    } else if (key == g_key_qaddr) {
      thread_dispatch_qaddr =
          object->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS);
    } else if (key == g_key_queue_name) {
      queue_vars_valid = true;
      queue_name = std::string(object->GetStringValue());
    } else if (key == g_key_queue_kind) {
      std::string queue_kind_str = std::string(object->GetStringValue());
      if (queue_kind_str == "serial") {
        queue_vars_valid = true;
        queue_kind = eQueueKindSerial;
      } else if (queue_kind_str == "concurrent") {
        queue_vars_valid = true;
        queue_kind = eQueueKindConcurrent;
      }
    } else if (key == g_key_queue_serial_number) {
      queue_serial_number = object->GetUnsignedIntegerValue(0);
      if (queue_serial_number != 0)
        queue_vars_valid = true;
    } else if (key == g_key_dispatch_queue_t) {
      dispatch_queue_t = object->GetUnsignedIntegerValue(0);
      if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS)
        queue_vars_valid = true;
    } else if (key == g_key_associated_with_dispatch_queue) {
      queue_vars_valid = true;
      bool associated = object->GetBooleanValue();
      if (associated)
        associated_with_dispatch_queue = eLazyBoolYes;
      else
        associated_with_dispatch_queue = eLazyBoolNo;
    } else if (key == g_key_reason) {
      reason = std::string(object->GetStringValue());
    } else if (key == g_key_description) {
      description = std::string(object->GetStringValue());
    } else if (key == g_key_registers) {
      StructuredData::Dictionary *registers_dict = object->GetAsDictionary();

      if (registers_dict) {
        registers_dict->ForEach(
            [&expedited_register_map](llvm::StringRef key,
                                      StructuredData::Object *object) -> bool {
              uint32_t reg;
              if (llvm::to_integer(key, reg))
                expedited_register_map[reg] =
                    std::string(object->GetStringValue());
              return true; // Keep iterating through all array items
            });
      }
    } else if (key == g_key_memory) {
      StructuredData::Array *array = object->GetAsArray();
      if (array) {
        array->ForEach([this](StructuredData::Object *object) -> bool {
          StructuredData::Dictionary *mem_cache_dict =
              object->GetAsDictionary();
          if (mem_cache_dict) {
            lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS;
            if (mem_cache_dict->GetValueForKeyAsInteger<lldb::addr_t>(
                    "address", mem_cache_addr)) {
              if (mem_cache_addr != LLDB_INVALID_ADDRESS) {
                llvm::StringRef str;
                if (mem_cache_dict->GetValueForKeyAsString("bytes", str)) {
                  StringExtractor bytes(str);
                  bytes.SetFilePos(0);

                  const size_t byte_size = bytes.GetStringRef().size() / 2;
                  WritableDataBufferSP data_buffer_sp(
                      new DataBufferHeap(byte_size, 0));
                  const size_t bytes_copied =
                      bytes.GetHexBytes(data_buffer_sp->GetData(), 0);
                  if (bytes_copied == byte_size)
                    m_memory_cache.AddL1CacheData(mem_cache_addr,
                                                  data_buffer_sp);
                }
              }
            }
          }
          return true; // Keep iterating through all array items
        });
      }

    } else if (key == g_key_signal)
      signo = object->GetUnsignedIntegerValue(LLDB_INVALID_SIGNAL_NUMBER);
    return true; // Keep iterating through all dictionary key/value pairs
  });

  return SetThreadStopInfo(tid, expedited_register_map, signo, thread_name,
                           reason, description, exc_type, exc_data,
                           thread_dispatch_qaddr, queue_vars_valid,
                           associated_with_dispatch_queue, dispatch_queue_t,
                           queue_name, queue_kind, queue_serial_number);
}

StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
  lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
  stop_packet.SetFilePos(0);
  const char stop_type = stop_packet.GetChar();
  switch (stop_type) {
  case 'T':
  case 'S': {
    // This is a bit of a hack, but it is required. If we did exec, we need to
    // clear our thread lists and also know to rebuild our dynamic register
    // info before we lookup and threads and populate the expedited register
    // values so we need to know this right away so we can cleanup and update
    // our registers.
    const uint32_t stop_id = GetStopID();
    if (stop_id == 0) {
      // Our first stop, make sure we have a process ID, and also make sure we
      // know about our registers
      if (GetID() == LLDB_INVALID_PROCESS_ID && pid != LLDB_INVALID_PROCESS_ID)
        SetID(pid);
      BuildDynamicRegisterInfo(true);
    }
    // Stop with signal and thread info
    lldb::pid_t stop_pid = LLDB_INVALID_PROCESS_ID;
    lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
    const uint8_t signo = stop_packet.GetHexU8();
    llvm::StringRef key;
    llvm::StringRef value;
    std::string thread_name;
    std::string reason;
    std::string description;
    uint32_t exc_type = 0;
    std::vector<addr_t> exc_data;
    addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
    bool queue_vars_valid =
        false; // says if locals below that start with "queue_" are valid
    addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
    LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
    std::string queue_name;
    QueueKind queue_kind = eQueueKindUnknown;
    uint64_t queue_serial_number = 0;
    ExpeditedRegisterMap expedited_register_map;
    AddressableBits addressable_bits;
    while (stop_packet.GetNameColonValue(key, value)) {
      if (key.compare("metype") == 0) {
        // exception type in big endian hex
        value.getAsInteger(16, exc_type);
      } else if (key.compare("medata") == 0) {
        // exception data in big endian hex
        uint64_t x;
        value.getAsInteger(16, x);
        exc_data.push_back(x);
      } else if (key.compare("thread") == 0) {
        // thread-id
        StringExtractorGDBRemote thread_id{value};
        auto pid_tid = thread_id.GetPidTid(pid);
        if (pid_tid) {
          stop_pid = pid_tid->first;
          tid = pid_tid->second;
        } else
          tid = LLDB_INVALID_THREAD_ID;
      } else if (key.compare("threads") == 0) {
        std::lock_guard<std::recursive_mutex> guard(
            m_thread_list_real.GetMutex());
        UpdateThreadIDsFromStopReplyThreadsValue(value);
      } else if (key.compare("thread-pcs") == 0) {
        m_thread_pcs.clear();
        // A comma separated list of all threads in the current
        // process that includes the thread for this stop reply packet
        lldb::addr_t pc;
        while (!value.empty()) {
          llvm::StringRef pc_str;
          std::tie(pc_str, value) = value.split(',');
          if (pc_str.getAsInteger(16, pc))
            pc = LLDB_INVALID_ADDRESS;
          m_thread_pcs.push_back(pc);
        }
      } else if (key.compare("jstopinfo") == 0) {
        StringExtractor json_extractor(value);
        std::string json;
        // Now convert the HEX bytes into a string value
        json_extractor.GetHexByteString(json);

        // This JSON contains thread IDs and thread stop info for all threads.
        // It doesn't contain expedited registers, memory or queue info.
        m_jstopinfo_sp = StructuredData::ParseJSON(json);
      } else if (key.compare("hexname") == 0) {
        StringExtractor name_extractor(value);
        // Now convert the HEX bytes into a string value
        name_extractor.GetHexByteString(thread_name);
      } else if (key.compare("name") == 0) {
        thread_name = std::string(value);
      } else if (key.compare("qaddr") == 0) {
        value.getAsInteger(16, thread_dispatch_qaddr);
      } else if (key.compare("dispatch_queue_t") == 0) {
        queue_vars_valid = true;
        value.getAsInteger(16, dispatch_queue_t);
      } else if (key.compare("qname") == 0) {
        queue_vars_valid = true;
        StringExtractor name_extractor(value);
        // Now convert the HEX bytes into a string value
        name_extractor.GetHexByteString(queue_name);
      } else if (key.compare("qkind") == 0) {
        queue_kind = llvm::StringSwitch<QueueKind>(value)
                         .Case("serial", eQueueKindSerial)
                         .Case("concurrent", eQueueKindConcurrent)
                         .Default(eQueueKindUnknown);
        queue_vars_valid = queue_kind != eQueueKindUnknown;
      } else if (key.compare("qserialnum") == 0) {
        if (!value.getAsInteger(0, queue_serial_number))
          queue_vars_valid = true;
      } else if (key.compare("reason") == 0) {
        reason = std::string(value);
      } else if (key.compare("description") == 0) {
        StringExtractor desc_extractor(value);
        // Now convert the HEX bytes into a string value
        desc_extractor.GetHexByteString(description);
      } else if (key.compare("memory") == 0) {
        // Expedited memory. GDB servers can choose to send back expedited
        // memory that can populate the L1 memory cache in the process so that
        // things like the frame pointer backchain can be expedited. This will
        // help stack backtracing be more efficient by not having to send as
        // many memory read requests down the remote GDB server.

        // Key/value pair format: memory:<addr>=<bytes>;
        // <addr> is a number whose base will be interpreted by the prefix:
        //      "0x[0-9a-fA-F]+" for hex
        //      "0[0-7]+" for octal
        //      "[1-9]+" for decimal
        // <bytes> is native endian ASCII hex bytes just like the register
        // values
        llvm::StringRef addr_str, bytes_str;
        std::tie(addr_str, bytes_str) = value.split('=');
        if (!addr_str.empty() && !bytes_str.empty()) {
          lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS;
          if (!addr_str.getAsInteger(0, mem_cache_addr)) {
            StringExtractor bytes(bytes_str);
            const size_t byte_size = bytes.GetBytesLeft() / 2;
            WritableDataBufferSP data_buffer_sp(
                new DataBufferHeap(byte_size, 0));
            const size_t bytes_copied =
                bytes.GetHexBytes(data_buffer_sp->GetData(), 0);
            if (bytes_copied == byte_size)
              m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp);
          }
        }
      } else if (key.compare("watch") == 0 || key.compare("rwatch") == 0 ||
                 key.compare("awatch") == 0) {
        // Support standard GDB remote stop reply packet 'TAAwatch:addr'
        lldb::addr_t wp_addr = LLDB_INVALID_ADDRESS;
        value.getAsInteger(16, wp_addr);

        WatchpointResourceSP wp_resource_sp =
            m_watchpoint_resource_list.FindByAddress(wp_addr);

        // Rewrite gdb standard watch/rwatch/awatch to
        // "reason:watchpoint" + "description:ADDR",
        // which is parsed in SetThreadStopInfo.
        reason = "watchpoint";
        StreamString ostr;
        ostr.Printf("%" PRIu64, wp_addr);
        description = std::string(ostr.GetString());
      } else if (key.compare("swbreak") == 0 || key.compare("hwbreak") == 0) {
        reason = "breakpoint";
      } else if (key.compare("replaylog") == 0) {
        reason = "history boundary";
      } else if (key.compare("library") == 0) {
        auto error = LoadModules();
        if (error) {
          Log *log(GetLog(GDBRLog::Process));
          LLDB_LOG_ERROR(log, std::move(error), "Failed to load modules: {0}");
        }
      } else if (key.compare("fork") == 0 || key.compare("vfork") == 0) {
        // fork includes child pid/tid in thread-id format
        StringExtractorGDBRemote thread_id{value};
        auto pid_tid = thread_id.GetPidTid(LLDB_INVALID_PROCESS_ID);
        if (!pid_tid) {
          Log *log(GetLog(GDBRLog::Process));
          LLDB_LOG(log, "Invalid PID/TID to fork: {0}", value);
          pid_tid = {{LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID}};
        }

        reason = key.str();
        StreamString ostr;
        ostr.Printf("%" PRIu64 " %" PRIu64, pid_tid->first, pid_tid->second);
        description = std::string(ostr.GetString());
      } else if (key.compare("addressing_bits") == 0) {
        uint64_t addressing_bits;
        if (!value.getAsInteger(0, addressing_bits)) {
          addressable_bits.SetAddressableBits(addressing_bits);
        }
      } else if (key.compare("low_mem_addressing_bits") == 0) {
        uint64_t addressing_bits;
        if (!value.getAsInteger(0, addressing_bits)) {
          addressable_bits.SetLowmemAddressableBits(addressing_bits);
        }
      } else if (key.compare("high_mem_addressing_bits") == 0) {
        uint64_t addressing_bits;
        if (!value.getAsInteger(0, addressing_bits)) {
          addressable_bits.SetHighmemAddressableBits(addressing_bits);
        }
      } else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1])) {
        uint32_t reg = UINT32_MAX;
        if (!key.getAsInteger(16, reg))
          expedited_register_map[reg] = std::string(std::move(value));
      }
      // swbreak and hwbreak are also expected keys, but we don't need to
      // change our behaviour for them because lldb always expects the remote
      // to adjust the program counter (if relevant, e.g., for x86 targets)
    }

    if (stop_pid != LLDB_INVALID_PROCESS_ID && stop_pid != pid) {
      Log *log = GetLog(GDBRLog::Process);
      LLDB_LOG(log,
               "Received stop for incorrect PID = {0} (inferior PID = {1})",
               stop_pid, pid);
      return eStateInvalid;
    }

    if (tid == LLDB_INVALID_THREAD_ID) {
      // A thread id may be invalid if the response is old style 'S' packet
      // which does not provide the
      // thread information. So update the thread list and choose the first
      // one.
      UpdateThreadIDList();

      if (!m_thread_ids.empty()) {
        tid = m_thread_ids.front();
      }
    }

    SetAddressableBitMasks(addressable_bits);

    ThreadSP thread_sp = SetThreadStopInfo(
        tid, expedited_register_map, signo, thread_name, reason, description,
        exc_type, exc_data, thread_dispatch_qaddr, queue_vars_valid,
        associated_with_dispatch_queue, dispatch_queue_t, queue_name,
        queue_kind, queue_serial_number);

    return eStateStopped;
  } break;

  case 'W':
  case 'X':
    // process exited
    return eStateExited;

  default:
    break;
  }
  return eStateInvalid;
}

void ProcessGDBRemote::RefreshStateAfterStop() {
  std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());

  m_thread_ids.clear();
  m_thread_pcs.clear();

  // Set the thread stop info. It might have a "threads" key whose value is a
  // list of all thread IDs in the current process, so m_thread_ids might get
  // set.
  // Check to see if SetThreadStopInfo() filled in m_thread_ids?
  if (m_thread_ids.empty()) {
      // No, we need to fetch the thread list manually
      UpdateThreadIDList();
  }

  // We might set some stop info's so make sure the thread list is up to
  // date before we do that or we might overwrite what was computed here.
  UpdateThreadListIfNeeded();

  if (m_last_stop_packet)
    SetThreadStopInfo(*m_last_stop_packet);
  m_last_stop_packet.reset();

  // If we have queried for a default thread id
  if (m_initial_tid != LLDB_INVALID_THREAD_ID) {
    m_thread_list.SetSelectedThreadByID(m_initial_tid);
    m_initial_tid = LLDB_INVALID_THREAD_ID;
  }

  // Let all threads recover from stopping and do any clean up based on the
  // previous thread state (if any).
  m_thread_list_real.RefreshStateAfterStop();
}

Status ProcessGDBRemote::DoHalt(bool &caused_stop) {
  Status error;

  if (GetPublicState() == eStateAttaching) {
    // We are being asked to halt during an attach. We used to just close our
    // file handle and debugserver will go away, but with remote proxies, it
    // is better to send a positive signal, so let's send the interrupt first...
    caused_stop = m_gdb_comm.Interrupt(GetInterruptTimeout());
    m_gdb_comm.Disconnect();
  } else
    caused_stop = m_gdb_comm.Interrupt(GetInterruptTimeout());
  return error;
}

Status ProcessGDBRemote::DoDetach(bool keep_stopped) {
  Status error;
  Log *log = GetLog(GDBRLog::Process);
  LLDB_LOGF(log, "ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped);

  error = m_gdb_comm.Detach(keep_stopped);
  if (log) {
    if (error.Success())
      log->PutCString(
          "ProcessGDBRemote::DoDetach() detach packet sent successfully");
    else
      LLDB_LOGF(log,
                "ProcessGDBRemote::DoDetach() detach packet send failed: %s",
                error.AsCString() ? error.AsCString() : "<unknown error>");
  }

  if (!error.Success())
    return error;

  // Sleep for one second to let the process get all detached...
  StopAsyncThread();

  SetPrivateState(eStateDetached);
  ResumePrivateStateThread();

  // KillDebugserverProcess ();
  return error;
}

Status ProcessGDBRemote::DoDestroy() {
  Log *log = GetLog(GDBRLog::Process);
  LLDB_LOGF(log, "ProcessGDBRemote::DoDestroy()");

  // Interrupt if our inferior is running...
  int exit_status = SIGABRT;
  std::string exit_string;

  if (m_gdb_comm.IsConnected()) {
    if (GetPublicState() != eStateAttaching) {
      llvm::Expected<int> kill_res = m_gdb_comm.KillProcess(GetID());

      if (kill_res) {
        exit_status = kill_res.get();
#if defined(__APPLE__)
        // For Native processes on Mac OS X, we launch through the Host
        // Platform, then hand the process off to debugserver, which becomes
        // the parent process through "PT_ATTACH".  Then when we go to kill
        // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then
        // we call waitpid which returns with no error and the correct
        // status.  But amusingly enough that doesn't seem to actually reap
        // the process, but instead it is left around as a Zombie.  Probably
        // the kernel is in the process of switching ownership back to lldb
        // which was the original parent, and gets confused in the handoff.
        // Anyway, so call waitpid here to finally reap it.
        PlatformSP platform_sp(GetTarget().GetPlatform());
        if (platform_sp && platform_sp->IsHost()) {
          int status;
          ::pid_t reap_pid;
          reap_pid = waitpid(GetID(), &status, WNOHANG);
          LLDB_LOGF(log, "Reaped pid: %d, status: %d.\n", reap_pid, status);
        }
#endif
        ClearThreadIDList();
        exit_string.assign("killed");
      } else {
        exit_string.assign(llvm::toString(kill_res.takeError()));
      }
    } else {
      exit_string.assign("killed or interrupted while attaching.");
    }
  } else {
    // If we missed setting the exit status on the way out, do it here.
    // NB set exit status can be called multiple times, the first one sets the
    // status.
    exit_string.assign("destroying when not connected to debugserver");
  }

  SetExitStatus(exit_status, exit_string.c_str());

  StopAsyncThread();
  KillDebugserverProcess();
  RemoveNewThreadBreakpoints();
  return Status();
}

void ProcessGDBRemote::RemoveNewThreadBreakpoints() {
  if (m_thread_create_bp_sp) {
    if (TargetSP target_sp = m_target_wp.lock())
      target_sp->RemoveBreakpointByID(m_thread_create_bp_sp->GetID());
    m_thread_create_bp_sp.reset();
  }
}

void ProcessGDBRemote::SetLastStopPacket(
    const StringExtractorGDBRemote &response) {
  const bool did_exec =
      response.GetStringRef().find(";reason:exec;") != std::string::npos;
  if (did_exec) {
    Log *log = GetLog(GDBRLog::Process);
    LLDB_LOGF(log, "ProcessGDBRemote::SetLastStopPacket () - detected exec");

    m_thread_list_real.Clear();
    m_thread_list.Clear();
    BuildDynamicRegisterInfo(true);
    m_gdb_comm.ResetDiscoverableSettings(did_exec);
  }

  m_last_stop_packet = response;
}

void ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp) {
  Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp));
}

// Process Queries

bool ProcessGDBRemote::IsAlive() {
  return m_gdb_comm.IsConnected() && Process::IsAlive();
}

addr_t ProcessGDBRemote::GetImageInfoAddress() {
  // request the link map address via the $qShlibInfoAddr packet
  lldb::addr_t addr = m_gdb_comm.GetShlibInfoAddr();

  // the loaded module list can also provides a link map address
  if (addr == LLDB_INVALID_ADDRESS) {
    llvm::Expected<LoadedModuleInfoList> list = GetLoadedModuleList();
    if (!list) {
      Log *log = GetLog(GDBRLog::Process);
      LLDB_LOG_ERROR(log, list.takeError(), "Failed to read module list: {0}.");
    } else {
      addr = list->m_link_map;
    }
  }

  return addr;
}

void ProcessGDBRemote::WillPublicStop() {
  // See if the GDB remote client supports the JSON threads info. If so, we
  // gather stop info for all threads, expedited registers, expedited memory,
  // runtime queue information (iOS and MacOSX only), and more. Expediting
  // memory will help stack backtracing be much faster. Expediting registers
  // will make sure we don't have to read the thread registers for GPRs.
  m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo();

  if (m_jthreadsinfo_sp) {
    // Now set the stop info for each thread and also expedite any registers
    // and memory that was in the jThreadsInfo response.
    StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
    if (thread_infos) {
      const size_t n = thread_infos->GetSize();
      for (size_t i = 0; i < n; ++i) {
        StructuredData::Dictionary *thread_dict =
            thread_infos->GetItemAtIndex(i)->GetAsDictionary();
        if (thread_dict)
          SetThreadStopInfo(thread_dict);
      }
    }
  }
}

// Process Memory
size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
                                      Status &error) {
  using xPacketState = GDBRemoteCommunicationClient::xPacketState;

  GetMaxMemorySize();
  xPacketState x_state = m_gdb_comm.GetxPacketState();

  // M and m packets take 2 bytes for 1 byte of memory
  size_t max_memory_size = x_state != xPacketState::Unimplemented
                               ? m_max_memory_size
                               : m_max_memory_size / 2;
  if (size > max_memory_size) {
    // Keep memory read sizes down to a sane limit. This function will be
    // called multiple times in order to complete the task by
    // lldb_private::Process so it is ok to do this.
    size = max_memory_size;
  }

  char packet[64];
  int packet_len;
  packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64,
                          x_state != xPacketState::Unimplemented ? 'x' : 'm',
                          (uint64_t)addr, (uint64_t)size);
  assert(packet_len + 1 < (int)sizeof(packet));
  UNUSED_IF_ASSERT_DISABLED(packet_len);
  StringExtractorGDBRemote response;
  if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response,
                                              GetInterruptTimeout()) ==
      GDBRemoteCommunication::PacketResult::Success) {
    if (response.IsNormalResponse()) {
      error.Clear();
      if (x_state != xPacketState::Unimplemented) {
        // The lower level GDBRemoteCommunication packet receive layer has
        // already de-quoted any 0x7d character escaping that was present in
        // the packet

        llvm::StringRef data_received = response.GetStringRef();
        if (x_state == xPacketState::Prefixed &&
            !data_received.consume_front("b")) {
          error = Status::FromErrorStringWithFormatv(
              "unexpected response to GDB server memory read packet '{0}': "
              "'{1}'",
              packet, data_received);
          return 0;
        }
        // Don't write past the end of BUF if the remote debug server gave us
        // too much data for some reason.
        size_t memcpy_size = std::min(size, data_received.size());
        memcpy(buf, data_received.data(), memcpy_size);
        return memcpy_size;
      } else {
        return response.GetHexBytes(
            llvm::MutableArrayRef<uint8_t>((uint8_t *)buf, size), '\xdd');
      }
    } else if (response.IsErrorResponse())
      error = Status::FromErrorStringWithFormat(
          "memory read failed for 0x%" PRIx64, addr);
    else if (response.IsUnsupportedResponse())
      error = Status::FromErrorStringWithFormat(
          "GDB server does not support reading memory");
    else
      error = Status::FromErrorStringWithFormat(
          "unexpected response to GDB server memory read packet '%s': '%s'",
          packet, response.GetStringRef().data());
  } else {
    error = Status::FromErrorStringWithFormat("failed to send packet: '%s'",
                                              packet);
  }
  return 0;
}

/// Returns the number of ranges that is safe to request using MultiMemRead
/// while respecting max_packet_size.
static uint64_t ComputeNumRangesMultiMemRead(
    uint64_t max_packet_size,
    llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges) {
  // Each range is specified by two numbers (up to 16 ASCII characters) and one
  // comma.
  constexpr uint64_t range_overhead = 33;
  uint64_t current_size = 0;
  for (auto [idx, range] : llvm::enumerate(ranges)) {
    uint64_t potential_size = current_size + range.size + range_overhead;
    if (potential_size > max_packet_size) {
      if (idx == 0)
        LLDB_LOG(GetLog(GDBRLog::Process),
                 "MultiMemRead input has a range (base = {0:x}, size = {1}) "
                 "bigger than the maximum allowed by remote",
                 range.base, range.size);
      return idx;
    }
  }
  return ranges.size();
}

llvm::SmallVector<llvm::MutableArrayRef<uint8_t>>
ProcessGDBRemote::ReadMemoryRanges(
    llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges,
    llvm::MutableArrayRef<uint8_t> buffer) {
  if (!m_gdb_comm.GetMultiMemReadSupported())
    return Process::ReadMemoryRanges(ranges, buffer);

  const llvm::ArrayRef<Range<lldb::addr_t, size_t>> original_ranges = ranges;
  llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> memory_regions;

  while (!ranges.empty()) {
    uint64_t num_ranges =
        ComputeNumRangesMultiMemRead(m_max_memory_size, ranges);
    if (num_ranges == 0)
      return Process::ReadMemoryRanges(original_ranges, buffer);

    auto ranges_for_request = ranges.take_front(num_ranges);
    ranges = ranges.drop_front(num_ranges);

    llvm::Expected<StringExtractorGDBRemote> response =
        SendMultiMemReadPacket(ranges_for_request);
    if (!response) {
      LLDB_LOG_ERROR(GetLog(GDBRLog::Process), response.takeError(),
                     "MultiMemRead error response: {0}");
      return Process::ReadMemoryRanges(original_ranges, buffer);
    }

    llvm::StringRef response_str = response->GetStringRef();
    const unsigned expected_num_ranges = ranges_for_request.size();
    if (llvm::Error error = ParseMultiMemReadPacket(
            response_str, buffer, expected_num_ranges, memory_regions)) {
      LLDB_LOG_ERROR(GetLog(GDBRLog::Process), std::move(error),
                     "MultiMemRead error parsing response: {0}");
      return Process::ReadMemoryRanges(original_ranges, buffer);
    }
  }
  return memory_regions;
}

llvm::Expected<StringExtractorGDBRemote>
ProcessGDBRemote::SendMultiMemReadPacket(
    llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges) {
  std::string packet_str;
  llvm::raw_string_ostream stream(packet_str);
  stream << "MultiMemRead:ranges:";

  auto range_to_stream = [&](auto range) {
    // the "-" marker omits the '0x' prefix.
    stream << llvm::formatv("{0:x-},{1:x-}", range.base, range.size);
  };
  llvm::interleave(ranges, stream, range_to_stream, ",");
  stream << ";";

  StringExtractorGDBRemote response;
  GDBRemoteCommunication::PacketResult packet_result =
      m_gdb_comm.SendPacketAndWaitForResponse(packet_str.data(), response,
                                              GetInterruptTimeout());
  if (packet_result != GDBRemoteCommunication::PacketResult::Success)
    return llvm::createStringErrorV("MultiMemRead failed to send packet: '{0}'",
                                    packet_str);

  if (response.IsErrorResponse())
    return llvm::createStringErrorV("MultiMemRead failed: '{0}'",
                                    response.GetStringRef());

  if (!response.IsNormalResponse())
    return llvm::createStringErrorV("MultiMemRead unexpected response: '{0}'",
                                    response.GetStringRef());

  return response;
}

llvm::Error ProcessGDBRemote::ParseMultiMemReadPacket(
    llvm::StringRef response_str, llvm::MutableArrayRef<uint8_t> buffer,
    unsigned expected_num_ranges,
    llvm::SmallVectorImpl<llvm::MutableArrayRef<uint8_t>> &memory_regions) {
  // The sizes and the data are separated by a `;`.
  auto [sizes_str, memory_data] = response_str.split(';');
  if (sizes_str.size() == response_str.size())
    return llvm::createStringErrorV(
        "MultiMemRead response missing field separator ';' in: '{0}'",
        response_str);

  // Sizes are separated by a `,`.
  for (llvm::StringRef size_str : llvm::split(sizes_str, ',')) {
    uint64_t read_size;
    if (size_str.getAsInteger(16, read_size))
      return llvm::createStringErrorV(
          "MultiMemRead response has invalid size string: {0}", size_str);

    if (memory_data.size() < read_size)
      return llvm::createStringErrorV("MultiMemRead response did not have "
                                      "enough data, requested sizes: {0}",
                                      sizes_str);

    llvm::StringRef region_to_read = memory_data.take_front(read_size);
    memory_data = memory_data.drop_front(read_size);

    assert(buffer.size() >= read_size);
    llvm::MutableArrayRef<uint8_t> region_to_write =
        buffer.take_front(read_size);
    buffer = buffer.drop_front(read_size);

    memcpy(region_to_write.data(), region_to_read.data(), read_size);
    memory_regions.push_back(region_to_write);
  }

  return llvm::Error::success();
}

bool ProcessGDBRemote::SupportsMemoryTagging() {
  return m_gdb_comm.GetMemoryTaggingSupported();
}

llvm::Expected<std::vector<uint8_t>>
ProcessGDBRemote::DoReadMemoryTags(lldb::addr_t addr, size_t len,
                                   int32_t type) {
  // By this point ReadMemoryTags has validated that tagging is enabled
  // for this target/process/address.
  DataBufferSP buffer_sp = m_gdb_comm.ReadMemoryTags(addr, len, type);
  if (!buffer_sp) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "Error reading memory tags from remote");
  }

  // Return the raw tag data
  llvm::ArrayRef<uint8_t> tag_data = buffer_sp->GetData();
  std::vector<uint8_t> got;
  got.reserve(tag_data.size());
  std::copy(tag_data.begin(), tag_data.end(), std::back_inserter(got));
  return got;
}

Status ProcessGDBRemote::DoWriteMemoryTags(lldb::addr_t addr, size_t len,
                                           int32_t type,
                                           const std::vector<uint8_t> &tags) {
  // By now WriteMemoryTags should have validated that tagging is enabled
  // for this target/process.
  return m_gdb_comm.WriteMemoryTags(addr, len, type, tags);
}

Status ProcessGDBRemote::WriteObjectFile(
    std::vector<ObjectFile::LoadableData> entries) {
  Status error;
  // Sort the entries by address because some writes, like those to flash
  // memory, must happen in order of increasing address.
  llvm::stable_sort(entries, [](const ObjectFile::LoadableData a,
                                const ObjectFile::LoadableData b) {
    return a.Dest < b.Dest;
  });
  m_allow_flash_writes = true;
  error = Process::WriteObjectFile(entries);
  if (error.Success())
    error = FlashDone();
  else
    // Even though some of the writing failed, try to send a flash done if some
    // of the writing succeeded so the flash state is reset to normal, but
    // don't stomp on the error status that was set in the write failure since
    // that's the one we want to report back.
    FlashDone();
  m_allow_flash_writes = false;
  return error;
}

bool ProcessGDBRemote::HasErased(FlashRange range) {
  auto size = m_erased_flash_ranges.GetSize();
  for (size_t i = 0; i < size; ++i)
    if (m_erased_flash_ranges.GetEntryAtIndex(i)->Contains(range))
      return true;
  return false;
}

Status ProcessGDBRemote::FlashErase(lldb::addr_t addr, size_t size) {
  Status status;

  MemoryRegionInfo region;
  status = GetMemoryRegionInfo(addr, region);
  if (!status.Success())
    return status;

  // The gdb spec doesn't say if erasures are allowed across multiple regions,
  // but we'll disallow it to be safe and to keep the logic simple by worring
  // about only one region's block size.  DoMemoryWrite is this function's
  // primary user, and it can easily keep writes within a single memory region
  if (addr + size > region.GetRange().GetRangeEnd()) {
    status =
        Status::FromErrorString("Unable to erase flash in multiple regions");
    return status;
  }

  uint64_t blocksize = region.GetBlocksize();
  if (blocksize == 0) {
    status =
        Status::FromErrorString("Unable to erase flash because blocksize is 0");
    return status;
  }

  // Erasures can only be done on block boundary adresses, so round down addr
  // and round up size
  lldb::addr_t block_start_addr = addr - (addr % blocksize);
  size += (addr - block_start_addr);
  if ((size % blocksize) != 0)
    size += (blocksize - size % blocksize);

  FlashRange range(block_start_addr, size);

  if (HasErased(range))
    return status;

  // We haven't erased the entire range, but we may have erased part of it.
  // (e.g., block A is already erased and range starts in A and ends in B). So,
  // adjust range if necessary to exclude already erased blocks.
  if (!m_erased_flash_ranges.IsEmpty()) {
    // Assuming that writes and erasures are done in increasing addr order,
    // because that is a requirement of the vFlashWrite command.  Therefore, we
    // only need to look at the last range in the list for overlap.
    const auto &last_range = *m_erased_flash_ranges.Back();
    if (range.GetRangeBase() < last_range.GetRangeEnd()) {
      auto overlap = last_range.GetRangeEnd() - range.GetRangeBase();
      // overlap will be less than range.GetByteSize() or else HasErased()
      // would have been true
      range.SetByteSize(range.GetByteSize() - overlap);
      range.SetRangeBase(range.GetRangeBase() + overlap);
    }
  }

  StreamString packet;
  packet.Printf("vFlashErase:%" PRIx64 ",%" PRIx64, range.GetRangeBase(),
                (uint64_t)range.GetByteSize());

  StringExtractorGDBRemote response;
  if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
                                              GetInterruptTimeout()) ==
      GDBRemoteCommunication::PacketResult::Success) {
    if (response.IsOKResponse()) {
      m_erased_flash_ranges.Insert(range, true);
    } else {
      if (response.IsErrorResponse())
        status = Status::FromErrorStringWithFormat(
            "flash erase failed for 0x%" PRIx64, addr);
      else if (response.IsUnsupportedResponse())
        status = Status::FromErrorStringWithFormat(
            "GDB server does not support flashing");
      else
        status = Status::FromErrorStringWithFormat(
            "unexpected response to GDB server flash erase packet '%s': '%s'",
            packet.GetData(), response.GetStringRef().data());
    }
  } else {
    status = Status::FromErrorStringWithFormat("failed to send packet: '%s'",
                                               packet.GetData());
  }
  return status;
}

Status ProcessGDBRemote::FlashDone() {
  Status status;
  // If we haven't erased any blocks, then we must not have written anything
  // either, so there is no need to actually send a vFlashDone command
  if (m_erased_flash_ranges.IsEmpty())
    return status;
  StringExtractorGDBRemote response;
  if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response,
                                              GetInterruptTimeout()) ==
      GDBRemoteCommunication::PacketResult::Success) {
    if (response.IsOKResponse()) {
      m_erased_flash_ranges.Clear();
    } else {
      if (response.IsErrorResponse())
        status = Status::FromErrorStringWithFormat("flash done failed");
      else if (response.IsUnsupportedResponse())
        status = Status::FromErrorStringWithFormat(
            "GDB server does not support flashing");
      else
        status = Status::FromErrorStringWithFormat(
            "unexpected response to GDB server flash done packet: '%s'",
            response.GetStringRef().data());
    }
  } else {
    status =
        Status::FromErrorStringWithFormat("failed to send flash done packet");
  }
  return status;
}

size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf,
                                       size_t size, Status &error) {
  GetMaxMemorySize();
  // M and m packets take 2 bytes for 1 byte of memory
  size_t max_memory_size = m_max_memory_size / 2;
  if (size > max_memory_size) {
    // Keep memory read sizes down to a sane limit. This function will be
    // called multiple times in order to complete the task by
    // lldb_private::Process so it is ok to do this.
    size = max_memory_size;
  }

  StreamGDBRemote packet;

  MemoryRegionInfo region;
  Status region_status = GetMemoryRegionInfo(addr, region);

  bool is_flash =
      region_status.Success() && region.GetFlash() == MemoryRegionInfo::eYes;

  if (is_flash) {
    if (!m_allow_flash_writes) {
      error = Status::FromErrorString("Writing to flash memory is not allowed");
      return 0;
    }
    // Keep the write within a flash memory region
    if (addr + size > region.GetRange().GetRangeEnd())
      size = region.GetRange().GetRangeEnd() - addr;
    // Flash memory must be erased before it can be written
    error = FlashErase(addr, size);
    if (!error.Success())
      return 0;
    packet.Printf("vFlashWrite:%" PRIx64 ":", addr);
    packet.PutEscapedBytes(buf, size);
  } else {
    packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
    packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(),
                             endian::InlHostByteOrder());
  }
  StringExtractorGDBRemote response;
  if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
                                              GetInterruptTimeout()) ==
      GDBRemoteCommunication::PacketResult::Success) {
    if (response.IsOKResponse()) {
      error.Clear();
      return size;
    } else if (response.IsErrorResponse())
      error = Status::FromErrorStringWithFormat(
          "memory write failed for 0x%" PRIx64, addr);
    else if (response.IsUnsupportedResponse())
      error = Status::FromErrorStringWithFormat(
          "GDB server does not support writing memory");
    else
      error = Status::FromErrorStringWithFormat(
          "unexpected response to GDB server memory write packet '%s': '%s'",
          packet.GetData(), response.GetStringRef().data());
  } else {
    error = Status::FromErrorStringWithFormat("failed to send packet: '%s'",
                                              packet.GetData());
  }
  return 0;
}

lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size,
                                                uint32_t permissions,
                                                Status &error) {
  Log *log = GetLog(LLDBLog::Process | LLDBLog::Expressions);
  addr_t allocated_addr = LLDB_INVALID_ADDRESS;

  if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo) {
    allocated_addr = m_gdb_comm.AllocateMemory(size, permissions);
    if (allocated_addr != LLDB_INVALID_ADDRESS ||
        m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes)
      return allocated_addr;
  }

  if (m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolNo) {
    // Call mmap() to create memory in the inferior..
    unsigned prot = 0;
    if (permissions & lldb::ePermissionsReadable)
      prot |= eMmapProtRead;
    if (permissions & lldb::ePermissionsWritable)
      prot |= eMmapProtWrite;
    if (permissions & lldb::ePermissionsExecutable)
      prot |= eMmapProtExec;

    if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
                         eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0))
      m_addr_to_mmap_size[allocated_addr] = size;
    else {
      allocated_addr = LLDB_INVALID_ADDRESS;
      LLDB_LOGF(log,
                "ProcessGDBRemote::%s no direct stub support for memory "
                "allocation, and InferiorCallMmap also failed - is stub "
                "missing register context save/restore capability?",
                __FUNCTION__);
    }
  }

  if (allocated_addr == LLDB_INVALID_ADDRESS)
    error = Status::FromErrorStringWithFormat(
        "unable to allocate %" PRIu64 " bytes of memory with permissions %s",
        (uint64_t)size, GetPermissionsAsCString(permissions));
  else
    error.Clear();
  return allocated_addr;
}

Status ProcessGDBRemote::DoGetMemoryRegionInfo(addr_t load_addr,
                                               MemoryRegionInfo &region_info) {

  Status error(m_gdb_comm.GetMemoryRegionInfo(load_addr, region_info));
  return error;
}

std::optional<uint32_t> ProcessGDBRemote::GetWatchpointSlotCount() {
  return m_gdb_comm.GetWatchpointSlotCount();
}

std::optional<bool> ProcessGDBRemote::DoGetWatchpointReportedAfter() {
  return m_gdb_comm.GetWatchpointReportedAfter();
}

Status ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) {
  Status error;
  LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory();

  switch (supported) {
  case eLazyBoolCalculate:
    // We should never be deallocating memory without allocating memory first
    // so we should never get eLazyBoolCalculate
    error = Status::FromErrorString(
        "tried to deallocate memory without ever allocating memory");
    break;

  case eLazyBoolYes:
    if (!m_gdb_comm.DeallocateMemory(addr))
      error = Status::FromErrorStringWithFormat(
          "unable to deallocate memory at 0x%" PRIx64, addr);
    break;

  case eLazyBoolNo:
    // Call munmap() to deallocate memory in the inferior..
    {
      MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
      if (pos != m_addr_to_mmap_size.end() &&
          InferiorCallMunmap(this, addr, pos->second))
        m_addr_to_mmap_size.erase(pos);
      else
        error = Status::FromErrorStringWithFormat(
            "unable to deallocate memory at 0x%" PRIx64, addr);
    }
    break;
  }

  return error;
}

// Process STDIO
size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len,
                                  Status &error) {
  if (m_stdio_communication.IsConnected()) {
    ConnectionStatus status;
    m_stdio_communication.WriteAll(src, src_len, status, nullptr);
  } else if (m_stdin_forward) {
    m_gdb_comm.SendStdinNotification(src, src_len);
  }
  return 0;
}

Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
  Status error;
  assert(bp_site != nullptr);

  // Get logging info
  Log *log = GetLog(GDBRLog::Breakpoints);
  user_id_t site_id = bp_site->GetID();

  // Get the breakpoint address
  const addr_t addr = bp_site->GetLoadAddress();

  // Log that a breakpoint was requested
  LLDB_LOGF(log,
            "ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64
            ") address = 0x%" PRIx64,
            site_id, (uint64_t)addr);

  // Breakpoint already exists and is enabled
  if (bp_site->IsEnabled()) {
    LLDB_LOGF(log,
              "ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64
              ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)",
              site_id, (uint64_t)addr);
    return error;
  }

  // Get the software breakpoint trap opcode size
  const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);

  // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this
  // breakpoint type is supported by the remote stub. These are set to true by
  // default, and later set to false only after we receive an unimplemented
  // response when sending a breakpoint packet. This means initially that
  // unless we were specifically instructed to use a hardware breakpoint, LLDB
  // will attempt to set a software breakpoint. HardwareRequired() also queries
  // a boolean variable which indicates if the user specifically asked for
  // hardware breakpoints.  If true then we will skip over software
  // breakpoints.
  if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) &&
      (!bp_site->HardwareRequired())) {
    // Try to send off a software breakpoint packet ($Z0)
    uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
        eBreakpointSoftware, true, addr, bp_op_size, GetInterruptTimeout());
    if (error_no == 0) {
      // The breakpoint was placed successfully
      bp_site->SetEnabled(true);
      bp_site->SetType(BreakpointSite::eExternal);
      return error;
    }

    // SendGDBStoppointTypePacket() will return an error if it was unable to
    // set this breakpoint. We need to differentiate between a error specific
    // to placing this breakpoint or if we have learned that this breakpoint
    // type is unsupported. To do this, we must test the support boolean for
    // this breakpoint type to see if it now indicates that this breakpoint
    // type is unsupported.  If they are still supported then we should return
    // with the error code.  If they are now unsupported, then we would like to
    // fall through and try another form of breakpoint.
    if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) {
      if (error_no != UINT8_MAX)
        error = Status::FromErrorStringWithFormat(
            "error: %d sending the breakpoint request", error_no);
      else
        error = Status::FromErrorString("error sending the breakpoint request");
      return error;
    }

    // We reach here when software breakpoints have been found to be
    // unsupported. For future calls to set a breakpoint, we will not attempt
    // to set a breakpoint with a type that is known not to be supported.
    LLDB_LOGF(log, "Software breakpoints are unsupported");

    // So we will fall through and try a hardware breakpoint
  }

  // The process of setting a hardware breakpoint is much the same as above.
  // We check the supported boolean for this breakpoint type, and if it is
  // thought to be supported then we will try to set this breakpoint with a
  // hardware breakpoint.
  if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) {
    // Try to send off a hardware breakpoint packet ($Z1)
    uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
        eBreakpointHardware, true, addr, bp_op_size, GetInterruptTimeout());
    if (error_no == 0) {
      // The breakpoint was placed successfully
      bp_site->SetEnabled(true);
      bp_site->SetType(BreakpointSite::eHardware);
      return error;
    }

    // Check if the error was something other then an unsupported breakpoint
    // type
    if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) {
      // Unable to set this hardware breakpoint
      if (error_no != UINT8_MAX)
        error = Status::FromErrorStringWithFormat(
            "error: %d sending the hardware breakpoint request "
            "(hardware breakpoint resources might be exhausted or unavailable)",
            error_no);
      else
        error = Status::FromErrorString(
            "error sending the hardware breakpoint request "
            "(hardware breakpoint resources "
            "might be exhausted or unavailable)");
      return error;
    }

    // We will reach here when the stub gives an unsupported response to a
    // hardware breakpoint
    LLDB_LOGF(log, "Hardware breakpoints are unsupported");

    // Finally we will falling through to a #trap style breakpoint
  }

  // Don't fall through when hardware breakpoints were specifically requested
  if (bp_site->HardwareRequired()) {
    error = Status::FromErrorString("hardware breakpoints are not supported");
    return error;
  }

  // As a last resort we want to place a manual breakpoint. An instruction is
  // placed into the process memory using memory write packets.
  return EnableSoftwareBreakpoint(bp_site);
}

Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) {
  Status error;
  assert(bp_site != nullptr);
  addr_t addr = bp_site->GetLoadAddress();
  user_id_t site_id = bp_site->GetID();
  Log *log = GetLog(GDBRLog::Breakpoints);
  LLDB_LOGF(log,
            "ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64
            ") addr = 0x%8.8" PRIx64,
            site_id, (uint64_t)addr);

  if (bp_site->IsEnabled()) {
    const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);

    BreakpointSite::Type bp_type = bp_site->GetType();
    switch (bp_type) {
    case BreakpointSite::eSoftware:
      error = DisableSoftwareBreakpoint(bp_site);
      break;

    case BreakpointSite::eHardware:
      if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false,
                                                addr, bp_op_size,
                                                GetInterruptTimeout()))
        error = Status::FromErrorString("unknown error");
      break;

    case BreakpointSite::eExternal: {
      if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false,
                                                addr, bp_op_size,
                                                GetInterruptTimeout()))
        error = Status::FromErrorString("unknown error");
    } break;
    }
    if (error.Success())
      bp_site->SetEnabled(false);
  } else {
    LLDB_LOGF(log,
              "ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64
              ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)",
              site_id, (uint64_t)addr);
    return error;
  }

  if (error.Success())
    error = Status::FromErrorString("unknown error");
  return error;
}

// Pre-requisite: wp != NULL.
static GDBStoppointType
GetGDBStoppointType(const WatchpointResourceSP &wp_res_sp) {
  assert(wp_res_sp);
  bool read = wp_res_sp->WatchpointResourceRead();
  bool write = wp_res_sp->WatchpointResourceWrite();

  assert((read || write) &&
         "WatchpointResource type is neither read nor write");
  if (read && write)
    return eWatchpointReadWrite;
  else if (read)
    return eWatchpointRead;
  else
    return eWatchpointWrite;
}

Status ProcessGDBRemote::EnableWatchpoint(WatchpointSP wp_sp, bool notify) {
  Status error;
  if (!wp_sp) {
    error = Status::FromErrorString("No watchpoint specified");
    return error;
  }
  user_id_t watchID = wp_sp->GetID();
  addr_t addr = wp_sp->GetLoadAddress();
  Log *log(GetLog(GDBRLog::Watchpoints));
  LLDB_LOGF(log, "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")",
            watchID);
  if (wp_sp->IsEnabled()) {
    LLDB_LOGF(log,
              "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64
              ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
              watchID, (uint64_t)addr);
    return error;
  }

  bool read = wp_sp->WatchpointRead();
  bool write = wp_sp->WatchpointWrite() || wp_sp->WatchpointModify();
  size_t size = wp_sp->GetByteSize();

  ArchSpec target_arch = GetTarget().GetArchitecture();
  WatchpointHardwareFeature supported_features =
      m_gdb_comm.GetSupportedWatchpointTypes();

  std::vector<WatchpointResourceSP> resources =
      WatchpointAlgorithms::AtomizeWatchpointRequest(
          addr, size, read, write, supported_features, target_arch);

  // LWP_TODO: Now that we know the WP Resources needed to implement this
  // Watchpoint, we need to look at currently allocated Resources in the
  // Process and if they match, or are within the same memory granule, or
  // overlapping memory ranges, then we need to combine them.  e.g. one
  // Watchpoint watching 1 byte at 0x1002 and a second watchpoint watching 1
  // byte at 0x1003, they must use the same hardware watchpoint register
  // (Resource) to watch them.

  // This may mean that an existing resource changes its type (read to
  // read+write) or address range it is watching, in which case the old
  // watchpoint needs to be disabled and the new Resource addr/size/type
  // watchpoint enabled.

  // If we modify a shared Resource to accomodate this newly added Watchpoint,
  // and we are unable to set all of the Resources for it in the inferior, we
  // will return an error for this Watchpoint and the shared Resource should
  // be restored.  e.g. this Watchpoint requires three Resources, one which
  // is shared with another Watchpoint.  We extend the shared Resouce to
  // handle both Watchpoints and we try to set two new ones.  But if we don't
  // have sufficient watchpoint register for all 3, we need to show an error
  // for creating this Watchpoint and we should reset the shared Resource to
  // its original configuration because it is no longer shared.

  bool set_all_resources = true;
  std::vector<WatchpointResourceSP> succesfully_set_resources;
  for (const auto &wp_res_sp : resources) {
    addr_t addr = wp_res_sp->GetLoadAddress();
    size_t size = wp_res_sp->GetByteSize();
    GDBStoppointType type = GetGDBStoppointType(wp_res_sp);
    if (!m_gdb_comm.SupportsGDBStoppointPacket(type) ||
        m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, size,
                                              GetInterruptTimeout())) {
      set_all_resources = false;
      break;
    } else {
      succesfully_set_resources.push_back(wp_res_sp);
    }
  }
  if (set_all_resources) {
    wp_sp->SetEnabled(true, notify);
    for (const auto &wp_res_sp : resources) {
      // LWP_TODO: If we expanded/reused an existing Resource,
      // it's already in the WatchpointResourceList.
      wp_res_sp->AddConstituent(wp_sp);
      m_watchpoint_resource_list.Add(wp_res_sp);
    }
    return error;
  } else {
    // We failed to allocate one of the resources.  Unset all
    // of the new resources we did successfully set in the
    // process.
    for (const auto &wp_res_sp : succesfully_set_resources) {
      addr_t addr = wp_res_sp->GetLoadAddress();
      size_t size = wp_res_sp->GetByteSize();
      GDBStoppointType type = GetGDBStoppointType(wp_res_sp);
      m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, size,
                                            GetInterruptTimeout());
    }
    error = Status::FromErrorString(
        "Setting one of the watchpoint resources failed");
  }
  return error;
}

Status ProcessGDBRemote::DisableWatchpoint(WatchpointSP wp_sp, bool notify) {
  Status error;
  if (!wp_sp) {
    error = Status::FromErrorString("Watchpoint argument was NULL.");
    return error;
  }

  user_id_t watchID = wp_sp->GetID();

  Log *log(GetLog(GDBRLog::Watchpoints));

  addr_t addr = wp_sp->GetLoadAddress();

  LLDB_LOGF(log,
            "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64
            ") addr = 0x%8.8" PRIx64,
            watchID, (uint64_t)addr);

  if (!wp_sp->IsEnabled()) {
    LLDB_LOGF(log,
              "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64
              ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)",
              watchID, (uint64_t)addr);
    // See also 'class WatchpointSentry' within StopInfo.cpp. This disabling
    // attempt might come from the user-supplied actions, we'll route it in
    // order for the watchpoint object to intelligently process this action.
    wp_sp->SetEnabled(false, notify);
    return error;
  }

  if (wp_sp->IsHardware()) {
    bool disabled_all = true;

    std::vector<WatchpointResourceSP> unused_resources;
    for (const auto &wp_res_sp : m_watchpoint_resource_list.Sites()) {
      if (wp_res_sp->ConstituentsContains(wp_sp)) {
        GDBStoppointType type = GetGDBStoppointType(wp_res_sp);
        addr_t addr = wp_res_sp->GetLoadAddress();
        size_t size = wp_res_sp->GetByteSize();
        if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, size,
                                                  GetInterruptTimeout())) {
          disabled_all = false;
        } else {
          wp_res_sp->RemoveConstituent(wp_sp);
          if (wp_res_sp->GetNumberOfConstituents() == 0)
            unused_resources.push_back(wp_res_sp);
        }
      }
    }
    for (auto &wp_res_sp : unused_resources)
      m_watchpoint_resource_list.Remove(wp_res_sp->GetID());

    wp_sp->SetEnabled(false, notify);
    if (!disabled_all)
      error = Status::FromErrorString(
          "Failure disabling one of the watchpoint locations");
  }
  return error;
}

void ProcessGDBRemote::Clear() {
  m_thread_list_real.Clear();
  m_thread_list.Clear();
}

Status ProcessGDBRemote::DoSignal(int signo) {
  Status error;
  Log *log = GetLog(GDBRLog::Process);
  LLDB_LOGF(log, "ProcessGDBRemote::DoSignal (signal = %d)", signo);

  if (!m_gdb_comm.SendAsyncSignal(signo, GetInterruptTimeout()))
    error =
        Status::FromErrorStringWithFormat("failed to send signal %i", signo);
  return error;
}

Status
ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) {
  // Make sure we aren't already connected?
  if (m_gdb_comm.IsConnected())
    return Status();

  PlatformSP platform_sp(GetTarget().GetPlatform());
  if (platform_sp && !platform_sp->IsHost())
    return Status::FromErrorString("Lost debug server connection");

  auto error = LaunchAndConnectToDebugserver(process_info);
  if (error.Fail()) {
    const char *error_string = error.AsCString();
    if (error_string == nullptr)
      error_string = "unable to launch " DEBUGSERVER_BASENAME;
  }
  return error;
}

static FileSpec GetDebugserverPath(Platform &platform) {
  Log *log = GetLog(GDBRLog::Process);
  // If we locate debugserver, keep that located version around
  static FileSpec g_debugserver_file_spec;
  FileSpec debugserver_file_spec;

  Environment host_env = Host::GetEnvironment();

  // Always check to see if we have an environment override for the path to the
  // debugserver to use and use it if we do.
  std::string env_debugserver_path = host_env.lookup("LLDB_DEBUGSERVER_PATH");
  if (!env_debugserver_path.empty()) {
    debugserver_file_spec.SetFile(env_debugserver_path,
                                  FileSpec::Style::native);
    LLDB_LOG(log, "gdb-remote stub exe path set from environment variable: {0}",
             env_debugserver_path);
  } else
    debugserver_file_spec = g_debugserver_file_spec;
  if (FileSystem::Instance().Exists(debugserver_file_spec))
    return debugserver_file_spec;

  // The debugserver binary is in the LLDB.framework/Resources directory.
  debugserver_file_spec = HostInfo::GetSupportExeDir();
  if (debugserver_file_spec) {
    debugserver_file_spec.AppendPathComponent(DEBUGSERVER_BASENAME);
    if (FileSystem::Instance().Exists(debugserver_file_spec)) {
      LLDB_LOG(log, "found gdb-remote stub exe '{0}'", debugserver_file_spec);

      g_debugserver_file_spec = debugserver_file_spec;
    } else {
      debugserver_file_spec = platform.LocateExecutable(DEBUGSERVER_BASENAME);
      if (!debugserver_file_spec) {
        // Platform::LocateExecutable() wouldn't return a path if it doesn't
        // exist
        LLDB_LOG(log, "could not find gdb-remote stub exe '{0}'",
                 debugserver_file_spec);
      }
      // Don't cache the platform specific GDB server binary as it could
      // change from platform to platform
      g_debugserver_file_spec.Clear();
    }
  }
  return debugserver_file_spec;
}

Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
    const ProcessInfo &process_info) {
  using namespace std::placeholders; // For _1, _2, etc.

  if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
    return Status();

  ProcessLaunchInfo debugserver_launch_info;
  // Make debugserver run in its own session so signals generated by special
  // terminal key sequences (^C) don't affect debugserver.
  debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);

  const std::weak_ptr<ProcessGDBRemote> this_wp =
      std::static_pointer_cast<ProcessGDBRemote>(shared_from_this());
  debugserver_launch_info.SetMonitorProcessCallback(
      std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3));
  debugserver_launch_info.SetUserID(process_info.GetUserID());

  FileSpec debugserver_path = GetDebugserverPath(*GetTarget().GetPlatform());

#if defined(__APPLE__)
  // On macOS 11, we need to support x86_64 applications translated to
  // arm64. We check whether a binary is translated and spawn the correct
  // debugserver accordingly.
  int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID,
               static_cast<int>(process_info.GetProcessID())};
  struct kinfo_proc processInfo;
  size_t bufsize = sizeof(processInfo);
  if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, &bufsize,
             NULL, 0) == 0 &&
      bufsize > 0) {
    if (processInfo.kp_proc.p_flag & P_TRANSLATED) {
      debugserver_path = FileSpec("/Library/Apple/usr/libexec/oah/debugserver");
    }
  }
#endif

  if (!FileSystem::Instance().Exists(debugserver_path))
    return Status::FromErrorString("could not find '" DEBUGSERVER_BASENAME
                                   "'. Please ensure it is properly installed "
                                   "and available in your PATH");

  debugserver_launch_info.SetExecutableFile(debugserver_path,
                                            /*add_exe_file_as_first_arg=*/true);

  llvm::Expected<Socket::Pair> socket_pair = Socket::CreatePair();
  if (!socket_pair)
    return Status::FromError(socket_pair.takeError());

  Status error;
  SharedSocket shared_socket(socket_pair->first.get(), error);
  if (error.Fail())
    return error;

  error = m_gdb_comm.StartDebugserverProcess(shared_socket.GetSendableFD(),
                                             debugserver_launch_info, nullptr);

  if (error.Fail()) {
    Log *log = GetLog(GDBRLog::Process);

    LLDB_LOGF(log, "failed to start debugserver process: %s",
              error.AsCString());
    return error;
  }

  m_debugserver_pid = debugserver_launch_info.GetProcessID();
  shared_socket.CompleteSending(m_debugserver_pid);

  // Our process spawned correctly, we can now set our connection to use
  // our end of the socket pair
  m_gdb_comm.SetConnection(std::make_unique<ConnectionFileDescriptor>(
      std::move(socket_pair->second)));
  StartAsyncThread();

  if (m_gdb_comm.IsConnected()) {
    // Finish the connection process by doing the handshake without
    // connecting (send NULL URL)
    error = ConnectToDebugserver("");
  } else {
    error = Status::FromErrorString("connection failed");
  }
  return error;
}

void ProcessGDBRemote::MonitorDebugserverProcess(
    std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t debugserver_pid,
    int signo,      // Zero for no signal
    int exit_status // Exit value of process if signal is zero
) {
  // "debugserver_pid" argument passed in is the process ID for debugserver
  // that we are tracking...
  Log *log = GetLog(GDBRLog::Process);

  LLDB_LOGF(log,
            "ProcessGDBRemote::%s(process_wp, pid=%" PRIu64
            ", signo=%i (0x%x), exit_status=%i)",
            __FUNCTION__, debugserver_pid, signo, signo, exit_status);

  std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock();
  LLDB_LOGF(log, "ProcessGDBRemote::%s(process = %p)", __FUNCTION__,
            static_cast<void *>(process_sp.get()));
  if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid)
    return;

  // Sleep for a half a second to make sure our inferior process has time to
  // set its exit status before we set it incorrectly when both the debugserver
  // and the inferior process shut down.
  std::this_thread::sleep_for(std::chrono::milliseconds(500));

  // If our process hasn't yet exited, debugserver might have died. If the
  // process did exit, then we are reaping it.
  const StateType state = process_sp->GetState();

  if (state != eStateInvalid && state != eStateUnloaded &&
      state != eStateExited && state != eStateDetached) {
    StreamString stream;
    if (signo == 0)
      stream.Format(DEBUGSERVER_BASENAME " died with an exit status of {0:x8}",
                    exit_status);
    else {
      llvm::StringRef signal_name =
          process_sp->GetUnixSignals()->GetSignalAsStringRef(signo);
      const char *format_str = DEBUGSERVER_BASENAME " died with signal {0}";
      if (!signal_name.empty())
        stream.Format(format_str, signal_name);
      else
        stream.Format(format_str, signo);
    }
    process_sp->SetExitStatus(-1, stream.GetString());
  }
  // Debugserver has exited we need to let our ProcessGDBRemote know that it no
  // longer has a debugserver instance
  process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
}

void ProcessGDBRemote::KillDebugserverProcess() {
  m_gdb_comm.Disconnect();
  if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) {
    Host::Kill(m_debugserver_pid, SIGINT);
    m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
  }
}

void ProcessGDBRemote::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance,
                                DebuggerInitialize);
}

void ProcessGDBRemote::DebuggerInitialize(Debugger &debugger) {
  if (!PluginManager::GetSettingForProcessPlugin(
          debugger, PluginProperties::GetSettingName())) {
    const bool is_global_setting = true;
    PluginManager::CreateSettingForProcessPlugin(
        debugger, GetGlobalPluginProperties().GetValueProperties(),
        "Properties for the gdb-remote process plug-in.", is_global_setting);
  }
}

bool ProcessGDBRemote::StartAsyncThread() {
  Log *log = GetLog(GDBRLog::Process);

  LLDB_LOGF(log, "ProcessGDBRemote::%s ()", __FUNCTION__);

  std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
  if (!m_async_thread.IsJoinable()) {
    // Create a thread that watches our internal state and controls which
    // events make it to clients (into the DCProcess event queue).

    llvm::Expected<HostThread> async_thread =
        ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>", [this] {
          return ProcessGDBRemote::AsyncThread();
        });
    if (!async_thread) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Host), async_thread.takeError(),
                     "failed to launch host thread: {0}");
      return false;
    }
    m_async_thread = *async_thread;
  } else
    LLDB_LOGF(log,
              "ProcessGDBRemote::%s () - Called when Async thread was "
              "already running.",
              __FUNCTION__);

  return m_async_thread.IsJoinable();
}

void ProcessGDBRemote::StopAsyncThread() {
  Log *log = GetLog(GDBRLog::Process);

  LLDB_LOGF(log, "ProcessGDBRemote::%s ()", __FUNCTION__);

  std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
  if (m_async_thread.IsJoinable()) {
    m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit);

    //  This will shut down the async thread.
    m_gdb_comm.Disconnect(); // Disconnect from the debug server.

    // Stop the stdio thread
    m_async_thread.Join(nullptr);
    m_async_thread.Reset();
  } else
    LLDB_LOGF(
        log,
        "ProcessGDBRemote::%s () - Called when Async thread was not running.",
        __FUNCTION__);
}

thread_result_t ProcessGDBRemote::AsyncThread() {
  Log *log = GetLog(GDBRLog::Process);
  LLDB_LOGF(log, "ProcessGDBRemote::%s(pid = %" PRIu64 ") thread starting...",
            __FUNCTION__, GetID());

  EventSP event_sp;

  // We need to ignore any packets that come in after we have
  // have decided the process has exited.  There are some
  // situations, for instance when we try to interrupt a running
  // process and the interrupt fails, where another packet might
  // get delivered after we've decided to give up on the process.
  // But once we've decided we are done with the process we will
  // not be in a state to do anything useful with new packets.
  // So it is safer to simply ignore any remaining packets by
  // explicitly checking for eStateExited before reentering the
  // fetch loop.

  bool done = false;
  while (!done && GetPrivateState() != eStateExited) {
    LLDB_LOGF(log,
              "ProcessGDBRemote::%s(pid = %" PRIu64
              ") listener.WaitForEvent (NULL, event_sp)...",
              __FUNCTION__, GetID());

    if (m_async_listener_sp->GetEvent(event_sp, std::nullopt)) {
      const uint32_t event_type = event_sp->GetType();
      if (event_sp->BroadcasterIs(&m_async_broadcaster)) {
        LLDB_LOGF(log,
                  "ProcessGDBRemote::%s(pid = %" PRIu64
                  ") Got an event of type: %d...",
                  __FUNCTION__, GetID(), event_type);

        switch (event_type) {
        case eBroadcastBitAsyncContinue: {
          const EventDataBytes *continue_packet =
              EventDataBytes::GetEventDataFromEvent(event_sp.get());

          if (continue_packet) {
            const char *continue_cstr =
                (const char *)continue_packet->GetBytes();
            const size_t continue_cstr_len = continue_packet->GetByteSize();
            LLDB_LOGF(log,
                      "ProcessGDBRemote::%s(pid = %" PRIu64
                      ") got eBroadcastBitAsyncContinue: %s",
                      __FUNCTION__, GetID(), continue_cstr);

            if (::strstr(continue_cstr, "vAttach") == nullptr)
              SetPrivateState(eStateRunning);
            StringExtractorGDBRemote response;

            StateType stop_state =
                GetGDBRemote().SendContinuePacketAndWaitForResponse(
                    *this, *GetUnixSignals(),
                    llvm::StringRef(continue_cstr, continue_cstr_len),
                    GetInterruptTimeout(), response);

            // We need to immediately clear the thread ID list so we are sure
            // to get a valid list of threads. The thread ID list might be
            // contained within the "response", or the stop reply packet that
            // caused the stop. So clear it now before we give the stop reply
            // packet to the process using the
            // SetLastStopPacket()...
            ClearThreadIDList();

            switch (stop_state) {
            case eStateStopped:
            case eStateCrashed:
            case eStateSuspended:
              SetLastStopPacket(response);
              SetPrivateState(stop_state);
              break;

            case eStateExited: {
              SetLastStopPacket(response);
              ClearThreadIDList();
              response.SetFilePos(1);

              int exit_status = response.GetHexU8();
              std::string desc_string;
              if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';') {
                llvm::StringRef desc_str;
                llvm::StringRef desc_token;
                while (response.GetNameColonValue(desc_token, desc_str)) {
                  if (desc_token != "description")
                    continue;
                  StringExtractor extractor(desc_str);
                  extractor.GetHexByteString(desc_string);
                }
              }
              SetExitStatus(exit_status, desc_string.c_str());
              done = true;
              break;
            }
            case eStateInvalid: {
              // Check to see if we were trying to attach and if we got back
              // the "E87" error code from debugserver -- this indicates that
              // the process is not debuggable.  Return a slightly more
              // helpful error message about why the attach failed.
              if (::strstr(continue_cstr, "vAttach") != nullptr &&
                  response.GetError() == 0x87) {
                SetExitStatus(-1, "cannot attach to process due to "
                                  "System Integrity Protection");
              } else if (::strstr(continue_cstr, "vAttach") != nullptr &&
                         response.GetStatus().Fail()) {
                SetExitStatus(-1, response.GetStatus().AsCString());
              } else {
                SetExitStatus(-1, "lost connection");
              }
              done = true;
              break;
            }

            default:
              SetPrivateState(stop_state);
              break;
            }   // switch(stop_state)
          }     // if (continue_packet)
        }       // case eBroadcastBitAsyncContinue
        break;

        case eBroadcastBitAsyncThreadShouldExit:
          LLDB_LOGF(log,
                    "ProcessGDBRemote::%s(pid = %" PRIu64
                    ") got eBroadcastBitAsyncThreadShouldExit...",
                    __FUNCTION__, GetID());
          done = true;
          break;

        default:
          LLDB_LOGF(log,
                    "ProcessGDBRemote::%s(pid = %" PRIu64
                    ") got unknown event 0x%8.8x",
                    __FUNCTION__, GetID(), event_type);
          done = true;
          break;
        }
      }
    } else {
      LLDB_LOGF(log,
                "ProcessGDBRemote::%s(pid = %" PRIu64
                ") listener.WaitForEvent (NULL, event_sp) => false",
                __FUNCTION__, GetID());
      done = true;
    }
  }

  LLDB_LOGF(log, "ProcessGDBRemote::%s(pid = %" PRIu64 ") thread exiting...",
            __FUNCTION__, GetID());

  return {};
}

// uint32_t
// ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList
// &matches, std::vector<lldb::pid_t> &pids)
//{
//    // If we are planning to launch the debugserver remotely, then we need to
//    fire up a debugserver
//    // process and ask it for the list of processes. But if we are local, we
//    can let the Host do it.
//    if (m_local_debugserver)
//    {
//        return Host::ListProcessesMatchingName (name, matches, pids);
//    }
//    else
//    {
//        // FIXME: Implement talking to the remote debugserver.
//        return 0;
//    }
//
//}
//
bool ProcessGDBRemote::NewThreadNotifyBreakpointHit(
    void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
    lldb::user_id_t break_loc_id) {
  // I don't think I have to do anything here, just make sure I notice the new
  // thread when it starts to
  // run so I can stop it if that's what I want to do.
  Log *log = GetLog(LLDBLog::Step);
  LLDB_LOGF(log, "Hit New Thread Notification breakpoint.");
  return false;
}

Status ProcessGDBRemote::UpdateAutomaticSignalFiltering() {
  Log *log = GetLog(GDBRLog::Process);
  LLDB_LOG(log, "Check if need to update ignored signals");

  // QPassSignals package is not supported by the server, there is no way we
  // can ignore any signals on server side.
  if (!m_gdb_comm.GetQPassSignalsSupported())
    return Status();

  // No signals, nothing to send.
  if (m_unix_signals_sp == nullptr)
    return Status();

  // Signals' version hasn't changed, no need to send anything.
  uint64_t new_signals_version = m_unix_signals_sp->GetVersion();
  if (new_signals_version == m_last_signals_version) {
    LLDB_LOG(log, "Signals' version hasn't changed. version={0}",
             m_last_signals_version);
    return Status();
  }

  auto signals_to_ignore =
      m_unix_signals_sp->GetFilteredSignals(false, false, false);
  Status error = m_gdb_comm.SendSignalsToIgnore(signals_to_ignore);

  LLDB_LOG(log,
           "Signals' version changed. old version={0}, new version={1}, "
           "signals ignored={2}, update result={3}",
           m_last_signals_version, new_signals_version,
           signals_to_ignore.size(), error);

  if (error.Success())
    m_last_signals_version = new_signals_version;

  return error;
}

bool ProcessGDBRemote::StartNoticingNewThreads() {
  Log *log = GetLog(LLDBLog::Step);
  if (m_thread_create_bp_sp) {
    if (log && log->GetVerbose())
      LLDB_LOGF(log, "Enabled noticing new thread breakpoint.");
    m_thread_create_bp_sp->SetEnabled(true);
  } else {
    PlatformSP platform_sp(GetTarget().GetPlatform());
    if (platform_sp) {
      m_thread_create_bp_sp =
          platform_sp->SetThreadCreationBreakpoint(GetTarget());
      if (m_thread_create_bp_sp) {
        if (log && log->GetVerbose())
          LLDB_LOGF(
              log, "Successfully created new thread notification breakpoint %i",
              m_thread_create_bp_sp->GetID());
        m_thread_create_bp_sp->SetCallback(
            ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true);
      } else {
        LLDB_LOGF(log, "Failed to create new thread notification breakpoint.");
      }
    }
  }
  return m_thread_create_bp_sp.get() != nullptr;
}

bool ProcessGDBRemote::StopNoticingNewThreads() {
  Log *log = GetLog(LLDBLog::Step);
  if (log && log->GetVerbose())
    LLDB_LOGF(log, "Disabling new thread notification breakpoint.");

  if (m_thread_create_bp_sp)
    m_thread_create_bp_sp->SetEnabled(false);

  return true;
}

DynamicLoader *ProcessGDBRemote::GetDynamicLoader() {
  if (m_dyld_up.get() == nullptr)
    m_dyld_up.reset(DynamicLoader::FindPlugin(this, ""));
  return m_dyld_up.get();
}

Status ProcessGDBRemote::SendEventData(const char *data) {
  int return_value;
  bool was_supported;

  Status error;

  return_value = m_gdb_comm.SendLaunchEventDataPacket(data, &was_supported);
  if (return_value != 0) {
    if (!was_supported)
      error = Status::FromErrorString(
          "Sending events is not supported for this process.");
    else
      error = Status::FromErrorStringWithFormat("Error sending event data: %d.",
                                                return_value);
  }
  return error;
}

DataExtractor ProcessGDBRemote::GetAuxvData() {
  DataBufferSP buf;
  if (m_gdb_comm.GetQXferAuxvReadSupported()) {
    llvm::Expected<std::string> response = m_gdb_comm.ReadExtFeature("auxv", "");
    if (response)
      buf = std::make_shared<DataBufferHeap>(response->c_str(),
                                             response->length());
    else
      LLDB_LOG_ERROR(GetLog(GDBRLog::Process), response.takeError(), "{0}");
  }
  return DataExtractor(buf, GetByteOrder(), GetAddressByteSize());
}

StructuredData::ObjectSP
ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) {
  StructuredData::ObjectSP object_sp;

  if (m_gdb_comm.GetThreadExtendedInfoSupported()) {
    StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
    SystemRuntime *runtime = GetSystemRuntime();
    if (runtime) {
      runtime->AddThreadExtendedInfoPacketHints(args_dict);
    }
    args_dict->GetAsDictionary()->AddIntegerItem("thread", tid);

    StreamString packet;
    packet << "jThreadExtendedInfo:";
    args_dict->Dump(packet, false);

    // FIXME the final character of a JSON dictionary, '}', is the escape
    // character in gdb-remote binary mode.  lldb currently doesn't escape
    // these characters in its packet output -- so we add the quoted version of
    // the } character here manually in case we talk to a debugserver which un-
    // escapes the characters at packet read time.
    packet << (char)(0x7d ^ 0x20);

    StringExtractorGDBRemote response;
    response.SetResponseValidatorToJSON();
    if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) ==
        GDBRemoteCommunication::PacketResult::Success) {
      StringExtractorGDBRemote::ResponseType response_type =
          response.GetResponseType();
      if (response_type == StringExtractorGDBRemote::eResponse) {
        if (!response.Empty()) {
          object_sp = StructuredData::ParseJSON(response.GetStringRef());
        }
      }
    }
  }
  return object_sp;
}

StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos(
    lldb::addr_t image_list_address, lldb::addr_t image_count) {

  StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
  args_dict->GetAsDictionary()->AddIntegerItem("image_list_address",
                                               image_list_address);
  args_dict->GetAsDictionary()->AddIntegerItem("image_count", image_count);

  return GetLoadedDynamicLibrariesInfos_sender(args_dict);
}

StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos() {
  StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());

  args_dict->GetAsDictionary()->AddBooleanItem("fetch_all_solibs", true);

  return GetLoadedDynamicLibrariesInfos_sender(args_dict);
}

StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos(
    const std::vector<lldb::addr_t> &load_addresses) {
  StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
  StructuredData::ArraySP addresses(new StructuredData::Array);

  for (auto addr : load_addresses)
    addresses->AddIntegerItem(addr);

  args_dict->GetAsDictionary()->AddItem("solib_addresses", addresses);

  return GetLoadedDynamicLibrariesInfos_sender(args_dict);
}

StructuredData::ObjectSP
ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender(
    StructuredData::ObjectSP args_dict) {
  StructuredData::ObjectSP object_sp;

  if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported()) {
    // Scope for the scoped timeout object
    GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm,
                                                  std::chrono::seconds(10));

    StreamString packet;
    packet << "jGetLoadedDynamicLibrariesInfos:";
    args_dict->Dump(packet, false);

    // FIXME the final character of a JSON dictionary, '}', is the escape
    // character in gdb-remote binary mode.  lldb currently doesn't escape
    // these characters in its packet output -- so we add the quoted version of
    // the } character here manually in case we talk to a debugserver which un-
    // escapes the characters at packet read time.
    packet << (char)(0x7d ^ 0x20);

    StringExtractorGDBRemote response;
    response.SetResponseValidatorToJSON();
    if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) ==
        GDBRemoteCommunication::PacketResult::Success) {
      StringExtractorGDBRemote::ResponseType response_type =
          response.GetResponseType();
      if (response_type == StringExtractorGDBRemote::eResponse) {
        if (!response.Empty()) {
          object_sp = StructuredData::ParseJSON(response.GetStringRef());
        }
      }
    }
  }
  return object_sp;
}

StructuredData::ObjectSP ProcessGDBRemote::GetDynamicLoaderProcessState() {
  StructuredData::ObjectSP object_sp;
  StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());

  if (m_gdb_comm.GetDynamicLoaderProcessStateSupported()) {
    StringExtractorGDBRemote response;
    response.SetResponseValidatorToJSON();
    if (m_gdb_comm.SendPacketAndWaitForResponse("jGetDyldProcessState",
                                                response) ==
        GDBRemoteCommunication::PacketResult::Success) {
      StringExtractorGDBRemote::ResponseType response_type =
          response.GetResponseType();
      if (response_type == StringExtractorGDBRemote::eResponse) {
        if (!response.Empty()) {
          object_sp = StructuredData::ParseJSON(response.GetStringRef());
        }
      }
    }
  }
  return object_sp;
}

StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() {
  std::lock_guard<std::mutex> guard(m_shared_cache_info_mutex);
  StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());

  if (m_shared_cache_info_sp || !m_gdb_comm.GetSharedCacheInfoSupported())
    return m_shared_cache_info_sp;

  StreamString packet;
  packet << "jGetSharedCacheInfo:";
  args_dict->Dump(packet, false);

  StringExtractorGDBRemote response;
  response.SetResponseValidatorToJSON();
  if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) ==
      GDBRemoteCommunication::PacketResult::Success) {
    StringExtractorGDBRemote::ResponseType response_type =
        response.GetResponseType();
    if (response_type == StringExtractorGDBRemote::eResponse) {
      if (response.Empty())
        return {};
      StructuredData::ObjectSP response_sp =
          StructuredData::ParseJSON(response.GetStringRef());
      if (!response_sp)
        return {};
      StructuredData::Dictionary *dict = response_sp->GetAsDictionary();
      if (!dict)
        return {};
      if (!dict->HasKey("shared_cache_uuid"))
        return {};
      llvm::StringRef uuid_str;
      if (!dict->GetValueForKeyAsString("shared_cache_uuid", uuid_str, "") ||
          uuid_str == "00000000-0000-0000-0000-000000000000")
        return {};
      if (dict->HasKey("shared_cache_path")) {
        UUID uuid;
        uuid.SetFromStringRef(uuid_str);
        FileSpec sc_path(
            dict->GetValueForKey("shared_cache_path")->GetStringValue());

        SymbolSharedCacheUse sc_mode =
            ModuleList::GetGlobalModuleListProperties()
                .GetSharedCacheBinaryLoading();

        if (sc_mode == eSymbolSharedCacheUseHostAndInferiorSharedCache ||
            sc_mode == eSymbolSharedCacheUseInferiorSharedCacheOnly) {
          // Attempt to open the shared cache at sc_path, and
          // if the uuid matches, index all the files.
          HostInfo::SharedCacheIndexFiles(sc_path, uuid, sc_mode);
        }
      }
      m_shared_cache_info_sp = response_sp;
    }
  }
  return m_shared_cache_info_sp;
}

Status ProcessGDBRemote::ConfigureStructuredData(
    llvm::StringRef type_name, const StructuredData::ObjectSP &config_sp) {
  return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp);
}

// Establish the largest memory read/write payloads we should use. If the
// remote stub has a max packet size, stay under that size.
//
// If the remote stub's max packet size is crazy large, use a reasonable
// largeish default.
//
// If the remote stub doesn't advertise a max packet size, use a conservative
// default.

void ProcessGDBRemote::GetMaxMemorySize() {
  const uint64_t reasonable_largeish_default = 128 * 1024;
  const uint64_t conservative_default = 512;

  if (m_max_memory_size == 0) {
    uint64_t stub_max_size = m_gdb_comm.GetRemoteMaxPacketSize();
    if (stub_max_size != UINT64_MAX && stub_max_size != 0) {
      // Save the stub's claimed maximum packet size
      m_remote_stub_max_memory_size = stub_max_size;

      // Even if the stub says it can support ginormous packets, don't exceed
      // our reasonable largeish default packet size.
      if (stub_max_size > reasonable_largeish_default) {
        stub_max_size = reasonable_largeish_default;
      }

      // Memory packet have other overheads too like Maddr,size:#NN Instead of
      // calculating the bytes taken by size and addr every time, we take a
      // maximum guess here.
      if (stub_max_size > 70)
        stub_max_size -= 32 + 32 + 6;
      else {
        // In unlikely scenario that max packet size is less then 70, we will
        // hope that data being written is small enough to fit.
        Log *log(GetLog(GDBRLog::Comm | GDBRLog::Memory));
        if (log)
          log->Warning("Packet size is too small. "
                       "LLDB may face problems while writing memory");
      }

      m_max_memory_size = stub_max_size;
    } else {
      m_max_memory_size = conservative_default;
    }
  }
}

void ProcessGDBRemote::SetUserSpecifiedMaxMemoryTransferSize(
    uint64_t user_specified_max) {
  if (user_specified_max != 0) {
    GetMaxMemorySize();

    if (m_remote_stub_max_memory_size != 0) {
      if (m_remote_stub_max_memory_size < user_specified_max) {
        m_max_memory_size = m_remote_stub_max_memory_size; // user specified a
                                                           // packet size too
                                                           // big, go as big
        // as the remote stub says we can go.
      } else {
        m_max_memory_size = user_specified_max; // user's packet size is good
      }
    } else {
      m_max_memory_size =
          user_specified_max; // user's packet size is probably fine
    }
  }
}

bool ProcessGDBRemote::GetModuleSpec(const FileSpec &module_file_spec,
                                     const ArchSpec &arch,
                                     ModuleSpec &module_spec) {
  Log *log = GetLog(LLDBLog::Platform);

  const ModuleCacheKey key(module_file_spec.GetPath(),
                           arch.GetTriple().getTriple());
  auto cached = m_cached_module_specs.find(key);
  if (cached != m_cached_module_specs.end()) {
    module_spec = cached->second;
    return bool(module_spec);
  }

  if (!m_gdb_comm.GetModuleInfo(module_file_spec, arch, module_spec)) {
    LLDB_LOGF(log, "ProcessGDBRemote::%s - failed to get module info for %s:%s",
              __FUNCTION__, module_file_spec.GetPath().c_str(),
              arch.GetTriple().getTriple().c_str());
    return false;
  }

  if (log) {
    StreamString stream;
    module_spec.Dump(stream);
    LLDB_LOGF(log, "ProcessGDBRemote::%s - got module info for (%s:%s) : %s",
              __FUNCTION__, module_file_spec.GetPath().c_str(),
              arch.GetTriple().getTriple().c_str(), stream.GetData());
  }

  m_cached_module_specs[key] = module_spec;
  return true;
}

void ProcessGDBRemote::PrefetchModuleSpecs(
    llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) {
  auto module_specs = m_gdb_comm.GetModulesInfo(module_file_specs, triple);
  if (module_specs) {
    for (const FileSpec &spec : module_file_specs)
      m_cached_module_specs[ModuleCacheKey(spec.GetPath(),
                                           triple.getTriple())] = ModuleSpec();
    for (const ModuleSpec &spec : *module_specs)
      m_cached_module_specs[ModuleCacheKey(spec.GetFileSpec().GetPath(),
                                           triple.getTriple())] = spec;
  }
}

llvm::VersionTuple ProcessGDBRemote::GetHostOSVersion() {
  return m_gdb_comm.GetOSVersion();
}

llvm::VersionTuple ProcessGDBRemote::GetHostMacCatalystVersion() {
  return m_gdb_comm.GetMacCatalystVersion();
}

namespace {

typedef std::vector<std::string> stringVec;

typedef std::vector<struct GdbServerRegisterInfo> GDBServerRegisterVec;
struct RegisterSetInfo {
  ConstString name;
};

typedef std::map<uint32_t, RegisterSetInfo> RegisterSetMap;

struct GdbServerTargetInfo {
  std::string arch;
  std::string osabi;
  stringVec includes;
  RegisterSetMap reg_set_map;
};

static FieldEnum::Enumerators ParseEnumEvalues(const XMLNode &enum_node) {
  Log *log(GetLog(GDBRLog::Process));
  // We will use the last instance of each value. Also we preserve the order
  // of declaration in the XML, as it may not be numerical.
  // For example, hardware may initially release with two states that software
  // can read from a register field:
  // 0 = startup, 1 = running
  // If in a future hardware release, the designers added a pre-startup state:
  // 0 = startup, 1 = running, 2 = pre-startup
  // Now it makes more sense to list them in this logical order as opposed to
  // numerical order:
  // 2 = pre-startup, 1 = startup, 0 = startup
  // This only matters for "register info" but let's trust what the server
  // chose regardless.
  std::map<uint64_t, FieldEnum::Enumerator> enumerators;

  enum_node.ForEachChildElementWithName(
      "evalue", [&enumerators, &log](const XMLNode &enumerator_node) {
        std::optional<llvm::StringRef> name;
        std::optional<uint64_t> value;

        enumerator_node.ForEachAttribute(
            [&name, &value, &log](const llvm::StringRef &attr_name,
                                  const llvm::StringRef &attr_value) {
              if (attr_name == "name") {
                if (attr_value.size())
                  name = attr_value;
                else
                  LLDB_LOG(log, "ProcessGDBRemote::ParseEnumEvalues "
                                "Ignoring empty name in evalue");
              } else if (attr_name == "value") {
                uint64_t parsed_value = 0;
                if (llvm::to_integer(attr_value, parsed_value))
                  value = parsed_value;
                else
                  LLDB_LOG(log,
                           "ProcessGDBRemote::ParseEnumEvalues "
                           "Invalid value \"{0}\" in "
                           "evalue",
                           attr_value.data());
              } else
                LLDB_LOG(log,
                         "ProcessGDBRemote::ParseEnumEvalues Ignoring "
                         "unknown attribute "
                         "\"{0}\" in evalue",
                         attr_name.data());

              // Keep walking attributes.
              return true;
            });

        if (value && name)
          enumerators.insert_or_assign(
              *value, FieldEnum::Enumerator(*value, name->str()));

        // Find all evalue elements.
        return true;
      });

  FieldEnum::Enumerators final_enumerators;
  for (auto [_, enumerator] : enumerators)
    final_enumerators.push_back(enumerator);

  return final_enumerators;
}

static void
ParseEnums(XMLNode feature_node,
           llvm::StringMap<std::unique_ptr<FieldEnum>> &registers_enum_types) {
  Log *log(GetLog(GDBRLog::Process));

  // The top level element is "<enum...".
  feature_node.ForEachChildElementWithName(
      "enum", [log, &registers_enum_types](const XMLNode &enum_node) {
        std::string id;

        enum_node.ForEachAttribute([&id](const llvm::StringRef &attr_name,
                                         const llvm::StringRef &attr_value) {
          if (attr_name == "id")
            id = attr_value;

          // There is also a "size" attribute that is supposed to be the size in
          // bytes of the register this applies to. However:
          // * LLDB doesn't need this information.
          // * It  is difficult to verify because you have to wait until the
          //   enum is applied to a field.
          //
          // So we will emit this attribute in XML for GDB's sake, but will not
          // bother ingesting it.

          // Walk all attributes.
          return true;
        });

        if (!id.empty()) {
          FieldEnum::Enumerators enumerators = ParseEnumEvalues(enum_node);
          if (!enumerators.empty()) {
            LLDB_LOG(log,
                     "ProcessGDBRemote::ParseEnums Found enum type \"{0}\"",
                     id);
            registers_enum_types.insert_or_assign(
                id, std::make_unique<FieldEnum>(id, enumerators));
          }
        }

        // Find all <enum> elements.
        return true;
      });
}

static std::vector<RegisterFlags::Field> ParseFlagsFields(
    XMLNode flags_node, unsigned size,
    const llvm::StringMap<std::unique_ptr<FieldEnum>> &registers_enum_types) {
  Log *log(GetLog(GDBRLog::Process));
  const unsigned max_start_bit = size * 8 - 1;

  // Process the fields of this set of flags.
  std::vector<RegisterFlags::Field> fields;
  flags_node.ForEachChildElementWithName("field", [&fields, max_start_bit, &log,
                                                   &registers_enum_types](
                                                      const XMLNode
                                                          &field_node) {
    std::optional<llvm::StringRef> name;
    std::optional<unsigned> start;
    std::optional<unsigned> end;
    std::optional<llvm::StringRef> type;

    field_node.ForEachAttribute([&name, &start, &end, &type, max_start_bit,
                                 &log](const llvm::StringRef &attr_name,
                                       const llvm::StringRef &attr_value) {
      // Note that XML in general requires that each of these attributes only
      // appears once, so we don't have to handle that here.
      if (attr_name == "name") {
        LLDB_LOG(
            log,
            "ProcessGDBRemote::ParseFlagsFields Found field node name \"{0}\"",
            attr_value.data());
        name = attr_value;
      } else if (attr_name == "start") {
        unsigned parsed_start = 0;
        if (llvm::to_integer(attr_value, parsed_start)) {
          if (parsed_start > max_start_bit) {
            LLDB_LOG(log,
                     "ProcessGDBRemote::ParseFlagsFields Invalid start {0} in "
                     "field node, "
                     "cannot be > {1}",
                     parsed_start, max_start_bit);
          } else
            start = parsed_start;
        } else {
          LLDB_LOG(
              log,
              "ProcessGDBRemote::ParseFlagsFields Invalid start \"{0}\" in "
              "field node",
              attr_value.data());
        }
      } else if (attr_name == "end") {
        unsigned parsed_end = 0;
        if (llvm::to_integer(attr_value, parsed_end))
          if (parsed_end > max_start_bit) {
            LLDB_LOG(log,
                     "ProcessGDBRemote::ParseFlagsFields Invalid end {0} in "
                     "field node, "
                     "cannot be > {1}",
                     parsed_end, max_start_bit);
          } else
            end = parsed_end;
        else {
          LLDB_LOG(log,
                   "ProcessGDBRemote::ParseFlagsFields Invalid end \"{0}\" in "
                   "field node",
                   attr_value.data());
        }
      } else if (attr_name == "type") {
        type = attr_value;
      } else {
        LLDB_LOG(
            log,
            "ProcessGDBRemote::ParseFlagsFields Ignoring unknown attribute "
            "\"{0}\" in field node",
            attr_name.data());
      }

      return true; // Walk all attributes of the field.
    });

    if (name && start && end) {
      if (*start > *end)
        LLDB_LOG(
            log,
            "ProcessGDBRemote::ParseFlagsFields Start {0} > end {1} in field "
            "\"{2}\", ignoring",
            *start, *end, name->data());
      else {
        if (RegisterFlags::Field::GetSizeInBits(*start, *end) > 64)
          LLDB_LOG(log,
                   "ProcessGDBRemote::ParseFlagsFields Ignoring field \"{2}\" "
                   "that has "
                   "size > 64 bits, this is not supported",
                   name->data());
        else {
          // A field's type may be set to the name of an enum type.
          const FieldEnum *enum_type = nullptr;
          if (type && !type->empty()) {
            auto found = registers_enum_types.find(*type);
            if (found != registers_enum_types.end()) {
              enum_type = found->second.get();

              // No enumerator can exceed the range of the field itself.
              uint64_t max_value =
                  RegisterFlags::Field::GetMaxValue(*start, *end);
              for (const auto &enumerator : enum_type->GetEnumerators()) {
                if (enumerator.m_value > max_value) {
                  enum_type = nullptr;
                  LLDB_LOG(
                      log,
                      "ProcessGDBRemote::ParseFlagsFields In enum \"{0}\" "
                      "evalue \"{1}\" with value {2} exceeds the maximum value "
                      "of field \"{3}\" ({4}), ignoring enum",
                      type->data(), enumerator.m_name, enumerator.m_value,
                      name->data(), max_value);
                  break;
                }
              }
            } else {
              LLDB_LOG(log,
                       "ProcessGDBRemote::ParseFlagsFields Could not find type "
                       "\"{0}\" "
                       "for field \"{1}\", ignoring",
                       type->data(), name->data());
            }
          }

          fields.push_back(
              RegisterFlags::Field(name->str(), *start, *end, enum_type));
        }
      }
    }

    return true; // Iterate all "field" nodes.
  });
  return fields;
}

void ParseFlags(
    XMLNode feature_node,
    llvm::StringMap<std::unique_ptr<RegisterFlags>> &registers_flags_types,
    const llvm::StringMap<std::unique_ptr<FieldEnum>> &registers_enum_types) {
  Log *log(GetLog(GDBRLog::Process));

  feature_node.ForEachChildElementWithName(
      "flags",
      [&log, &registers_flags_types,
       &registers_enum_types](const XMLNode &flags_node) -> bool {
        LLDB_LOG(log, "ProcessGDBRemote::ParseFlags Found flags node \"{0}\"",
                 flags_node.GetAttributeValue("id").c_str());

        std::optional<llvm::StringRef> id;
        std::optional<unsigned> size;
        flags_node.ForEachAttribute(
            [&id, &size, &log](const llvm::StringRef &name,
                               const llvm::StringRef &value) {
              if (name == "id") {
                id = value;
              } else if (name == "size") {
                unsigned parsed_size = 0;
                if (llvm::to_integer(value, parsed_size))
                  size = parsed_size;
                else {
                  LLDB_LOG(log,
                           "ProcessGDBRemote::ParseFlags Invalid size \"{0}\" "
                           "in flags node",
                           value.data());
                }
              } else {
                LLDB_LOG(log,
                         "ProcessGDBRemote::ParseFlags Ignoring unknown "
                         "attribute \"{0}\" in flags node",
                         name.data());
              }
              return true; // Walk all attributes.
            });

        if (id && size) {
          // Process the fields of this set of flags.
          std::vector<RegisterFlags::Field> fields =
              ParseFlagsFields(flags_node, *size, registers_enum_types);
          if (fields.size()) {
            // Sort so that the fields with the MSBs are first.
            std::sort(fields.rbegin(), fields.rend());
            std::vector<RegisterFlags::Field>::const_iterator overlap =
                std::adjacent_find(fields.begin(), fields.end(),
                                   [](const RegisterFlags::Field &lhs,
                                      const RegisterFlags::Field &rhs) {
                                     return lhs.Overlaps(rhs);
                                   });

            // If no fields overlap, use them.
            if (overlap == fields.end()) {
              if (registers_flags_types.contains(*id)) {
                // In theory you could define some flag set, use it with a
                // register then redefine it. We do not know if anyone does
                // that, or what they would expect to happen in that case.
                //
                // LLDB chooses to take the first definition and ignore the rest
                // as waiting until everything has been processed is more
                // expensive and difficult. This means that pointers to flag
                // sets in the register info remain valid if later the flag set
                // is redefined. If we allowed redefinitions, LLDB would crash
                // when you tried to print a register that used the original
                // definition.
                LLDB_LOG(
                    log,
                    "ProcessGDBRemote::ParseFlags Definition of flags "
                    "\"{0}\" shadows "
                    "previous definition, using original definition instead.",
                    id->data());
              } else {
                registers_flags_types.insert_or_assign(
                    *id, std::make_unique<RegisterFlags>(id->str(), *size,
                                                         std::move(fields)));
              }
            } else {
              // If any fields overlap, ignore the whole set of flags.
              std::vector<RegisterFlags::Field>::const_iterator next =
                  std::next(overlap);
              LLDB_LOG(
                  log,
                  "ProcessGDBRemote::ParseFlags Ignoring flags because fields "
                  "{0} (start: {1} end: {2}) and {3} (start: {4} end: {5}) "
                  "overlap.",
                  overlap->GetName().c_str(), overlap->GetStart(),
                  overlap->GetEnd(), next->GetName().c_str(), next->GetStart(),
                  next->GetEnd());
            }
          } else {
            LLDB_LOG(
                log,
                "ProcessGDBRemote::ParseFlags Ignoring definition of flags "
                "\"{0}\" because it contains no fields.",
                id->data());
          }
        }

        return true; // Keep iterating through all "flags" elements.
      });
}

bool ParseRegisters(
    XMLNode feature_node, GdbServerTargetInfo &target_info,
    std::vector<DynamicRegisterInfo::Register> &registers,
    llvm::StringMap<std::unique_ptr<RegisterFlags>> &registers_flags_types,
    llvm::StringMap<std::unique_ptr<FieldEnum>> &registers_enum_types) {
  if (!feature_node)
    return false;

  Log *log(GetLog(GDBRLog::Process));

  // Enums first because they are referenced by fields in the flags.
  ParseEnums(feature_node, registers_enum_types);
  for (const auto &enum_type : registers_enum_types)
    enum_type.second->DumpToLog(log);

  ParseFlags(feature_node, registers_flags_types, registers_enum_types);
  for (const auto &flags : registers_flags_types)
    flags.second->DumpToLog(log);

  feature_node.ForEachChildElementWithName(
      "reg",
      [&target_info, &registers, &registers_flags_types,
       log](const XMLNode &reg_node) -> bool {
        std::string gdb_group;
        std::string gdb_type;
        DynamicRegisterInfo::Register reg_info;
        bool encoding_set = false;
        bool format_set = false;

        // FIXME: we're silently ignoring invalid data here
        reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type,
                                   &encoding_set, &format_set, &reg_info,
                                   log](const llvm::StringRef &name,
                                        const llvm::StringRef &value) -> bool {
          if (name == "name") {
            reg_info.name.SetString(value);
          } else if (name == "bitsize") {
            if (llvm::to_integer(value, reg_info.byte_size))
              reg_info.byte_size =
                  llvm::divideCeil(reg_info.byte_size, CHAR_BIT);
          } else if (name == "type") {
            gdb_type = value.str();
          } else if (name == "group") {
            gdb_group = value.str();
          } else if (name == "regnum") {
            llvm::to_integer(value, reg_info.regnum_remote);
          } else if (name == "offset") {
            llvm::to_integer(value, reg_info.byte_offset);
          } else if (name == "altname") {
            reg_info.alt_name.SetString(value);
          } else if (name == "encoding") {
            encoding_set = true;
            reg_info.encoding = Args::StringToEncoding(value, eEncodingUint);
          } else if (name == "format") {
            format_set = true;
            if (!OptionArgParser::ToFormat(value.data(), reg_info.format,
                                           nullptr)
                     .Success())
              reg_info.format =
                  llvm::StringSwitch<lldb::Format>(value)
                      .Case("vector-sint8", eFormatVectorOfSInt8)
                      .Case("vector-uint8", eFormatVectorOfUInt8)
                      .Case("vector-sint16", eFormatVectorOfSInt16)
                      .Case("vector-uint16", eFormatVectorOfUInt16)
                      .Case("vector-sint32", eFormatVectorOfSInt32)
                      .Case("vector-uint32", eFormatVectorOfUInt32)
                      .Case("vector-float32", eFormatVectorOfFloat32)
                      .Case("vector-uint64", eFormatVectorOfUInt64)
                      .Case("vector-uint128", eFormatVectorOfUInt128)
                      .Default(eFormatInvalid);
          } else if (name == "group_id") {
            uint32_t set_id = UINT32_MAX;
            llvm::to_integer(value, set_id);
            RegisterSetMap::const_iterator pos =
                target_info.reg_set_map.find(set_id);
            if (pos != target_info.reg_set_map.end())
              reg_info.set_name = pos->second.name;
          } else if (name == "gcc_regnum" || name == "ehframe_regnum") {
            llvm::to_integer(value, reg_info.regnum_ehframe);
          } else if (name == "dwarf_regnum") {
            llvm::to_integer(value, reg_info.regnum_dwarf);
          } else if (name == "generic") {
            reg_info.regnum_generic = Args::StringToGenericRegister(value);
          } else if (name == "value_regnums") {
            SplitCommaSeparatedRegisterNumberString(value, reg_info.value_regs,
                                                    0);
          } else if (name == "invalidate_regnums") {
            SplitCommaSeparatedRegisterNumberString(
                value, reg_info.invalidate_regs, 0);
          } else {
            LLDB_LOGF(log,
                      "ProcessGDBRemote::ParseRegisters unhandled reg "
                      "attribute %s = %s",
                      name.data(), value.data());
          }
          return true; // Keep iterating through all attributes
        });

        if (!gdb_type.empty()) {
          // gdb_type could reference some flags type defined in XML.
          llvm::StringMap<std::unique_ptr<RegisterFlags>>::iterator it =
              registers_flags_types.find(gdb_type);
          if (it != registers_flags_types.end()) {
            auto flags_type = it->second.get();
            if (reg_info.byte_size == flags_type->GetSize())
              reg_info.flags_type = flags_type;
            else
              LLDB_LOGF(log,
                        "ProcessGDBRemote::ParseRegisters Size of register "
                        "flags %s (%d bytes) for "
                        "register %s does not match the register size (%d "
                        "bytes). Ignoring this set of flags.",
                        flags_type->GetID().c_str(), flags_type->GetSize(),
                        reg_info.name.AsCString(), reg_info.byte_size);
          }

          // There's a slim chance that the gdb_type name is both a flags type
          // and a simple type. Just in case, look for that too (setting both
          // does no harm).
          if (!gdb_type.empty() && !(encoding_set || format_set)) {
            if (llvm::StringRef(gdb_type).starts_with("int")) {
              reg_info.format = eFormatHex;
              reg_info.encoding = eEncodingUint;
            } else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") {
              reg_info.format = eFormatAddressInfo;
              reg_info.encoding = eEncodingUint;
            } else if (gdb_type == "float" || gdb_type == "ieee_single" ||
                       gdb_type == "ieee_double") {
              reg_info.format = eFormatFloat;
              reg_info.encoding = eEncodingIEEE754;
            } else if (gdb_type == "aarch64v" ||
                       llvm::StringRef(gdb_type).starts_with("vec") ||
                       gdb_type == "i387_ext" || gdb_type == "uint128" ||
                       reg_info.byte_size > 16) {
              // lldb doesn't handle 128-bit uints correctly (for ymm*h), so
              // treat them as vector (similarly to xmm/ymm).
              // We can fall back to handling anything else <= 128 bit as an
              // unsigned integer, more than that, call it a vector of bytes.
              // This can happen if we don't recognise the type for AArc64 SVE
              // registers.
              reg_info.format = eFormatVectorOfUInt8;
              reg_info.encoding = eEncodingVector;
            } else {
              LLDB_LOGF(
                  log,
                  "ProcessGDBRemote::ParseRegisters Could not determine lldb"
                  "format and encoding for gdb type %s",
                  gdb_type.c_str());
            }
          }
        }

        // Only update the register set name if we didn't get a "reg_set"
        // attribute. "set_name" will be empty if we didn't have a "reg_set"
        // attribute.
        if (!reg_info.set_name) {
          if (!gdb_group.empty()) {
            reg_info.set_name.SetCString(gdb_group.c_str());
          } else {
            // If no register group name provided anywhere,
            // we'll create a 'general' register set
            reg_info.set_name.SetCString("general");
          }
        }

        if (reg_info.byte_size == 0) {
          LLDB_LOGF(log,
                    "ProcessGDBRemote::%s Skipping zero bitsize register %s",
                    __FUNCTION__, reg_info.name.AsCString());
        } else
          registers.push_back(reg_info);

        return true; // Keep iterating through all "reg" elements
      });
  return true;
}

} // namespace

// This method fetches a register description feature xml file from
// the remote stub and adds registers/register groupsets/architecture
// information to the current process.  It will call itself recursively
// for nested register definition files.  It returns true if it was able
// to fetch and parse an xml file.
bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess(
    ArchSpec &arch_to_use, std::string xml_filename,
    std::vector<DynamicRegisterInfo::Register> &registers) {
  // request the target xml file
  llvm::Expected<std::string> raw = m_gdb_comm.ReadExtFeature("features", xml_filename);
  if (errorToBool(raw.takeError()))
    return false;

  XMLDocument xml_document;

  if (xml_document.ParseMemory(raw->c_str(), raw->size(),
                               xml_filename.c_str())) {
    GdbServerTargetInfo target_info;
    std::vector<XMLNode> feature_nodes;

    // The top level feature XML file will start with a <target> tag.
    XMLNode target_node = xml_document.GetRootElement("target");
    if (target_node) {
      target_node.ForEachChildElement([&target_info, &feature_nodes](
                                          const XMLNode &node) -> bool {
        llvm::StringRef name = node.GetName();
        if (name == "architecture") {
          node.GetElementText(target_info.arch);
        } else if (name == "osabi") {
          node.GetElementText(target_info.osabi);
        } else if (name == "xi:include" || name == "include") {
          std::string href = node.GetAttributeValue("href");
          if (!href.empty())
            target_info.includes.push_back(href);
        } else if (name == "feature") {
          feature_nodes.push_back(node);
        } else if (name == "groups") {
          node.ForEachChildElementWithName(
              "group", [&target_info](const XMLNode &node) -> bool {
                uint32_t set_id = UINT32_MAX;
                RegisterSetInfo set_info;

                node.ForEachAttribute(
                    [&set_id, &set_info](const llvm::StringRef &name,
                                         const llvm::StringRef &value) -> bool {
                      // FIXME: we're silently ignoring invalid data here
                      if (name == "id")
                        llvm::to_integer(value, set_id);
                      if (name == "name")
                        set_info.name = ConstString(value);
                      return true; // Keep iterating through all attributes
                    });

                if (set_id != UINT32_MAX)
                  target_info.reg_set_map[set_id] = set_info;
                return true; // Keep iterating through all "group" elements
              });
        }
        return true; // Keep iterating through all children of the target_node
      });
    } else {
      // In an included XML feature file, we're already "inside" the <target>
      // tag of the initial XML file; this included file will likely only have
      // a <feature> tag.  Need to check for any more included files in this
      // <feature> element.
      XMLNode feature_node = xml_document.GetRootElement("feature");
      if (feature_node) {
        feature_nodes.push_back(feature_node);
        feature_node.ForEachChildElement([&target_info](
                                        const XMLNode &node) -> bool {
          llvm::StringRef name = node.GetName();
          if (name == "xi:include" || name == "include") {
            std::string href = node.GetAttributeValue("href");
            if (!href.empty())
              target_info.includes.push_back(href);
            }
            return true;
          });
      }
    }

    // gdbserver does not implement the LLDB packets used to determine host
    // or process architecture.  If that is the case, attempt to use
    // the <architecture/> field from target.xml, e.g.:
    //
    //   <architecture>i386:x86-64</architecture> (seen from VMWare ESXi)
    //   <architecture>arm</architecture> (seen from Segger JLink on unspecified
    //   arm board)
    if (!arch_to_use.IsValid() && !target_info.arch.empty()) {
      // We don't have any information about vendor or OS.
      arch_to_use.SetTriple(llvm::StringSwitch<std::string>(target_info.arch)
                                .Case("i386:x86-64", "x86_64")
                                .Case("riscv:rv64", "riscv64")
                                .Case("riscv:rv32", "riscv32")
                                .Default(target_info.arch) +
                            "--");

      if (arch_to_use.IsValid())
        GetTarget().MergeArchitecture(arch_to_use);
    }

    if (arch_to_use.IsValid()) {
      for (auto &feature_node : feature_nodes) {
        ParseRegisters(feature_node, target_info, registers,
                       m_registers_flags_types, m_registers_enum_types);
      }

      for (const auto &include : target_info.includes) {
        GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, include,
                                              registers);
      }
    }
  } else {
    return false;
  }
  return true;
}

void ProcessGDBRemote::AddRemoteRegisters(
    std::vector<DynamicRegisterInfo::Register> &registers,
    const ArchSpec &arch_to_use) {
  std::map<uint32_t, uint32_t> remote_to_local_map;
  uint32_t remote_regnum = 0;
  for (auto it : llvm::enumerate(registers)) {
    DynamicRegisterInfo::Register &remote_reg_info = it.value();

    // Assign successive remote regnums if missing.
    if (remote_reg_info.regnum_remote == LLDB_INVALID_REGNUM)
      remote_reg_info.regnum_remote = remote_regnum;

    // Create a mapping from remote to local regnos.
    remote_to_local_map[remote_reg_info.regnum_remote] = it.index();

    remote_regnum = remote_reg_info.regnum_remote + 1;
  }

  for (DynamicRegisterInfo::Register &remote_reg_info : registers) {
    auto proc_to_lldb = [&remote_to_local_map](uint32_t process_regnum) {
      auto lldb_regit = remote_to_local_map.find(process_regnum);
      return lldb_regit != remote_to_local_map.end() ? lldb_regit->second
                                                     : LLDB_INVALID_REGNUM;
    };

    llvm::transform(remote_reg_info.value_regs,
                    remote_reg_info.value_regs.begin(), proc_to_lldb);
    llvm::transform(remote_reg_info.invalidate_regs,
                    remote_reg_info.invalidate_regs.begin(), proc_to_lldb);
  }

  // Don't use Process::GetABI, this code gets called from DidAttach, and
  // in that context we haven't set the Target's architecture yet, so the
  // ABI is also potentially incorrect.
  if (ABISP abi_sp = ABI::FindPlugin(shared_from_this(), arch_to_use))
    abi_sp->AugmentRegisterInfo(registers);

  m_register_info_sp->SetRegisterInfo(std::move(registers), arch_to_use);
}

// query the target of gdb-remote for extended target information returns
// true on success (got register definitions), false on failure (did not).
llvm::Error ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
  // If the remote does not offer XML, does not matter if we would have been
  // able to parse it.
  if (!m_gdb_comm.GetQXferFeaturesReadSupported())
    return llvm::createStringError(
        llvm::inconvertibleErrorCode(),
        "the debug server does not support \"qXfer:features:read\"");

  if (!XMLDocument::XMLEnabled())
    return llvm::createStringError(
        llvm::inconvertibleErrorCode(),
        "the debug server supports \"qXfer:features:read\", but LLDB does not "
        "have XML parsing enabled (check LLLDB_ENABLE_LIBXML2)");

  // These hold register type information for the whole of target.xml.
  // target.xml may include further documents that
  // GetGDBServerRegisterInfoXMLAndProcess will recurse to fetch and process.
  // That's why we clear the cache here, and not in
  // GetGDBServerRegisterInfoXMLAndProcess. To prevent it being cleared on every
  // include read.
  m_registers_flags_types.clear();
  m_registers_enum_types.clear();
  std::vector<DynamicRegisterInfo::Register> registers;
  if (GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, "target.xml",
                                            registers) &&
      // Target XML is not required to include register information.
      !registers.empty())
    AddRemoteRegisters(registers, arch_to_use);

  return m_register_info_sp->GetNumRegisters() > 0
             ? llvm::ErrorSuccess()
             : llvm::createStringError(
                   llvm::inconvertibleErrorCode(),
                   "the debug server did not describe any registers");
}

llvm::Expected<LoadedModuleInfoList> ProcessGDBRemote::GetLoadedModuleList() {
  // Make sure LLDB has an XML parser it can use first
  if (!XMLDocument::XMLEnabled())
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "XML parsing not available");

  Log *log = GetLog(LLDBLog::Process);
  LLDB_LOGF(log, "ProcessGDBRemote::%s", __FUNCTION__);

  LoadedModuleInfoList list;
  GDBRemoteCommunicationClient &comm = m_gdb_comm;
  bool can_use_svr4 = GetGlobalPluginProperties().GetUseSVR4();

  // check that we have extended feature read support
  if (can_use_svr4 && comm.GetQXferLibrariesSVR4ReadSupported()) {
    // request the loaded library list
    llvm::Expected<std::string> raw = comm.ReadExtFeature("libraries-svr4", "");
    if (!raw)
      return raw.takeError();

    // parse the xml file in memory
    LLDB_LOGF(log, "parsing: %s", raw->c_str());
    XMLDocument doc;

    if (!doc.ParseMemory(raw->c_str(), raw->size(), "noname.xml"))
      return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                     "Error reading noname.xml");

    XMLNode root_element = doc.GetRootElement("library-list-svr4");
    if (!root_element)
      return llvm::createStringError(
          llvm::inconvertibleErrorCode(),
          "Error finding library-list-svr4 xml element");

    // main link map structure
    std::string main_lm = root_element.GetAttributeValue("main-lm");
    // FIXME: we're silently ignoring invalid data here
    if (!main_lm.empty())
      llvm::to_integer(main_lm, list.m_link_map);

    root_element.ForEachChildElementWithName(
        "library", [log, &list](const XMLNode &library) -> bool {
          LoadedModuleInfoList::LoadedModuleInfo module;

          // FIXME: we're silently ignoring invalid data here
          library.ForEachAttribute(
              [&module](const llvm::StringRef &name,
                        const llvm::StringRef &value) -> bool {
                uint64_t uint_value = LLDB_INVALID_ADDRESS;
                if (name == "name")
                  module.set_name(value.str());
                else if (name == "lm") {
                  // the address of the link_map struct.
                  llvm::to_integer(value, uint_value);
                  module.set_link_map(uint_value);
                } else if (name == "l_addr") {
                  // the displacement as read from the field 'l_addr' of the
                  // link_map struct.
                  llvm::to_integer(value, uint_value);
                  module.set_base(uint_value);
                  // base address is always a displacement, not an absolute
                  // value.
                  module.set_base_is_offset(true);
                } else if (name == "l_ld") {
                  // the memory address of the libraries PT_DYNAMIC section.
                  llvm::to_integer(value, uint_value);
                  module.set_dynamic(uint_value);
                }

                return true; // Keep iterating over all properties of "library"
              });

          if (log) {
            std::string name;
            lldb::addr_t lm = 0, base = 0, ld = 0;
            bool base_is_offset;

            module.get_name(name);
            module.get_link_map(lm);
            module.get_base(base);
            module.get_base_is_offset(base_is_offset);
            module.get_dynamic(ld);

            LLDB_LOGF(log,
                      "found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64
                      "[%s], ld:0x%08" PRIx64 ", name:'%s')",
                      lm, base, (base_is_offset ? "offset" : "absolute"), ld,
                      name.c_str());
          }

          list.add(module);
          return true; // Keep iterating over all "library" elements in the root
                       // node
        });

    if (log)
      LLDB_LOGF(log, "found %" PRId32 " modules in total",
                (int)list.m_list.size());
    return list;
  } else if (comm.GetQXferLibrariesReadSupported()) {
    // request the loaded library list
    llvm::Expected<std::string> raw = comm.ReadExtFeature("libraries", "");

    if (!raw)
      return raw.takeError();

    LLDB_LOGF(log, "parsing: %s", raw->c_str());
    XMLDocument doc;

    if (!doc.ParseMemory(raw->c_str(), raw->size(), "noname.xml"))
      return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                     "Error reading noname.xml");

    XMLNode root_element = doc.GetRootElement("library-list");
    if (!root_element)
      return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                     "Error finding library-list xml element");

    // FIXME: we're silently ignoring invalid data here
    root_element.ForEachChildElementWithName(
        "library", [log, &list](const XMLNode &library) -> bool {
          LoadedModuleInfoList::LoadedModuleInfo module;

          std::string name = library.GetAttributeValue("name");
          module.set_name(name);

          // The base address of a given library will be the address of its
          // first section. Most remotes send only one section for Windows
          // targets for example.
          const XMLNode &section =
              library.FindFirstChildElementWithName("section");
          std::string address = section.GetAttributeValue("address");
          uint64_t address_value = LLDB_INVALID_ADDRESS;
          llvm::to_integer(address, address_value);
          module.set_base(address_value);
          // These addresses are absolute values.
          module.set_base_is_offset(false);

          if (log) {
            std::string name;
            lldb::addr_t base = 0;
            bool base_is_offset;
            module.get_name(name);
            module.get_base(base);
            module.get_base_is_offset(base_is_offset);

            LLDB_LOGF(log, "found (base:0x%08" PRIx64 "[%s], name:'%s')", base,
                      (base_is_offset ? "offset" : "absolute"), name.c_str());
          }

          list.add(module);
          return true; // Keep iterating over all "library" elements in the root
                       // node
        });

    if (log)
      LLDB_LOGF(log, "found %" PRId32 " modules in total",
                (int)list.m_list.size());
    return list;
  } else {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "Remote libraries not supported");
  }
}

lldb::ModuleSP ProcessGDBRemote::LoadModuleAtAddress(const FileSpec &file,
                                                     lldb::addr_t link_map,
                                                     lldb::addr_t base_addr,
                                                     bool value_is_offset) {
  DynamicLoader *loader = GetDynamicLoader();
  if (!loader)
    return nullptr;

  return loader->LoadModuleAtAddress(file, link_map, base_addr,
                                     value_is_offset);
}

llvm::Error ProcessGDBRemote::LoadModules() {
  using lldb_private::process_gdb_remote::ProcessGDBRemote;

  // request a list of loaded libraries from GDBServer
  llvm::Expected<LoadedModuleInfoList> module_list = GetLoadedModuleList();
  if (!module_list)
    return module_list.takeError();

  // get a list of all the modules
  ModuleList new_modules;

  for (LoadedModuleInfoList::LoadedModuleInfo &modInfo : module_list->m_list) {
    std::string mod_name;
    lldb::addr_t mod_base;
    lldb::addr_t link_map;
    bool mod_base_is_offset;

    bool valid = true;
    valid &= modInfo.get_name(mod_name);
    valid &= modInfo.get_base(mod_base);
    valid &= modInfo.get_base_is_offset(mod_base_is_offset);
    if (!valid)
      continue;

    if (!modInfo.get_link_map(link_map))
      link_map = LLDB_INVALID_ADDRESS;

    FileSpec file(mod_name);
    FileSystem::Instance().Resolve(file);
    lldb::ModuleSP module_sp =
        LoadModuleAtAddress(file, link_map, mod_base, mod_base_is_offset);

    if (module_sp.get())
      new_modules.Append(module_sp);
  }

  if (new_modules.GetSize() > 0) {
    ModuleList removed_modules;
    Target &target = GetTarget();
    ModuleList &loaded_modules = m_process->GetTarget().GetImages();

    for (size_t i = 0; i < loaded_modules.GetSize(); ++i) {
      const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i);

      bool found = false;
      for (size_t j = 0; j < new_modules.GetSize(); ++j) {
        if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get())
          found = true;
      }

      // The main executable will never be included in libraries-svr4, don't
      // remove it
      if (!found &&
          loaded_module.get() != target.GetExecutableModulePointer()) {
        removed_modules.Append(loaded_module);
      }
    }

    loaded_modules.Remove(removed_modules);
    m_process->GetTarget().ModulesDidUnload(removed_modules, false);

    new_modules.ForEach([&target](const lldb::ModuleSP module_sp) {
      lldb_private::ObjectFile *obj = module_sp->GetObjectFile();
      if (!obj)
        return IterationAction::Continue;

      if (obj->GetType() != ObjectFile::Type::eTypeExecutable)
        return IterationAction::Continue;

      lldb::ModuleSP module_copy_sp = module_sp;
      target.SetExecutableModule(module_copy_sp, eLoadDependentsNo);
      return IterationAction::Stop;
    });

    loaded_modules.AppendIfNeeded(new_modules);
    m_process->GetTarget().ModulesDidLoad(new_modules);
  }

  return llvm::ErrorSuccess();
}

Status ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file,
                                            bool &is_loaded,
                                            lldb::addr_t &load_addr) {
  is_loaded = false;
  load_addr = LLDB_INVALID_ADDRESS;

  std::string file_path = file.GetPath(false);
  if (file_path.empty())
    return Status::FromErrorString("Empty file name specified");

  StreamString packet;
  packet.PutCString("qFileLoadAddress:");
  packet.PutStringAsRawHex8(file_path);

  StringExtractorGDBRemote response;
  if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) !=
      GDBRemoteCommunication::PacketResult::Success)
    return Status::FromErrorString("Sending qFileLoadAddress packet failed");

  if (response.IsErrorResponse()) {
    if (response.GetError() == 1) {
      // The file is not loaded into the inferior
      is_loaded = false;
      load_addr = LLDB_INVALID_ADDRESS;
      return Status();
    }

    return Status::FromErrorString(
        "Fetching file load address from remote server returned an error");
  }

  if (response.IsNormalResponse()) {
    is_loaded = true;
    load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
    return Status();
  }

  return Status::FromErrorString(
      "Unknown error happened during sending the load address packet");
}

void ProcessGDBRemote::ModulesDidLoad(ModuleList &module_list) {
  // We must call the lldb_private::Process::ModulesDidLoad () first before we
  // do anything
  Process::ModulesDidLoad(module_list);

  // After loading shared libraries, we can ask our remote GDB server if it
  // needs any symbols.
  m_gdb_comm.ServeSymbolLookups(this);
}

void ProcessGDBRemote::HandleAsyncStdout(llvm::StringRef out) {
  AppendSTDOUT(out.data(), out.size());
}

static const char *end_delimiter = "--end--;";
static const int end_delimiter_len = 8;

void ProcessGDBRemote::HandleAsyncMisc(llvm::StringRef data) {
  std::string input = data.str(); // '1' to move beyond 'A'
  if (m_partial_profile_data.length() > 0) {
    m_partial_profile_data.append(input);
    input = m_partial_profile_data;
    m_partial_profile_data.clear();
  }

  size_t found, pos = 0, len = input.length();
  while ((found = input.find(end_delimiter, pos)) != std::string::npos) {
    StringExtractorGDBRemote profileDataExtractor(
        input.substr(pos, found).c_str());
    std::string profile_data =
        HarmonizeThreadIdsForProfileData(profileDataExtractor);
    BroadcastAsyncProfileData(profile_data);

    pos = found + end_delimiter_len;
  }

  if (pos < len) {
    // Last incomplete chunk.
    m_partial_profile_data = input.substr(pos);
  }
}

std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData(
    StringExtractorGDBRemote &profileDataExtractor) {
  std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map;
  std::string output;
  llvm::raw_string_ostream output_stream(output);
  llvm::StringRef name, value;

  // Going to assuming thread_used_usec comes first, else bail out.
  while (profileDataExtractor.GetNameColonValue(name, value)) {
    if (name.compare("thread_used_id") == 0) {
      StringExtractor threadIDHexExtractor(value);
      uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0);

      bool has_used_usec = false;
      uint32_t curr_used_usec = 0;
      llvm::StringRef usec_name, usec_value;
      uint32_t input_file_pos = profileDataExtractor.GetFilePos();
      if (profileDataExtractor.GetNameColonValue(usec_name, usec_value)) {
        if (usec_name == "thread_used_usec") {
          has_used_usec = true;
          usec_value.getAsInteger(0, curr_used_usec);
        } else {
          // We didn't find what we want, it is probably an older version. Bail
          // out.
          profileDataExtractor.SetFilePos(input_file_pos);
        }
      }

      if (has_used_usec) {
        uint32_t prev_used_usec = 0;
        std::map<uint64_t, uint32_t>::iterator iterator =
            m_thread_id_to_used_usec_map.find(thread_id);
        if (iterator != m_thread_id_to_used_usec_map.end())
          prev_used_usec = iterator->second;

        uint32_t real_used_usec = curr_used_usec - prev_used_usec;
        // A good first time record is one that runs for at least 0.25 sec
        bool good_first_time =
            (prev_used_usec == 0) && (real_used_usec > 250000);
        bool good_subsequent_time =
            (prev_used_usec > 0) &&
            ((real_used_usec > 0) || (HasAssignedIndexIDToThread(thread_id)));

        if (good_first_time || good_subsequent_time) {
          // We try to avoid doing too many index id reservation, resulting in
          // fast increase of index ids.

          output_stream << name << ":";
          int32_t index_id = AssignIndexIDToThread(thread_id);
          output_stream << index_id << ";";

          output_stream << usec_name << ":" << usec_value << ";";
        } else {
          // Skip past 'thread_used_name'.
          llvm::StringRef local_name, local_value;
          profileDataExtractor.GetNameColonValue(local_name, local_value);
        }

        // Store current time as previous time so that they can be compared
        // later.
        new_thread_id_to_used_usec_map[thread_id] = curr_used_usec;
      } else {
        // Bail out and use old string.
        output_stream << name << ":" << value << ";";
      }
    } else {
      output_stream << name << ":" << value << ";";
    }
  }
  output_stream << end_delimiter;
  m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map;

  return output;
}

void ProcessGDBRemote::HandleStopReply() {
  if (GetStopID() != 0)
    return;

  if (GetID() == LLDB_INVALID_PROCESS_ID) {
    lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
    if (pid != LLDB_INVALID_PROCESS_ID)
      SetID(pid);
  }
  BuildDynamicRegisterInfo(true);
}

llvm::Expected<bool> ProcessGDBRemote::SaveCore(llvm::StringRef outfile) {
  if (!m_gdb_comm.GetSaveCoreSupported())
    return false;

  StreamString packet;
  packet.PutCString("qSaveCore;path-hint:");
  packet.PutStringAsRawHex8(outfile);

  StringExtractorGDBRemote response;
  if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) ==
      GDBRemoteCommunication::PacketResult::Success) {
    // TODO: grab error message from the packet?  StringExtractor seems to
    // be missing a method for that
    if (response.IsErrorResponse())
      return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                     "qSaveCore returned an error");

    std::string path;

    // process the response
    for (auto x : llvm::split(response.GetStringRef(), ';')) {
      if (x.consume_front("core-path:"))
        StringExtractor(x).GetHexByteString(path);
    }

    // verify that we've gotten what we need
    if (path.empty())
      return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                     "qSaveCore returned no core path");

    // now transfer the core file
    FileSpec remote_core{llvm::StringRef(path)};
    Platform &platform = *GetTarget().GetPlatform();
    Status error = platform.GetFile(remote_core, FileSpec(outfile));

    if (platform.IsRemote()) {
      // NB: we unlink the file on error too
      platform.Unlink(remote_core);
      if (error.Fail())
        return error.ToError();
    }

    return true;
  }

  return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                 "Unable to send qSaveCore");
}

static const char *const s_async_json_packet_prefix = "JSON-async:";

static StructuredData::ObjectSP
ParseStructuredDataPacket(llvm::StringRef packet) {
  Log *log = GetLog(GDBRLog::Process);

  if (!packet.consume_front(s_async_json_packet_prefix)) {
    if (log) {
      LLDB_LOGF(
          log,
          "GDBRemoteCommunicationClientBase::%s() received $J packet "
          "but was not a StructuredData packet: packet starts with "
          "%s",
          __FUNCTION__,
          packet.slice(0, strlen(s_async_json_packet_prefix)).str().c_str());
    }
    return StructuredData::ObjectSP();
  }

  // This is an asynchronous JSON packet, destined for a StructuredDataPlugin.
  StructuredData::ObjectSP json_sp = StructuredData::ParseJSON(packet);
  if (log) {
    if (json_sp) {
      StreamString json_str;
      json_sp->Dump(json_str, true);
      json_str.Flush();
      LLDB_LOGF(log,
                "ProcessGDBRemote::%s() "
                "received Async StructuredData packet: %s",
                __FUNCTION__, json_str.GetData());
    } else {
      LLDB_LOGF(log,
                "ProcessGDBRemote::%s"
                "() received StructuredData packet:"
                " parse failure",
                __FUNCTION__);
    }
  }
  return json_sp;
}

void ProcessGDBRemote::HandleAsyncStructuredDataPacket(llvm::StringRef data) {
  auto structured_data_sp = ParseStructuredDataPacket(data);
  if (structured_data_sp)
    RouteAsyncStructuredData(structured_data_sp);
}

class CommandObjectProcessGDBRemoteSpeedTest : public CommandObjectParsed {
public:
  CommandObjectProcessGDBRemoteSpeedTest(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "process plugin packet speed-test",
                            "Tests packet speeds of various sizes to determine "
                            "the performance characteristics of the GDB remote "
                            "connection. ",
                            nullptr),
        m_option_group(),
        m_num_packets(LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount,
                      "The number of packets to send of each varying size "
                      "(default is 1000).",
                      1000),
        m_max_send(LLDB_OPT_SET_1, false, "max-send", 's', 0, eArgTypeCount,
                   "The maximum number of bytes to send in a packet. Sizes "
                   "increase in powers of 2 while the size is less than or "
                   "equal to this option value. (default 1024).",
                   1024),
        m_max_recv(LLDB_OPT_SET_1, false, "max-receive", 'r', 0, eArgTypeCount,
                   "The maximum number of bytes to receive in a packet. Sizes "
                   "increase in powers of 2 while the size is less than or "
                   "equal to this option value. (default 1024).",
                   1024),
        m_json(LLDB_OPT_SET_1, false, "json", 'j',
               "Print the output as JSON data for easy parsing.", false, true) {
    m_option_group.Append(&m_num_packets, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_max_send, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_max_recv, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_json, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Finalize();
  }

  ~CommandObjectProcessGDBRemoteSpeedTest() override = default;

  Options *GetOptions() override { return &m_option_group; }

  void DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc == 0) {
      ProcessGDBRemote *process =
          (ProcessGDBRemote *)m_interpreter.GetExecutionContext()
              .GetProcessPtr();
      if (process) {
        StreamSP output_stream_sp = result.GetImmediateOutputStream();
        if (!output_stream_sp)
          output_stream_sp = m_interpreter.GetDebugger().GetAsyncOutputStream();
        result.SetImmediateOutputStream(output_stream_sp);

        const uint32_t num_packets =
            (uint32_t)m_num_packets.GetOptionValue().GetCurrentValue();
        const uint64_t max_send = m_max_send.GetOptionValue().GetCurrentValue();
        const uint64_t max_recv = m_max_recv.GetOptionValue().GetCurrentValue();
        const bool json = m_json.GetOptionValue().GetCurrentValue();
        const uint64_t k_recv_amount =
            4 * 1024 * 1024; // Receive amount in bytes
        process->GetGDBRemote().TestPacketSpeed(
            num_packets, max_send, max_recv, k_recv_amount, json,
            output_stream_sp ? *output_stream_sp : result.GetOutputStream());
        result.SetStatus(eReturnStatusSuccessFinishResult);
        return;
      }
    } else {
      result.AppendErrorWithFormat("'%s' takes no arguments",
                                   m_cmd_name.c_str());
    }
    result.SetStatus(eReturnStatusFailed);
  }

protected:
  OptionGroupOptions m_option_group;
  OptionGroupUInt64 m_num_packets;
  OptionGroupUInt64 m_max_send;
  OptionGroupUInt64 m_max_recv;
  OptionGroupBoolean m_json;
};

class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed {
private:
public:
  CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "process plugin packet history",
                            "Dumps the packet history buffer. ", nullptr) {}

  ~CommandObjectProcessGDBRemotePacketHistory() override = default;

  void DoExecute(Args &command, CommandReturnObject &result) override {
    ProcessGDBRemote *process =
        (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
    if (process) {
      process->DumpPluginHistory(result.GetOutputStream());
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return;
    }
    result.SetStatus(eReturnStatusFailed);
  }
};

class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed {
private:
public:
  CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "process plugin packet xfer-size",
            "Maximum size that lldb will try to read/write one one chunk.",
            nullptr) {
    AddSimpleArgumentList(eArgTypeUnsignedInteger);
  }

  ~CommandObjectProcessGDBRemotePacketXferSize() override = default;

  void DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc == 0) {
      result.AppendErrorWithFormat("'%s' takes an argument to specify the max "
                                   "amount to be transferred when "
                                   "reading/writing",
                                   m_cmd_name.c_str());
      return;
    }

    ProcessGDBRemote *process =
        (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
    if (process) {
      const char *packet_size = command.GetArgumentAtIndex(0);
      errno = 0;
      uint64_t user_specified_max = strtoul(packet_size, nullptr, 10);
      if (errno == 0 && user_specified_max != 0) {
        process->SetUserSpecifiedMaxMemoryTransferSize(user_specified_max);
        result.SetStatus(eReturnStatusSuccessFinishResult);
        return;
      }
    }
    result.SetStatus(eReturnStatusFailed);
  }
};

class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed {
private:
public:
  CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "process plugin packet send",
                            "Send a custom packet through the GDB remote "
                            "protocol and print the answer. "
                            "The packet header and footer will automatically "
                            "be added to the packet prior to sending and "
                            "stripped from the result.",
                            nullptr) {
    AddSimpleArgumentList(eArgTypeNone, eArgRepeatStar);
  }

  ~CommandObjectProcessGDBRemotePacketSend() override = default;

  void DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc == 0) {
      result.AppendErrorWithFormat(
          "'%s' takes a one or more packet content arguments",
          m_cmd_name.c_str());
      return;
    }

    ProcessGDBRemote *process =
        (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
    if (process) {
      for (size_t i = 0; i < argc; ++i) {
        const char *packet_cstr = command.GetArgumentAtIndex(0);
        StringExtractorGDBRemote response;
        process->GetGDBRemote().SendPacketAndWaitForResponse(
            packet_cstr, response, process->GetInterruptTimeout());
        result.SetStatus(eReturnStatusSuccessFinishResult);
        Stream &output_strm = result.GetOutputStream();
        output_strm.Printf("  packet: %s\n", packet_cstr);
        std::string response_str = std::string(response.GetStringRef());

        if (strstr(packet_cstr, "qGetProfileData") != nullptr) {
          response_str = process->HarmonizeThreadIdsForProfileData(response);
        }

        if (response_str.empty())
          output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n");
        else
          output_strm.Printf("response: %s\n", response.GetStringRef().data());
      }
    }
  }
};

class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw {
private:
public:
  CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter)
      : CommandObjectRaw(interpreter, "process plugin packet monitor",
                         "Send a qRcmd packet through the GDB remote protocol "
                         "and print the response. "
                         "The argument passed to this command will be hex "
                         "encoded into a valid 'qRcmd' packet, sent and the "
                         "response will be printed.") {}

  ~CommandObjectProcessGDBRemotePacketMonitor() override = default;

  void DoExecute(llvm::StringRef command,
                 CommandReturnObject &result) override {
    if (command.empty()) {
      result.AppendErrorWithFormat("'%s' takes a command string argument",
                                   m_cmd_name.c_str());
      return;
    }

    ProcessGDBRemote *process =
        (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
    if (process) {
      StreamString packet;
      packet.PutCString("qRcmd,");
      packet.PutBytesAsRawHex8(command.data(), command.size());

      StringExtractorGDBRemote response;
      Stream &output_strm = result.GetOutputStream();
      process->GetGDBRemote().SendPacketAndReceiveResponseWithOutputSupport(
          packet.GetString(), response, process->GetInterruptTimeout(),
          [&output_strm](llvm::StringRef output) { output_strm << output; });
      result.SetStatus(eReturnStatusSuccessFinishResult);
      output_strm.Printf("  packet: %s\n", packet.GetData());
      const std::string &response_str = std::string(response.GetStringRef());

      if (response_str.empty())
        output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n");
      else
        output_strm.Printf("response: %s\n", response.GetStringRef().data());
    }
  }
};

class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword {
private:
public:
  CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "process plugin packet",
                               "Commands that deal with GDB remote packets.",
                               nullptr) {
    LoadSubCommand(
        "history",
        CommandObjectSP(
            new CommandObjectProcessGDBRemotePacketHistory(interpreter)));
    LoadSubCommand(
        "send", CommandObjectSP(
                    new CommandObjectProcessGDBRemotePacketSend(interpreter)));
    LoadSubCommand(
        "monitor",
        CommandObjectSP(
            new CommandObjectProcessGDBRemotePacketMonitor(interpreter)));
    LoadSubCommand(
        "xfer-size",
        CommandObjectSP(
            new CommandObjectProcessGDBRemotePacketXferSize(interpreter)));
    LoadSubCommand("speed-test",
                   CommandObjectSP(new CommandObjectProcessGDBRemoteSpeedTest(
                       interpreter)));
  }

  ~CommandObjectProcessGDBRemotePacket() override = default;
};

class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword {
public:
  CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "process plugin",
            "Commands for operating on a ProcessGDBRemote process.",
            "process plugin <subcommand> [<subcommand-options>]") {
    LoadSubCommand(
        "packet",
        CommandObjectSP(new CommandObjectProcessGDBRemotePacket(interpreter)));
  }

  ~CommandObjectMultiwordProcessGDBRemote() override = default;
};

CommandObject *ProcessGDBRemote::GetPluginCommandObject() {
  if (!m_command_sp)
    m_command_sp = std::make_shared<CommandObjectMultiwordProcessGDBRemote>(
        GetTarget().GetDebugger().GetCommandInterpreter());
  return m_command_sp.get();
}

void ProcessGDBRemote::DidForkSwitchSoftwareBreakpoints(bool enable) {
  GetBreakpointSiteList().ForEach([this, enable](BreakpointSite *bp_site) {
    if (bp_site->IsEnabled() &&
        (bp_site->GetType() == BreakpointSite::eSoftware ||
         bp_site->GetType() == BreakpointSite::eExternal)) {
      m_gdb_comm.SendGDBStoppointTypePacket(
          eBreakpointSoftware, enable, bp_site->GetLoadAddress(),
          GetSoftwareBreakpointTrapOpcode(bp_site), GetInterruptTimeout());
    }
  });
}

void ProcessGDBRemote::DidForkSwitchHardwareTraps(bool enable) {
  if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) {
    GetBreakpointSiteList().ForEach([this, enable](BreakpointSite *bp_site) {
      if (bp_site->IsEnabled() &&
          bp_site->GetType() == BreakpointSite::eHardware) {
        m_gdb_comm.SendGDBStoppointTypePacket(
            eBreakpointHardware, enable, bp_site->GetLoadAddress(),
            GetSoftwareBreakpointTrapOpcode(bp_site), GetInterruptTimeout());
      }
    });
  }

  for (const auto &wp_res_sp : m_watchpoint_resource_list.Sites()) {
    addr_t addr = wp_res_sp->GetLoadAddress();
    size_t size = wp_res_sp->GetByteSize();
    GDBStoppointType type = GetGDBStoppointType(wp_res_sp);
    m_gdb_comm.SendGDBStoppointTypePacket(type, enable, addr, size,
                                          GetInterruptTimeout());
  }
}

void ProcessGDBRemote::DidFork(lldb::pid_t child_pid, lldb::tid_t child_tid) {
  Log *log = GetLog(GDBRLog::Process);

  lldb::pid_t parent_pid = m_gdb_comm.GetCurrentProcessID();
  // Any valid TID will suffice, thread-relevant actions will set a proper TID
  // anyway.
  lldb::tid_t parent_tid = m_thread_ids.front();

  lldb::pid_t follow_pid, detach_pid;
  lldb::tid_t follow_tid, detach_tid;

  switch (GetFollowForkMode()) {
  case eFollowParent:
    follow_pid = parent_pid;
    follow_tid = parent_tid;
    detach_pid = child_pid;
    detach_tid = child_tid;
    break;
  case eFollowChild:
    follow_pid = child_pid;
    follow_tid = child_tid;
    detach_pid = parent_pid;
    detach_tid = parent_tid;
    break;
  }

  // Switch to the process that is going to be detached.
  if (!m_gdb_comm.SetCurrentThread(detach_tid, detach_pid)) {
    LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to set pid/tid");
    return;
  }

  // Disable all software breakpoints in the forked process.
  if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware))
    DidForkSwitchSoftwareBreakpoints(false);

  // Remove hardware breakpoints / watchpoints from parent process if we're
  // following child.
  if (GetFollowForkMode() == eFollowChild)
    DidForkSwitchHardwareTraps(false);

  // Switch to the process that is going to be followed
  if (!m_gdb_comm.SetCurrentThread(follow_tid, follow_pid) ||
      !m_gdb_comm.SetCurrentThreadForRun(follow_tid, follow_pid)) {
    LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to reset pid/tid");
    return;
  }

  LLDB_LOG(log, "Detaching process {0}", detach_pid);
  Status error = m_gdb_comm.Detach(false, detach_pid);
  if (error.Fail()) {
    LLDB_LOG(log, "ProcessGDBRemote::DidFork() detach packet send failed: {0}",
             error.AsCString() ? error.AsCString() : "<unknown error>");
    return;
  }

  // Hardware breakpoints/watchpoints are not inherited implicitly,
  // so we need to readd them if we're following child.
  if (GetFollowForkMode() == eFollowChild) {
    DidForkSwitchHardwareTraps(true);
    // Update our PID
    SetID(child_pid);
  }
}

void ProcessGDBRemote::DidVFork(lldb::pid_t child_pid, lldb::tid_t child_tid) {
  Log *log = GetLog(GDBRLog::Process);

  LLDB_LOG(
      log,
      "ProcessGDBRemote::DidFork() called for child_pid: {0}, child_tid {1}",
      child_pid, child_tid);
  ++m_vfork_in_progress_count;

  // Disable all software breakpoints for the duration of vfork.
  if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware))
    DidForkSwitchSoftwareBreakpoints(false);

  lldb::pid_t detach_pid;
  lldb::tid_t detach_tid;

  switch (GetFollowForkMode()) {
  case eFollowParent:
    detach_pid = child_pid;
    detach_tid = child_tid;
    break;
  case eFollowChild:
    detach_pid = m_gdb_comm.GetCurrentProcessID();
    // Any valid TID will suffice, thread-relevant actions will set a proper TID
    // anyway.
    detach_tid = m_thread_ids.front();

    // Switch to the parent process before detaching it.
    if (!m_gdb_comm.SetCurrentThread(detach_tid, detach_pid)) {
      LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to set pid/tid");
      return;
    }

    // Remove hardware breakpoints / watchpoints from the parent process.
    DidForkSwitchHardwareTraps(false);

    // Switch to the child process.
    if (!m_gdb_comm.SetCurrentThread(child_tid, child_pid) ||
        !m_gdb_comm.SetCurrentThreadForRun(child_tid, child_pid)) {
      LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to reset pid/tid");
      return;
    }
    break;
  }

  LLDB_LOG(log, "Detaching process {0}", detach_pid);
  Status error = m_gdb_comm.Detach(false, detach_pid);
  if (error.Fail()) {
      LLDB_LOG(log,
               "ProcessGDBRemote::DidFork() detach packet send failed: {0}",
                error.AsCString() ? error.AsCString() : "<unknown error>");
      return;
  }

  if (GetFollowForkMode() == eFollowChild) {
    // Update our PID
    SetID(child_pid);
  }
}

void ProcessGDBRemote::DidVForkDone() {
  assert(m_vfork_in_progress_count > 0);
  --m_vfork_in_progress_count;

  // Reenable all software breakpoints that were enabled before vfork.
  if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware))
    DidForkSwitchSoftwareBreakpoints(true);
}

void ProcessGDBRemote::DidExec() {
  // If we are following children, vfork is finished by exec (rather than
  // vforkdone that is submitted for parent).
  if (GetFollowForkMode() == eFollowChild) {
    if (m_vfork_in_progress_count > 0)
      --m_vfork_in_progress_count;
  }
  Process::DidExec();
}
