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

#include "lldb/Host/Config.h"

// C Includes
#include <errno.h>
#include <stdlib.h>
#ifndef LLDB_DISABLE_POSIX
#include <netinet/in.h>
#include <sys/mman.h> // for mmap
#include <sys/socket.h>
#include <unistd.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>

// C++ Includes
#include <algorithm>
#include <csignal>
#include <map>
#include <mutex>
#include <sstream>

#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Value.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/Symbols.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/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/CleanUp.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"

// Project includes
#include "GDBRemoteRegisterContext.h"
#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.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/StringSwitch.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"

#define DEBUGSERVER_BASENAME "debugserver"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;

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) {
  StreamFile strm;
  Status error(strm.GetFile().Open(path, File::eOpenOptionWrite |
                                             File::eOpenOptionCanCreate));
  if (error.Success())
    ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm);
}
}

namespace {

static PropertyDefinition g_properties[] = {
    {"packet-timeout", OptionValue::eTypeUInt64, true, 1, NULL, NULL,
     "Specify the default packet timeout in seconds."},
    {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, NULL, NULL,
     "The file that provides the description for remote target registers."},
    {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}};

enum { ePropertyPacketTimeout, ePropertyTargetDefinitionFile };

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

  PluginProperties() : Properties() {
    m_collection_sp.reset(new OptionValueProperties(GetSettingName()));
    m_collection_sp->Initialize(g_properties);
  }

  virtual ~PluginProperties() {}

  uint64_t GetPacketTimeout() {
    const uint32_t idx = ePropertyPacketTimeout;
    return m_collection_sp->GetPropertyAtIndexAsUInt64(
        NULL, idx, g_properties[idx].default_uint_value);
  }

  bool SetPacketTimeout(uint64_t timeout) {
    const uint32_t idx = ePropertyPacketTimeout;
    return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout);
  }

  FileSpec GetTargetDefinitionFile() const {
    const uint32_t idx = ePropertyTargetDefinitionFile;
    return m_collection_sp->GetPropertyAtIndexAsFileSpec(NULL, idx);
  }
};

typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;

static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() {
  static ProcessKDPPropertiesSP g_settings_sp;
  if (!g_settings_sp)
    g_settings_sp.reset(new PluginProperties());
  return g_settings_sp;
}

} // anonymous namespace end

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

#if defined(__APPLE__) &&                                                      \
    (defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
static bool rand_initialized = false;

static inline uint16_t get_random_port() {
  if (!rand_initialized) {
    time_t seed = time(NULL);

    rand_initialized = true;
    srand(seed);
  }
  return (rand() % (HIGH_PORT - LOW_PORT)) + LOW_PORT;
}
#endif

ConstString ProcessGDBRemote::GetPluginNameStatic() {
  static ConstString g_name("gdb-remote");
  return g_name;
}

const char *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) {
  lldb::ProcessSP process_sp;
  if (crash_file_path == NULL)
    process_sp.reset(new ProcessGDBRemote(target_sp, listener_sp));
  return process_sp;
}

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 exe_module->GetFileSpec().Exists();
  }
  // 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_last_stop_packet_mutex(),
      m_register_info(),
      m_async_broadcaster(NULL, "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_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_destroy_tried_resuming(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_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(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC));

  const uint32_t async_event_mask =
      eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;

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

  const uint32_t gdb_event_mask =
      Communication::eBroadcastBitReadThreadDidExit |
      GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify;
  if (m_async_listener_sp->StartListeningForEvents(
          &m_gdb_comm, gdb_event_mask) != gdb_event_mask) {
    if (log)
      log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events",
                  __FUNCTION__);
  }

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

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

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

//----------------------------------------------------------------------
// PluginInterface
//----------------------------------------------------------------------
ConstString ProcessGDBRemote::GetPluginName() { return GetPluginNameStatic(); }

uint32_t ProcessGDBRemote::GetPluginVersion() { return 1; }

bool ProcessGDBRemote::ParsePythonTargetDefinition(
    const FileSpec &target_definition_fspec) {
  ScriptInterpreter *interpreter =
      GetTarget().GetDebugger().GetCommandInterpreter().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 = 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->GetAsInteger())
          m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue();
      }

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

// If the remote stub didn't give us eh_frame or DWARF register numbers for a
// register, see if the ABI can provide them.
// DWARF and eh_frame register numbers are defined as a part of the ABI.
static void AugmentRegisterInfoViaABI(RegisterInfo &reg_info,
                                      ConstString reg_name, ABISP abi_sp) {
  if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM ||
      reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM) {
    if (abi_sp) {
      RegisterInfo abi_reg_info;
      if (abi_sp->GetRegisterInfoByName(reg_name, abi_reg_info)) {
        if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM &&
            abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) {
          reg_info.kinds[eRegisterKindEHFrame] =
              abi_reg_info.kinds[eRegisterKindEHFrame];
        }
        if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM &&
            abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) {
          reg_info.kinds[eRegisterKindDWARF] =
              abi_reg_info.kinds[eRegisterKindDWARF];
        }
        if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM &&
            abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) {
          reg_info.kinds[eRegisterKindGeneric] =
              abi_reg_info.kinds[eRegisterKindGeneric];
        }
      }
    }
  }
}

static size_t SplitCommaSeparatedRegisterNumberString(
    const llvm::StringRef &comma_separated_regiter_numbers,
    std::vector<uint32_t> &regnums, int base) {
  regnums.clear();
  std::pair<llvm::StringRef, llvm::StringRef> value_pair;
  value_pair.second = comma_separated_regiter_numbers;
  do {
    value_pair = value_pair.second.split(',');
    if (!value_pair.first.empty()) {
      uint32_t reg = StringConvert::ToUInt32(value_pair.first.str().c_str(),
                                             LLDB_INVALID_REGNUM, base);
      if (reg != LLDB_INVALID_REGNUM)
        regnums.push_back(reg);
    }
  } while (!value_pair.second.empty());
  return regnums.size();
}

void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
  if (!force && m_register_info.GetNumRegisters() > 0)
    return;

  m_register_info.Clear();

  // 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.

  FileSpec target_definition_fspec =
      GetGlobalPluginProperties()->GetTargetDefinitionFile();
  if (!target_definition_fspec.Exists()) {
    // If the filename doesn't exist, it may be a ~ not having been expanded -
    // try to resolve it.
    target_definition_fspec.ResolvePath();
  }
  if (target_definition_fspec) {
    // See if we can get register definitions from a python file
    if (ParsePythonTargetDefinition(target_definition_fspec)) {
      return;
    } else {
      StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream();
      stream_sp->Printf("ERROR: target description file %s failed to parse.\n",
                        target_definition_fspec.GetPath().c_str());
    }
  }

  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;

  if (GetGDBServerRegisterInfo(arch_to_use))
    return;

  char packet[128];
  uint32_t reg_offset = 0;
  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, false) ==
        GDBRemoteCommunication::PacketResult::Success) {
      response_type = response.GetResponseType();
      if (response_type == StringExtractorGDBRemote::eResponse) {
        llvm::StringRef name;
        llvm::StringRef value;
        ConstString reg_name;
        ConstString alt_name;
        ConstString set_name;
        std::vector<uint32_t> value_regs;
        std::vector<uint32_t> invalidate_regs;
        std::vector<uint8_t> dwarf_opcode_bytes;
        RegisterInfo reg_info = {
            NULL,          // Name
            NULL,          // Alt name
            0,             // byte size
            reg_offset,    // offset
            eEncodingUint, // encoding
            eFormatHex,    // format
            {
                LLDB_INVALID_REGNUM, // eh_frame reg num
                LLDB_INVALID_REGNUM, // DWARF reg num
                LLDB_INVALID_REGNUM, // generic reg num
                reg_num,             // process plugin reg num
                reg_num              // native register number
            },
            NULL,
            NULL,
            NULL, // Dwarf expression opcode bytes pointer
            0     // Dwarf expression opcode bytes length
        };

        while (response.GetNameColonValue(name, value)) {
          if (name.equals("name")) {
            reg_name.SetString(value);
          } else if (name.equals("alt-name")) {
            alt_name.SetString(value);
          } else if (name.equals("bitsize")) {
            value.getAsInteger(0, reg_info.byte_size);
            reg_info.byte_size /= CHAR_BIT;
          } else if (name.equals("offset")) {
            if (value.getAsInteger(0, reg_offset))
              reg_offset = UINT32_MAX;
          } else if (name.equals("encoding")) {
            const Encoding encoding = Args::StringToEncoding(value);
            if (encoding != eEncodingInvalid)
              reg_info.encoding = encoding;
          } else if (name.equals("format")) {
            Format format = eFormatInvalid;
            if (OptionArgParser::ToFormat(value.str().c_str(), format, NULL)
                    .Success())
              reg_info.format = format;
            else {
              reg_info.format =
                  llvm::StringSwitch<Format>(value)
                      .Case("binary", eFormatBinary)
                      .Case("decimal", eFormatDecimal)
                      .Case("hex", eFormatHex)
                      .Case("float", eFormatFloat)
                      .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.equals("set")) {
            set_name.SetString(value);
          } else if (name.equals("gcc") || name.equals("ehframe")) {
            if (value.getAsInteger(0, reg_info.kinds[eRegisterKindEHFrame]))
              reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM;
          } else if (name.equals("dwarf")) {
            if (value.getAsInteger(0, reg_info.kinds[eRegisterKindDWARF]))
              reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM;
          } else if (name.equals("generic")) {
            reg_info.kinds[eRegisterKindGeneric] =
                Args::StringToGenericRegister(value);
          } else if (name.equals("container-regs")) {
            SplitCommaSeparatedRegisterNumberString(value, value_regs, 16);
          } else if (name.equals("invalidate-regs")) {
            SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 16);
          } else if (name.equals("dynamic_size_dwarf_expr_bytes")) {
            size_t dwarf_opcode_len = value.size() / 2;
            assert(dwarf_opcode_len > 0);

            dwarf_opcode_bytes.resize(dwarf_opcode_len);
            reg_info.dynamic_size_dwarf_len = dwarf_opcode_len;

            StringExtractor opcode_extractor(value);
            uint32_t ret_val =
                opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes);
            assert(dwarf_opcode_len == ret_val);
            UNUSED_IF_ASSERT_DISABLED(ret_val);
            reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data();
          }
        }

        reg_info.byte_offset = reg_offset;
        assert(reg_info.byte_size != 0);
        reg_offset += reg_info.byte_size;
        if (!value_regs.empty()) {
          value_regs.push_back(LLDB_INVALID_REGNUM);
          reg_info.value_regs = value_regs.data();
        }
        if (!invalidate_regs.empty()) {
          invalidate_regs.push_back(LLDB_INVALID_REGNUM);
          reg_info.invalidate_regs = invalidate_regs.data();
        }

        // We have to make a temporary ABI here, and not use the GetABI because
        // this code gets called in DidAttach, when the target architecture
        // (and consequently the ABI we'll get from the process) may be wrong.
        ABISP abi_to_use = ABI::FindPlugin(shared_from_this(), arch_to_use);

        AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use);

        m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
      } else {
        break; // ensure exit before reg_num is incremented
      }
    } else {
      break;
    }
  }

  if (m_register_info.GetNumRegisters() > 0) {
    m_register_info.Finalize(GetTarget().GetArchitecture());
    return;
  }

  // We didn't get anything if the accumulated reg_num is zero.  See if we are
  // debugging ARM and fill with a hard coded register set until we can get an
  // updated debugserver down on the devices. On the other hand, if the
  // accumulated reg_num is positive, see if we can add composite registers to
  // the existing primordial ones.
  bool from_scratch = (m_register_info.GetNumRegisters() == 0);

  if (!target_arch.IsValid()) {
    if (arch_to_use.IsValid() &&
        (arch_to_use.GetMachine() == llvm::Triple::arm ||
         arch_to_use.GetMachine() == llvm::Triple::thumb) &&
        arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple)
      m_register_info.HardcodeARMRegisters(from_scratch);
  } else if (target_arch.GetMachine() == llvm::Triple::arm ||
             target_arch.GetMachine() == llvm::Triple::thumb) {
    m_register_info.HardcodeARMRegisters(from_scratch);
  }

  // At this point, we can finalize our register info.
  m_register_info.Finalize(GetTarget().GetArchitecture());
}

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

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

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

Status ProcessGDBRemote::DoConnectRemote(Stream *strm,
                                         llvm::StringRef remote_url) {
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_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);

      // '?' Packets must be handled differently in non-stop mode
      if (GetTarget().GetNonStopModeEnabled())
        HandleStopReplySequence();

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

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

  if (log)
    log->Printf("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());
  }

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

  if (error.Success()) {
    PlatformSP platform_sp = GetTarget().GetPlatform();
    if (platform_sp && platform_sp->IsConnected())
      SetUnixSignals(platform_sp->GetUnixSignals());
    else
      SetUnixSignals(UnixSignals::Create(GetTarget().GetArchitecture()));
  }

  return error;
}

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

//----------------------------------------------------------------------
// Process Control
//----------------------------------------------------------------------
Status ProcessGDBRemote::DoLaunch(Module *exe_module,
                                  ProcessLaunchInfo &launch_info) {
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
  Status error;

  if (log)
    log->Printf("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)
      log->Printf("ProcessGDBRemote::%s provided with STDIO paths via "
                  "launch_info: stdin=%s, stdout=%s, stderr=%s",
                  __FUNCTION__,
                  stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
                  stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
                  stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
    else
      log->Printf("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");

  ObjectFile *object_file = exe_module->GetObjectFile();
  if (object_file) {
    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, false,
                                  FileSpec::Style::native);
        if (!stdout_file_spec)
          stdout_file_spec.SetFile(FileSystem::DEV_NULL, false,
                                   FileSpec::Style::native);
        if (!stderr_file_spec)
          stderr_file_spec.SetFile(FileSystem::DEV_NULL, false,
                                   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) &&
            pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, NULL, 0)) {
          FileSpec slave_name{pty.GetSlaveName(NULL, 0), false};

          if (!stdin_file_spec)
            stdin_file_spec = slave_name;

          if (!stdout_file_spec)
            stdout_file_spec = slave_name;

          if (!stderr_file_spec)
            stderr_file_spec = slave_name;
        }
        if (log)
          log->Printf(
              "ProcessGDBRemote::%s adjusted STDIO paths for local platform "
              "(IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s",
              __FUNCTION__,
              stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
              stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
              stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
      }

      if (log)
        log->Printf("ProcessGDBRemote::%s final STDIO paths after all "
                    "adjustments: stdin=%s, stdout=%s, stderr=%s",
                    __FUNCTION__,
                    stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
                    stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
                    stderr_file_spec ? stderr_file_spec.GetCString()
                                     : "<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 != NULL && *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));

        int arg_packet_err = m_gdb_comm.SendArgumentsPacket(launch_info);
        if (arg_packet_err == 0) {
          std::string error_str;
          if (m_gdb_comm.GetLaunchSuccess(error_str)) {
            SetID(m_gdb_comm.GetCurrentProcessID());
          } else {
            error.SetErrorString(error_str.c_str());
          }
        } else {
          error.SetErrorStringWithFormat("'A' packet returned an error: %i",
                                         arg_packet_err);
        }
      }

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

      StringExtractorGDBRemote response;
      if (m_gdb_comm.GetStopReply(response)) {
        SetLastStopPacket(response);
        // '?' Packets must be handled differently in non-stop mode
        if (GetTarget().GetNonStopModeEnabled())
          HandleStopReplySequence();

        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.GetMasterFileDescriptor() != PseudoTerminal::invalid_fd)
            SetSTDIOFileDescriptor(pty.ReleaseMasterFileDescriptor());
        }
      }
    } else {
      if (log)
        log->Printf("failed to connect to debugserver: %s", error.AsCString());
    }
  } else {
    // Set our user ID to an invalid process ID.
    SetID(LLDB_INVALID_PROCESS_ID);
    error.SetErrorStringWithFormat(
        "failed to get object file from '%s' for arch %s",
        exe_module->GetFileSpec().GetFilename().AsCString(),
        exe_module->GetArchitecture().GetArchitectureName());
  }
  return error;
}

Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) {
  Status error;
  // Only connect if we have a valid connect URL
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));

  if (!connect_url.empty()) {
    if (log)
      log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__,
                  connect_url.str().c_str());
    std::unique_ptr<ConnectionFileDescriptor> conn_ap(
        new ConnectionFileDescriptor());
    if (conn_ap.get()) {
      const uint32_t max_retry_count = 50;
      uint32_t retry_count = 0;
      while (!m_gdb_comm.IsConnected()) {
        if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess) {
          m_gdb_comm.SetConnection(conn_ap.release());
          break;
        } else if (error.WasInterrupted()) {
          // If we were interrupted, don't keep retrying.
          break;
        }

        retry_count++;

        if (retry_count >= max_retry_count)
          break;

        usleep(100000);
      }
    }
  }

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

  // Start the communications read thread so all incoming data can be parsed
  // into packets and queued as they arrive.
  if (GetTarget().GetNonStopModeEnabled())
    m_gdb_comm.StartReadThread();

  // 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.SetErrorString("not connected to remote gdb server");
    return error;
  }

  // Send $QNonStop:1 packet on startup if required
  if (GetTarget().GetNonStopModeEnabled())
    GetTarget().SetNonStopModeEnabled(m_gdb_comm.SetNonStopMode(true));

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

  // Ask the remote server for the default thread id
  if (GetTarget().GetNonStopModeEnabled())
    m_gdb_comm.GetDefaultThreadId(m_initial_tid);

  size_t num_cmds = GetExtraStartupCommands().GetArgumentCount();
  for (size_t idx = 0; idx < num_cmds; idx++) {
    StringExtractorGDBRemote response;
    m_gdb_comm.SendPacketAndWaitForResponse(
        GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false);
  }
  return error;
}

void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
  if (log)
    log->Printf("ProcessGDBRemote::%s()", __FUNCTION__);
  if (GetID() != LLDB_INVALID_PROCESS_ID) {
    BuildDynamicRegisterInfo(false);

    // See if the GDB server supports the qHostInfo information

    // See if the GDB server supports the qProcessInfo packet, if so prefer
    // that over the Host information 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;
      if (log)
        log->Printf("ProcessGDBRemote::%s gdb-remote had process architecture, "
                    "using %s %s",
                    __FUNCTION__, process_arch.GetArchitectureName()
                                      ? process_arch.GetArchitectureName()
                                      : "<null>",
                    process_arch.GetTriple().getTriple().c_str()
                        ? process_arch.GetTriple().getTriple().c_str()
                        : "<null>");
    } else {
      process_arch = m_gdb_comm.GetHostArchitecture();
      if (log)
        log->Printf("ProcessGDBRemote::%s gdb-remote did not have process "
                    "architecture, using gdb-remote host architecture %s %s",
                    __FUNCTION__, process_arch.GetArchitectureName()
                                      ? process_arch.GetArchitectureName()
                                      : "<null>",
                    process_arch.GetTriple().getTriple().c_str()
                        ? process_arch.GetTriple().getTriple().c_str()
                        : "<null>");
    }

    if (process_arch.IsValid()) {
      const ArchSpec &target_arch = GetTarget().GetArchitecture();
      if (target_arch.IsValid()) {
        if (log)
          log->Printf(
              "ProcessGDBRemote::%s analyzing target arch, currently %s %s",
              __FUNCTION__, target_arch.GetArchitectureName()
                                ? target_arch.GetArchitectureName()
                                : "<null>",
              target_arch.GetTriple().getTriple().c_str()
                  ? target_arch.GetTriple().getTriple().c_str()
                  : "<null>");

        // 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);
          if (log)
            log->Printf("ProcessGDBRemote::%s remote process is ARM/Apple, "
                        "setting target arch to %s %s",
                        __FUNCTION__, process_arch.GetArchitectureName()
                                          ? process_arch.GetArchitectureName()
                                          : "<null>",
                        process_arch.GetTriple().getTriple().c_str()
                            ? process_arch.GetTriple().getTriple().c_str()
                            : "<null>");
        } 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);
          }
        }

        if (log)
          log->Printf("ProcessGDBRemote::%s final target arch after "
                      "adjustments for remote architecture: %s %s",
                      __FUNCTION__, target_arch.GetArchitectureName()
                                        ? target_arch.GetArchitectureName()
                                        : "<null>",
                      target_arch.GetTriple().getTriple().c_str()
                          ? target_arch.GetTriple().getTriple().c_str()
                          : "<null>");
      } 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);
      }
    }

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

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

Status ProcessGDBRemote::DoAttachToProcessWithID(
    lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) {
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
  Status error;

  if (log)
    log->Printf("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);
      m_async_broadcaster.BroadcastEvent(
          eBroadcastBitAsyncContinue, new EventDataBytes(packet, packet_len));
    } 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());

      m_async_broadcaster.BroadcastEvent(
          eBroadcastBitAsyncContinue,
          new EventDataBytes(packet.GetString().data(), packet.GetSize()));

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

lldb::user_id_t ProcessGDBRemote::StartTrace(const TraceOptions &options,
                                             Status &error) {
  return m_gdb_comm.SendStartTracePacket(options, error);
}

Status ProcessGDBRemote::StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) {
  return m_gdb_comm.SendStopTracePacket(uid, thread_id);
}

Status ProcessGDBRemote::GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
                                 llvm::MutableArrayRef<uint8_t> &buffer,
                                 size_t offset) {
  return m_gdb_comm.SendGetDataPacket(uid, thread_id, buffer, offset);
}

Status ProcessGDBRemote::GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
                                     llvm::MutableArrayRef<uint8_t> &buffer,
                                     size_t offset) {
  return m_gdb_comm.SendGetMetaDataPacket(uid, thread_id, buffer, offset);
}

Status ProcessGDBRemote::GetTraceConfig(lldb::user_id_t uid,
                                        TraceOptions &options) {
  return m_gdb_comm.SendGetTraceConfigPacket(uid, options);
}

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();
  return Status();
}

Status ProcessGDBRemote::DoResume() {
  Status error;
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
  if (log)
    log->Printf("ProcessGDBRemote::Resume()");

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

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

    StreamString continue_packet;
    bool continue_packet_error = false;
    if (m_gdb_comm.HasAnyVContSupport()) {
      if (!GetTarget().GetNonStopModeEnabled() &&
          (m_continue_c_tids.size() == 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, just send a "c" packet
        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.Printf(";c:%4.4" PRIx64, *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.Printf(";C%2.2x:%4.4" PRIx64, s_pos->second,
                                     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.Printf(";s:%4.4" PRIx64, *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.Printf(";S%2.2x:%4.4" PRIx64, s_pos->second,
                                     s_pos->first);
          } else
            continue_packet_error = true;
        }

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

    if (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
      const size_t num_continue_c_tids = m_continue_c_tids.size();
      const size_t num_continue_C_tids = m_continue_C_tids.size();
      const size_t num_continue_s_tids = m_continue_s_tids.size();
      const size_t num_continue_S_tids = m_continue_S_tids.size();
      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);

          // If in Non-Stop-Mode use vCont when stepping
          if (GetTarget().GetNonStopModeEnabled()) {
            if (m_gdb_comm.GetVContSupported('s'))
              continue_packet.PutCString("vCont;s");
            else
              continue_packet.PutChar('s');
          } else
            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 (continue_packet_error) {
      error.SetErrorString("can't make continue packet for this resume");
    } else {
      EventSP event_sp;
      if (!m_async_thread.IsJoinable()) {
        error.SetErrorString("Trying to resume but the async thread is dead.");
        if (log)
          log->Printf("ProcessGDBRemote::DoResume: Trying to resume but the "
                      "async thread is dead.");
        return error;
      }

      m_async_broadcaster.BroadcastEvent(
          eBroadcastBitAsyncContinue,
          new EventDataBytes(continue_packet.GetString().data(),
                             continue_packet.GetSize()));

      if (listener_sp->GetEvent(event_sp, std::chrono::seconds(5)) == false) {
        error.SetErrorString("Resume timed out.");
        if (log)
          log->Printf("ProcessGDBRemote::DoResume: Resume timed out.");
      } else if (event_sp->BroadcasterIs(&m_async_broadcaster)) {
        error.SetErrorString("Broadcast continue, but the async thread was "
                             "killed before we got an ack back.");
        if (log)
          log->Printf("ProcessGDBRemote::DoResume: Broadcast continue, but the "
                      "async thread was killed before we got an ack back.");
        return error;
      }
    }
  }

  return error;
}

void ProcessGDBRemote::HandleStopReplySequence() {
  while (true) {
    // Send vStopped
    StringExtractorGDBRemote response;
    m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false);

    // OK represents end of signal list
    if (response.IsOKResponse())
      break;

    // If not OK or a normal packet we have a problem
    if (!response.IsNormalResponse())
      break;

    SetLastStopPacket(response);
  }
}

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(std::string &value) {
  m_thread_ids.clear();
  size_t comma_pos;
  lldb::tid_t tid;
  while ((comma_pos = value.find(',')) != std::string::npos) {
    value[comma_pos] = '\0';
    // thread in big endian hex
    tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16);
    if (tid != LLDB_INVALID_THREAD_ID)
      m_thread_ids.push_back(tid);
    value.erase(0, comma_pos + 1);
  }
  tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16);
  if (tid != LLDB_INVALID_THREAD_ID)
    m_thread_ids.push_back(tid);
  return m_thread_ids.size();
}

size_t
ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue(std::string &value) {
  m_thread_pcs.clear();
  size_t comma_pos;
  lldb::addr_t pc;
  while ((comma_pos = value.find(',')) != std::string::npos) {
    value[comma_pos] = '\0';
    pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16);
    if (pc != LLDB_INVALID_ADDRESS)
      m_thread_pcs.push_back(pc);
    value.erase(0, comma_pos + 1);
  }
  pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16);
  if (pc != LLDB_INVALID_THREAD_ID)
    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

    // Lock the thread stack while we access it
    // Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex);
    std::unique_lock<std::recursive_mutex> stop_stack_lock(
        m_last_stop_packet_mutex, std::defer_lock);
    if (stop_stack_lock.try_lock()) {
      // Get the number of stop packets on the stack
      int nItems = m_stop_packet_stack.size();
      // Iterate over them
      for (int i = 0; i < nItems; i++) {
        // Get the thread stop info
        StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i];
        const std::string &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 != std::string::npos) {
          const size_t start = thread_pcs_pos + strlen(";thread-pcs:");
          const size_t end = stop_info_str.find(';', start);
          if (end != std::string::npos) {
            std::string value = stop_info_str.substr(start, end - start);
            UpdateThreadPCsFromStopReplyThreadsValue(value);
          }
        }

        const size_t threads_pos = stop_info_str.find(";threads:");
        if (threads_pos != std::string::npos) {
          const size_t start = threads_pos + strlen(";threads:");
          const size_t end = stop_info_str.find(';', start);
          if (end != std::string::npos) {
            std::string 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::UpdateThreadList(ThreadList &old_thread_list,
                                        ThreadList &new_thread_list) {
  // locker will keep a mutex locked until it goes out of scope
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_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) {
      tid_t tid = m_thread_ids[i];
      ThreadSP thread_sp(
          old_thread_list_copy.RemoveThreadByProtocolID(tid, false));
      if (!thread_sp) {
        thread_sp.reset(new ThreadGDBRemote(*this, 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.
    thread->GetRegisterContext()->InvalidateIfNeeded(true);
    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;
}

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) {
  ThreadSP thread_sp;
  if (tid != LLDB_INVALID_THREAD_ID) {
    // 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.reset(new ThreadGDBRemote(*this, tid));
        m_thread_list_real.AddThread(thread_sp);
      }
    }

    if (thread_sp) {
      ThreadGDBRemote *gdb_thread =
          static_cast<ThreadGDBRemote *>(thread_sp.get());
      gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true);

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

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

      thread_sp->SetName(thread_name.empty() ? NULL : 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
      if (!thread_sp->StopInfoIsUpToDate()) {
        thread_sp->SetStopInfo(StopInfoSP());
        // If there's a memory thread backed by this thread, we need to use it
        // to calculate StopInfo.
        if (ThreadSP memory_thread_sp =
                m_thread_list.GetBackingThread(thread_sp))
          thread_sp = memory_thread_sp;

        if (exc_type != 0) {
          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;
          if (!reason.empty()) {
            if (reason.compare("trace") == 0) {
              addr_t pc = thread_sp->GetRegisterContext()->GetPC();
              lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()
                                                      ->GetBreakpointSiteList()
                                                      .FindByAddress(pc);

              // If the current pc is a breakpoint site then the StopInfo
              // should be set to Breakpoint Otherwise, it will be set to
              // Trace.
              if (bp_site_sp &&
                  bp_site_sp->ValidForThisThread(thread_sp.get())) {
                thread_sp->SetStopInfo(
                    StopInfo::CreateStopReasonWithBreakpointSiteID(
                        *thread_sp, bp_site_sp->GetID()));
              } else
                thread_sp->SetStopInfo(
                    StopInfo::CreateStopReasonToTrace(*thread_sp));
              handled = true;
            } else if (reason.compare("breakpoint") == 0) {
              addr_t pc = thread_sp->GetRegisterContext()->GetPC();
              lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()
                                                      ->GetBreakpointSiteList()
                                                      .FindByAddress(pc);
              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.get())) {
                  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.compare("trap") == 0) {
              // Let the trap just use the standard signal stop reason below...
            } else if (reason.compare("watchpoint") == 0) {
              StringExtractor desc_extractor(description.c_str());
              addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
              uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32);
              addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
              watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
              if (wp_addr != LLDB_INVALID_ADDRESS) {
                WatchpointSP wp_sp;
                ArchSpec::Core core = GetTarget().GetArchitecture().GetCore();
                if ((core >= ArchSpec::kCore_mips_first &&
                     core <= ArchSpec::kCore_mips_last) ||
                    (core >= ArchSpec::eCore_arm_generic &&
                     core <= ArchSpec::eCore_arm_aarch64))
                  wp_sp = GetTarget().GetWatchpointList().FindByAddress(
                      wp_hit_addr);
                if (!wp_sp)
                  wp_sp =
                      GetTarget().GetWatchpointList().FindByAddress(wp_addr);
                if (wp_sp) {
                  wp_sp->SetHardwareIndex(wp_index);
                  watch_id = wp_sp->GetID();
                }
              }
              if (watch_id == LLDB_INVALID_WATCH_ID) {
                Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(
                    GDBR_LOG_WATCHPOINTS));
                if (log)
                  log->Printf("failed to find watchpoint");
              }
              thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID(
                  *thread_sp, watch_id, wp_hit_addr));
              handled = true;
            } else if (reason.compare("exception") == 0) {
              thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException(
                  *thread_sp, description.c_str()));
              handled = true;
            } else if (reason.compare("exec") == 0) {
              did_exec = true;
              thread_sp->SetStopInfo(
                  StopInfo::CreateStopReasonWithExec(*thread_sp));
              handled = true;
            }
          } else if (!signo) {
            addr_t pc = thread_sp->GetRegisterContext()->GetPC();
            lldb::BreakpointSiteSP bp_site_sp =
                thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(
                    pc);

            // If the current pc is a breakpoint site then the StopInfo should
            // be set to Breakpoint even though the remote stub did not set it
            // as such. This can happen when the thread is involuntarily
            // interrupted (e.g. due to stops on other threads) just as it is
            // about to execute the breakpoint instruction.
            if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) {
              thread_sp->SetStopInfo(
                  StopInfo::CreateStopReasonWithBreakpointSiteID(
                      *thread_sp, bp_site_sp->GetID()));
              handled = true;
            }
          }

          if (!handled && signo && did_exec == false) {
            if (signo == SIGTRAP) {
              // Currently we are going to assume SIGTRAP means we are either
              // hitting a breakpoint or hardware single stepping.
              handled = true;
              addr_t pc = thread_sp->GetRegisterContext()->GetPC() +
                          m_breakpoint_pc_offset;
              lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()
                                                      ->GetBreakpointSiteList()
                                                      .FindByAddress(pc);

              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.
                if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
                  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.
                // FIXME: We are still missing the case where we single step
                // over a trap instruction.
                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)
              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;
}

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

  // Stop with signal and thread info
  lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
  uint8_t signo = 0;
  std::string 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;
  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

  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](
                           ConstString key,
                           StructuredData::Object *object) -> bool {
    if (key == g_key_tid) {
      // thread in big endian hex
      tid = object->GetIntegerValue(LLDB_INVALID_THREAD_ID);
    } else if (key == g_key_metype) {
      // exception type in big endian hex
      exc_type = object->GetIntegerValue(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->GetIntegerValue());
          return true; // Keep iterating through all array items
        });
      }
    } else if (key == g_key_name) {
      thread_name = object->GetStringValue();
    } else if (key == g_key_qaddr) {
      thread_dispatch_qaddr = object->GetIntegerValue(LLDB_INVALID_ADDRESS);
    } else if (key == g_key_queue_name) {
      queue_vars_valid = true;
      queue_name = object->GetStringValue();
    } else if (key == g_key_queue_kind) {
      std::string queue_kind_str = 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->GetIntegerValue(0);
      if (queue_serial_number != 0)
        queue_vars_valid = true;
    } else if (key == g_key_dispatch_queue_t) {
      dispatch_queue_t = object->GetIntegerValue(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 = object->GetStringValue();
    } else if (key == g_key_description) {
      description = object->GetStringValue();
    } else if (key == g_key_registers) {
      StructuredData::Dictionary *registers_dict = object->GetAsDictionary();

      if (registers_dict) {
        registers_dict->ForEach(
            [&expedited_register_map](ConstString key,
                                      StructuredData::Object *object) -> bool {
              const uint32_t reg =
                  StringConvert::ToUInt32(key.GetCString(), UINT32_MAX, 10);
              if (reg != UINT32_MAX)
                expedited_register_map[reg] = 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;
                  DataBufferSP 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->GetIntegerValue(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) {
  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 is 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) {
        lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
        if (pid != LLDB_INVALID_PROCESS_ID)
          SetID(pid);
      }
      BuildDynamicRegisterInfo(true);
    }
    // Stop with signal and thread info
    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;
    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 in big endian hex
        if (value.getAsInteger(16, tid))
          tid = LLDB_INVALID_THREAD_ID;
      } else if (key.compare("threads") == 0) {
        std::lock_guard<std::recursive_mutex> guard(
            m_thread_list_real.GetMutex());

        m_thread_ids.clear();
        // A comma separated list of all threads in the current
        // process that includes the thread for this stop reply packet
        lldb::tid_t tid;
        while (!value.empty()) {
          llvm::StringRef tid_str;
          std::tie(tid_str, value) = value.split(',');
          if (tid_str.getAsInteger(16, tid))
            tid = LLDB_INVALID_THREAD_ID;
          m_thread_ids.push_back(tid);
        }
      } 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);
        std::string name;
        // Now convert the HEX bytes into a string value
        name_extractor.GetHexByteString(thread_name);
      } else if (key.compare("name") == 0) {
        thread_name = 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 = 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;
            DataBufferSP 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);

        WatchpointSP wp_sp =
            GetTarget().GetWatchpointList().FindByAddress(wp_addr);
        uint32_t wp_index = LLDB_INVALID_INDEX32;

        if (wp_sp)
          wp_index = wp_sp->GetHardwareIndex();

        reason = "watchpoint";
        StreamString ostr;
        ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index);
        description = ostr.GetString();
      } else if (key.compare("library") == 0) {
        LoadModules();
      } 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::move(value);
      }
    }

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

    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.

  // Scope for the lock
  {
    // Lock the thread stack while we access it
    std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
    // Get the number of stop packets on the stack
    int nItems = m_stop_packet_stack.size();
    // Iterate over them
    for (int i = 0; i < nItems; i++) {
      // Get the thread stop info
      StringExtractorGDBRemote stop_info = m_stop_packet_stack[i];
      // Process thread stop info
      SetThreadStopInfo(stop_info);
    }
    // Clear the thread stop stack
    m_stop_packet_stack.clear();
  }

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

  // 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 (m_public_state.GetValue() == eStateAttaching) {
    // We are being asked to halt during an attach. We need to just close our
    // file handle and debugserver will go away, and we can be done...
    m_gdb_comm.Disconnect();
  } else
    caused_stop = m_gdb_comm.Interrupt();
  return error;
}

Status ProcessGDBRemote::DoDetach(bool keep_stopped) {
  Status error;
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
  if (log)
    log->Printf("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
      log->Printf("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() {
  Status error;
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
  if (log)
    log->Printf("ProcessGDBRemote::DoDestroy()");

  // There is a bug in older iOS debugservers where they don't shut down the
  // process they are debugging properly.  If the process is sitting at a
  // breakpoint or an exception, this can cause problems with restarting.  So
  // we check to see if any of our threads are stopped at a breakpoint, and if
  // so we remove all the breakpoints, resume the process, and THEN destroy it
  // again.
  //
  // Note, we don't have a good way to test the version of debugserver, but I
  // happen to know that the set of all the iOS debugservers which don't
  // support GetThreadSuffixSupported() and that of the debugservers with this
  // bug are equal.  There really should be a better way to test this!
  //
  // We also use m_destroy_tried_resuming to make sure we only do this once, if
  // we resume and then halt and get called here to destroy again and we're
  // still at a breakpoint or exception, then we should just do the straight-
  // forward kill.
  //
  // And of course, if we weren't able to stop the process by the time we get
  // here, it isn't necessary (or helpful) to do any of this.

  if (!m_gdb_comm.GetThreadSuffixSupported() &&
      m_public_state.GetValue() != eStateRunning) {
    PlatformSP platform_sp = GetTarget().GetPlatform();

    // FIXME: These should be ConstStrings so we aren't doing strcmp'ing.
    if (platform_sp && platform_sp->GetName() &&
        platform_sp->GetName() == PlatformRemoteiOS::GetPluginNameStatic()) {
      if (m_destroy_tried_resuming) {
        if (log)
          log->PutCString("ProcessGDBRemote::DoDestroy() - Tried resuming to "
                          "destroy once already, not doing it again.");
      } else {
        // At present, the plans are discarded and the breakpoints disabled
        // Process::Destroy, but we really need it to happen here and it
        // doesn't matter if we do it twice.
        m_thread_list.DiscardThreadPlans();
        DisableAllBreakpointSites();

        bool stop_looks_like_crash = false;
        ThreadList &threads = GetThreadList();

        {
          std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());

          size_t num_threads = threads.GetSize();
          for (size_t i = 0; i < num_threads; i++) {
            ThreadSP thread_sp = threads.GetThreadAtIndex(i);
            StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
            StopReason reason = eStopReasonInvalid;
            if (stop_info_sp)
              reason = stop_info_sp->GetStopReason();
            if (reason == eStopReasonBreakpoint ||
                reason == eStopReasonException) {
              if (log)
                log->Printf(
                    "ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64
                    " stopped with reason: %s.",
                    thread_sp->GetProtocolID(), stop_info_sp->GetDescription());
              stop_looks_like_crash = true;
              break;
            }
          }
        }

        if (stop_looks_like_crash) {
          if (log)
            log->PutCString("ProcessGDBRemote::DoDestroy() - Stopped at a "
                            "breakpoint, continue and then kill.");
          m_destroy_tried_resuming = true;

          // If we are going to run again before killing, it would be good to
          // suspend all the threads before resuming so they won't get into
          // more trouble.  Sadly, for the threads stopped with the breakpoint
          // or exception, the exception doesn't get cleared if it is
          // suspended, so we do have to run the risk of letting those threads
          // proceed a bit.

          {
            std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());

            size_t num_threads = threads.GetSize();
            for (size_t i = 0; i < num_threads; i++) {
              ThreadSP thread_sp = threads.GetThreadAtIndex(i);
              StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
              StopReason reason = eStopReasonInvalid;
              if (stop_info_sp)
                reason = stop_info_sp->GetStopReason();
              if (reason != eStopReasonBreakpoint &&
                  reason != eStopReasonException) {
                if (log)
                  log->Printf("ProcessGDBRemote::DoDestroy() - Suspending "
                              "thread: 0x%4.4" PRIx64 " before running.",
                              thread_sp->GetProtocolID());
                thread_sp->SetResumeState(eStateSuspended);
              }
            }
          }
          Resume();
          return Destroy(false);
        }
      }
    }
  }

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

  if (m_gdb_comm.IsConnected()) {
    if (m_public_state.GetValue() != eStateAttaching) {
      StringExtractorGDBRemote response;
      bool send_async = true;
      GDBRemoteCommunication::ScopedTimeout(m_gdb_comm,
                                            std::chrono::seconds(3));

      if (m_gdb_comm.SendPacketAndWaitForResponse("k", response, send_async) ==
          GDBRemoteCommunication::PacketResult::Success) {
        char packet_cmd = response.GetChar(0);

        if (packet_cmd == 'W' || packet_cmd == 'X') {
#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);
            if (log)
              log->Printf("Reaped pid: %d, status: %d.\n", reap_pid, status);
          }
#endif
          SetLastStopPacket(response);
          ClearThreadIDList();
          exit_status = response.GetHexU8();
        } else {
          if (log)
            log->Printf("ProcessGDBRemote::DoDestroy - got unexpected response "
                        "to k packet: %s",
                        response.GetStringRef().c_str());
          exit_string.assign("got unexpected response to k packet: ");
          exit_string.append(response.GetStringRef());
        }
      } else {
        if (log)
          log->Printf("ProcessGDBRemote::DoDestroy - failed to send k packet");
        exit_string.assign("failed to send the k packet");
      }
    } else {
      if (log)
        log->Printf("ProcessGDBRemote::DoDestroy - killed or interrupted while "
                    "attaching");
      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();
  return error;
}

void ProcessGDBRemote::SetLastStopPacket(
    const StringExtractorGDBRemote &response) {
  const bool did_exec =
      response.GetStringRef().find(";reason:exec;") != std::string::npos;
  if (did_exec) {
    Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
    if (log)
      log->Printf("ProcessGDBRemote::SetLastStopPacket () - detected exec");

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

  // Scope the lock
  {
    // Lock the thread stack while we access it
    std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);

    // We are are not using non-stop mode, there can only be one last stop
    // reply packet, so clear the list.
    if (GetTarget().GetNonStopModeEnabled() == false)
      m_stop_packet_stack.clear();

    // Add this stop packet to the stop packet stack This stack will get popped
    // and examined when we switch to the Stopped state
    m_stop_packet_stack.push_back(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) {
    LoadedModuleInfoList list;
    if (GetLoadedModuleList(list).Success())
      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) {
  GetMaxMemorySize();
  bool binary_memory_read = m_gdb_comm.GetxPacketSupported();
  // M and m packets take 2 bytes for 1 byte of memory
  size_t max_memory_size =
      binary_memory_read ? 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,
                          binary_memory_read ? '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, true) ==
      GDBRemoteCommunication::PacketResult::Success) {
    if (response.IsNormalResponse()) {
      error.Clear();
      if (binary_memory_read) {
        // The lower level GDBRemoteCommunication packet receive layer has
        // already de-quoted any 0x7d character escaping that was present in
        // the packet

        size_t data_received_size = response.GetBytesLeft();
        if (data_received_size > size) {
          // Don't write past the end of BUF if the remote debug server gave us
          // too much data for some reason.
          data_received_size = size;
        }
        memcpy(buf, response.GetStringRef().data(), data_received_size);
        return data_received_size;
      } else {
        return response.GetHexBytes(
            llvm::MutableArrayRef<uint8_t>((uint8_t *)buf, size), '\xdd');
      }
    } else if (response.IsErrorResponse())
      error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr);
    else if (response.IsUnsupportedResponse())
      error.SetErrorStringWithFormat(
          "GDB server does not support reading memory");
    else
      error.SetErrorStringWithFormat(
          "unexpected response to GDB server memory read packet '%s': '%s'",
          packet, response.GetStringRef().c_str());
  } else {
    error.SetErrorStringWithFormat("failed to send packet: '%s'", packet);
  }
  return 0;
}

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.
  std::stable_sort(
      std::begin(entries), std::end(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.SetErrorString("Unable to erase flash in multiple regions");
    return status;
  }

  uint64_t blocksize = region.GetBlocksize();
  if (blocksize == 0) {
    status.SetErrorString("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,
                                              true) ==
      GDBRemoteCommunication::PacketResult::Success) {
    if (response.IsOKResponse()) {
      m_erased_flash_ranges.Insert(range, true);
    } else {
      if (response.IsErrorResponse())
        status.SetErrorStringWithFormat("flash erase failed for 0x%" PRIx64,
                                        addr);
      else if (response.IsUnsupportedResponse())
        status.SetErrorStringWithFormat("GDB server does not support flashing");
      else
        status.SetErrorStringWithFormat(
            "unexpected response to GDB server flash erase packet '%s': '%s'",
            packet.GetData(), response.GetStringRef().c_str());
    }
  } else {
    status.SetErrorStringWithFormat("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, true) ==
      GDBRemoteCommunication::PacketResult::Success) {
    if (response.IsOKResponse()) {
      m_erased_flash_ranges.Clear();
    } else {
      if (response.IsErrorResponse())
        status.SetErrorStringWithFormat("flash done failed");
      else if (response.IsUnsupportedResponse())
        status.SetErrorStringWithFormat("GDB server does not support flashing");
      else
        status.SetErrorStringWithFormat(
            "unexpected response to GDB server flash done packet: '%s'",
            response.GetStringRef().c_str());
    }
  } else {
    status.SetErrorStringWithFormat("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.SetErrorString("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,
                                              true) ==
      GDBRemoteCommunication::PacketResult::Success) {
    if (response.IsOKResponse()) {
      error.Clear();
      return size;
    } else if (response.IsErrorResponse())
      error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64,
                                     addr);
    else if (response.IsUnsupportedResponse())
      error.SetErrorStringWithFormat(
          "GDB server does not support writing memory");
    else
      error.SetErrorStringWithFormat(
          "unexpected response to GDB server memory write packet '%s': '%s'",
          packet.GetData(), response.GetStringRef().c_str());
  } else {
    error.SetErrorStringWithFormat("failed to send packet: '%s'",
                                   packet.GetData());
  }
  return 0;
}

lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size,
                                                uint32_t permissions,
                                                Status &error) {
  Log *log(
      GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_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;
      if (log)
        log->Printf("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.SetErrorStringWithFormat(
        "unable to allocate %" PRIu64 " bytes of memory with permissions %s",
        (uint64_t)size, GetPermissionsAsCString(permissions));
  else
    error.Clear();
  return allocated_addr;
}

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

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

Status ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num) {

  Status error(m_gdb_comm.GetWatchpointSupportInfo(num));
  return error;
}

Status ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num, bool &after) {
  Status error(m_gdb_comm.GetWatchpointSupportInfo(
      num, after, GetTarget().GetArchitecture()));
  return error;
}

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.SetErrorString(
        "tried to deallocate memory without ever allocating memory");
    break;

  case eLazyBoolYes:
    if (!m_gdb_comm.DeallocateMemory(addr))
      error.SetErrorStringWithFormat(
          "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.SetErrorStringWithFormat(
            "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.Write(src, src_len, status, NULL);
  } 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 != NULL);

  // Get logging info
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_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
  if (log)
    log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64
                ") address = 0x%" PRIx64,
                site_id, (uint64_t)addr);

  // Breakpoint already exists and is enabled
  if (bp_site->IsEnabled()) {
    if (log)
      log->Printf("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);
    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.SetErrorStringWithFormat(
            "error: %d sending the breakpoint request", errno);
      else
        error.SetErrorString("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.
    if (log)
      log->Printf("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);
    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.SetErrorStringWithFormat(
            "error: %d sending the hardware breakpoint request "
            "(hardware breakpoint resources might be exhausted or unavailable)",
            error_no);
      else
        error.SetErrorString("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
    if (log)
      log->Printf("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.SetErrorString("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 != NULL);
  addr_t addr = bp_site->GetLoadAddress();
  user_id_t site_id = bp_site->GetID();
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
  if (log)
    log->Printf("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))
        error.SetErrorToGenericError();
      break;

    case BreakpointSite::eExternal: {
      GDBStoppointType stoppoint_type;
      if (bp_site->IsHardware())
        stoppoint_type = eBreakpointHardware;
      else
        stoppoint_type = eBreakpointSoftware;

      if (m_gdb_comm.SendGDBStoppointTypePacket(stoppoint_type, false, addr,
                                                bp_op_size))
        error.SetErrorToGenericError();
    } break;
    }
    if (error.Success())
      bp_site->SetEnabled(false);
  } else {
    if (log)
      log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64
                  ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)",
                  site_id, (uint64_t)addr);
    return error;
  }

  if (error.Success())
    error.SetErrorToGenericError();
  return error;
}

// Pre-requisite: wp != NULL.
static GDBStoppointType GetGDBStoppointType(Watchpoint *wp) {
  assert(wp);
  bool watch_read = wp->WatchpointRead();
  bool watch_write = wp->WatchpointWrite();

  // watch_read and watch_write cannot both be false.
  assert(watch_read || watch_write);
  if (watch_read && watch_write)
    return eWatchpointReadWrite;
  else if (watch_read)
    return eWatchpointRead;
  else // Must be watch_write, then.
    return eWatchpointWrite;
}

Status ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) {
  Status error;
  if (wp) {
    user_id_t watchID = wp->GetID();
    addr_t addr = wp->GetLoadAddress();
    Log *log(
        ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
    if (log)
      log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")",
                  watchID);
    if (wp->IsEnabled()) {
      if (log)
        log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64
                    ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
                    watchID, (uint64_t)addr);
      return error;
    }

    GDBStoppointType type = GetGDBStoppointType(wp);
    // Pass down an appropriate z/Z packet...
    if (m_gdb_comm.SupportsGDBStoppointPacket(type)) {
      if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr,
                                                wp->GetByteSize()) == 0) {
        wp->SetEnabled(true, notify);
        return error;
      } else
        error.SetErrorString("sending gdb watchpoint packet failed");
    } else
      error.SetErrorString("watchpoints not supported");
  } else {
    error.SetErrorString("Watchpoint argument was NULL.");
  }
  if (error.Success())
    error.SetErrorToGenericError();
  return error;
}

Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) {
  Status error;
  if (wp) {
    user_id_t watchID = wp->GetID();

    Log *log(
        ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));

    addr_t addr = wp->GetLoadAddress();

    if (log)
      log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64
                  ") addr = 0x%8.8" PRIx64,
                  watchID, (uint64_t)addr);

    if (!wp->IsEnabled()) {
      if (log)
        log->Printf("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->SetEnabled(false, notify);
      return error;
    }

    if (wp->IsHardware()) {
      GDBStoppointType type = GetGDBStoppointType(wp);
      // Pass down an appropriate z/Z packet...
      if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr,
                                                wp->GetByteSize()) == 0) {
        wp->SetEnabled(false, notify);
        return error;
      } else
        error.SetErrorString("sending gdb watchpoint packet failed");
    }
    // TODO: clear software watchpoints if we implement them
  } else {
    error.SetErrorString("Watchpoint argument was NULL.");
  }
  if (error.Success())
    error.SetErrorToGenericError();
  return error;
}

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

Status ProcessGDBRemote::DoSignal(int signo) {
  Status error;
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
  if (log)
    log->Printf("ProcessGDBRemote::DoSignal (signal = %d)", signo);

  if (!m_gdb_comm.SendAsyncSignal(signo))
    error.SetErrorStringWithFormat("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("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;
}
#if !defined(_WIN32)
#define USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 1
#endif

#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
static bool SetCloexecFlag(int fd) {
#if defined(FD_CLOEXEC)
  int flags = ::fcntl(fd, F_GETFD);
  if (flags == -1)
    return false;
  return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0);
#else
  return false;
#endif
}
#endif

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

  Status error;
  if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID) {
    // If we locate debugserver, keep that located version around
    static FileSpec g_debugserver_file_spec;

    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, _4), false);
    debugserver_launch_info.SetUserID(process_info.GetUserID());

    int communication_fd = -1;
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
    // Use a socketpair on non-Windows systems for security and performance
    // reasons.
    int sockets[2]; /* the pair of socket descriptors */
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
      error.SetErrorToErrno();
      return error;
    }

    int our_socket = sockets[0];
    int gdb_socket = sockets[1];
    CleanUp cleanup_our(close, our_socket);
    CleanUp cleanup_gdb(close, gdb_socket);

    // Don't let any child processes inherit our communication socket
    SetCloexecFlag(our_socket);
    communication_fd = gdb_socket;
#endif

    error = m_gdb_comm.StartDebugserverProcess(
        nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info,
        nullptr, nullptr, communication_fd);

    if (error.Success())
      m_debugserver_pid = debugserver_launch_info.GetProcessID();
    else
      m_debugserver_pid = LLDB_INVALID_PROCESS_ID;

    if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) {
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
      // Our process spawned correctly, we can now set our connection to use
      // our end of the socket pair
      cleanup_our.disable();
      m_gdb_comm.SetConnection(new ConnectionFileDescriptor(our_socket, true));
#endif
      StartAsyncThread();
    }

    if (error.Fail()) {
      Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));

      if (log)
        log->Printf("failed to start debugserver process: %s",
                    error.AsCString());
      return error;
    }

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

bool ProcessGDBRemote::MonitorDebugserverProcess(
    std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t debugserver_pid,
    bool exited,    // True if the process did exit
    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(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
  const bool handled = true;

  if (log)
    log->Printf("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();
  if (log)
    log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__,
                static_cast<void *>(process_sp.get()));
  if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid)
    return handled;

  // 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.
  usleep(500000);
  // 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) {
    char error_str[1024];
    if (signo) {
      const char *signal_cstr =
          process_sp->GetUnixSignals()->GetSignalAsCString(signo);
      if (signal_cstr)
        ::snprintf(error_str, sizeof(error_str),
                   DEBUGSERVER_BASENAME " died with signal %s", signal_cstr);
      else
        ::snprintf(error_str, sizeof(error_str),
                   DEBUGSERVER_BASENAME " died with signal %i", signo);
    } else {
      ::snprintf(error_str, sizeof(error_str),
                 DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x",
                 exit_status);
    }

    process_sp->SetExitStatus(-1, error_str);
  }
  // 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;
  return handled;
}

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() {
  static llvm::once_flag g_once_flag;

  llvm::call_once(g_once_flag, []() {
    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(),
        ConstString("Properties for the gdb-remote process plug-in."),
        is_global_setting);
  }
}

bool ProcessGDBRemote::StartAsyncThread() {
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));

  if (log)
    log->Printf("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).

    m_async_thread =
        ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>",
                                     ProcessGDBRemote::AsyncThread, this, NULL);
  } else if (log)
    log->Printf("ProcessGDBRemote::%s () - Called when Async thread was "
                "already running.",
                __FUNCTION__);

  return m_async_thread.IsJoinable();
}

void ProcessGDBRemote::StopAsyncThread() {
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));

  if (log)
    log->Printf("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 if (log)
    log->Printf(
        "ProcessGDBRemote::%s () - Called when Async thread was not running.",
        __FUNCTION__);
}

bool ProcessGDBRemote::HandleNotifyPacket(StringExtractorGDBRemote &packet) {
  // get the packet at a string
  const std::string &pkt = packet.GetStringRef();
  // skip %stop:
  StringExtractorGDBRemote stop_info(pkt.c_str() + 5);

  // pass as a thread stop info packet
  SetLastStopPacket(stop_info);

  // check for more stop reasons
  HandleStopReplySequence();

  // if the process is stopped then we need to fake a resume so that we can
  // stop properly with the new break. This is possible due to
  // SetPrivateState() broadcasting the state change as a side effect.
  if (GetPrivateState() == lldb::StateType::eStateStopped) {
    SetPrivateState(lldb::StateType::eStateRunning);
  }

  // since we have some stopped packets we can halt the process
  SetPrivateState(lldb::StateType::eStateStopped);

  return true;
}

thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
  ProcessGDBRemote *process = (ProcessGDBRemote *)arg;

  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
  if (log)
    log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
                ") thread starting...",
                __FUNCTION__, arg, process->GetID());

  EventSP event_sp;
  bool done = false;
  while (!done) {
    if (log)
      log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
                  ") listener.WaitForEvent (NULL, event_sp)...",
                  __FUNCTION__, arg, process->GetID());
    if (process->m_async_listener_sp->GetEvent(event_sp, llvm::None)) {
      const uint32_t event_type = event_sp->GetType();
      if (event_sp->BroadcasterIs(&process->m_async_broadcaster)) {
        if (log)
          log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
                      ") Got an event of type: %d...",
                      __FUNCTION__, arg, process->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();
            if (log)
              log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
                          ") got eBroadcastBitAsyncContinue: %s",
                          __FUNCTION__, arg, process->GetID(), continue_cstr);

            if (::strstr(continue_cstr, "vAttach") == NULL)
              process->SetPrivateState(eStateRunning);
            StringExtractorGDBRemote response;

            // If in Non-Stop-Mode
            if (process->GetTarget().GetNonStopModeEnabled()) {
              // send the vCont packet
              if (!process->GetGDBRemote().SendvContPacket(
                      llvm::StringRef(continue_cstr, continue_cstr_len),
                      response)) {
                // Something went wrong
                done = true;
                break;
              }
            }
            // If in All-Stop-Mode
            else {
              StateType stop_state =
                  process->GetGDBRemote().SendContinuePacketAndWaitForResponse(
                      *process, *process->GetUnixSignals(),
                      llvm::StringRef(continue_cstr, continue_cstr_len),
                      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
              // process->SetLastStopPacket()...
              process->ClearThreadIDList();

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

              case eStateExited: {
                process->SetLastStopPacket(response);
                process->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);
                  }
                }
                process->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") != NULL &&
                    response.GetError() == 0x87) {
                  process->SetExitStatus(-1, "cannot attach to process due to "
                                             "System Integrity Protection");
                } else if (::strstr(continue_cstr, "vAttach") != NULL &&
                           response.GetStatus().Fail()) {
                  process->SetExitStatus(-1, response.GetStatus().AsCString());
                } else {
                  process->SetExitStatus(-1, "lost connection");
                }
                break;
              }

              default:
                process->SetPrivateState(stop_state);
                break;
              } // switch(stop_state)
            }   // else // if in All-stop-mode
          }     // if (continue_packet)
        }       // case eBroadcastBitAysncContinue
        break;

        case eBroadcastBitAsyncThreadShouldExit:
          if (log)
            log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
                        ") got eBroadcastBitAsyncThreadShouldExit...",
                        __FUNCTION__, arg, process->GetID());
          done = true;
          break;

        default:
          if (log)
            log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
                        ") got unknown event 0x%8.8x",
                        __FUNCTION__, arg, process->GetID(), event_type);
          done = true;
          break;
        }
      } else if (event_sp->BroadcasterIs(&process->m_gdb_comm)) {
        switch (event_type) {
        case Communication::eBroadcastBitReadThreadDidExit:
          process->SetExitStatus(-1, "lost connection");
          done = true;
          break;

        case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify: {
          lldb_private::Event *event = event_sp.get();
          const EventDataBytes *continue_packet =
              EventDataBytes::GetEventDataFromEvent(event);
          StringExtractorGDBRemote notify(
              (const char *)continue_packet->GetBytes());
          // Hand this over to the process to handle
          process->HandleNotifyPacket(notify);
          break;
        }

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

  if (log)
    log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
                ") thread exiting...",
                __FUNCTION__, arg, process->GetID());

  return NULL;
}

// 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(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
  if (log)
    log->Printf("Hit New Thread Notification breakpoint.");
  return false;
}

Status ProcessGDBRemote::UpdateAutomaticSignalFiltering() {
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_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(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
  if (m_thread_create_bp_sp) {
    if (log && log->GetVerbose())
      log->Printf("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())
          log->Printf(
              "Successfully created new thread notification breakpoint %i",
              m_thread_create_bp_sp->GetID());
        m_thread_create_bp_sp->SetCallback(
            ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true);
      } else {
        if (log)
          log->Printf("Failed to create new thread notification breakpoint.");
      }
    }
  }
  return m_thread_create_bp_sp.get() != NULL;
}

bool ProcessGDBRemote::StopNoticingNewThreads() {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
  if (log && log->GetVerbose())
    log->Printf("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_ap.get() == NULL)
    m_dyld_ap.reset(DynamicLoader::FindPlugin(this, NULL));
  return m_dyld_ap.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.SetErrorString("Sending events is not supported for this process.");
    else
      error.SetErrorStringWithFormat("Error sending event data: %d.",
                                     return_value);
  }
  return error;
}

const DataBufferSP ProcessGDBRemote::GetAuxvData() {
  DataBufferSP buf;
  if (m_gdb_comm.GetQXferAuxvReadSupported()) {
    std::string response_string;
    if (m_gdb_comm.SendPacketsAndConcatenateResponses("qXfer:auxv:read::",
                                                      response_string) ==
        GDBRemoteCommunication::PacketResult::Success)
      buf.reset(new DataBufferHeap(response_string.c_str(),
                                   response_string.length()));
  }
  return buf;
}

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,
                                                false) ==
        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) {
    StructuredData::ObjectSP addr_sp(new StructuredData::Integer(addr));
    addresses->AddItem(addr_sp);
  }

  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,
                                                false) ==
        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() {
  StructuredData::ObjectSP object_sp;
  StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());

  if (m_gdb_comm.GetSharedCacheInfoSupported()) {
    StreamString packet;
    packet << "jGetSharedCacheInfo:";
    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,
                                                false) ==
        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;
}

Status ProcessGDBRemote::ConfigureStructuredData(
    const ConstString &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(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(
            GDBR_LOG_COMM | GDBR_LOG_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 = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_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)) {
    if (log)
      log->Printf("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);
    log->Printf("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();
}

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

bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
                    GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp,
                    uint32_t &cur_reg_num, uint32_t &reg_offset) {
  if (!feature_node)
    return false;

  feature_node.ForEachChildElementWithName(
      "reg", [&target_info, &dyn_reg_info, &cur_reg_num, &reg_offset,
              &abi_sp](const XMLNode &reg_node) -> bool {
        std::string gdb_group;
        std::string gdb_type;
        ConstString reg_name;
        ConstString alt_name;
        ConstString set_name;
        std::vector<uint32_t> value_regs;
        std::vector<uint32_t> invalidate_regs;
        std::vector<uint8_t> dwarf_opcode_bytes;
        bool encoding_set = false;
        bool format_set = false;
        RegisterInfo reg_info = {
            NULL,          // Name
            NULL,          // Alt name
            0,             // byte size
            reg_offset,    // offset
            eEncodingUint, // encoding
            eFormatHex,    // format
            {
                LLDB_INVALID_REGNUM, // eh_frame reg num
                LLDB_INVALID_REGNUM, // DWARF reg num
                LLDB_INVALID_REGNUM, // generic reg num
                cur_reg_num,         // process plugin reg num
                cur_reg_num          // native register number
            },
            NULL,
            NULL,
            NULL, // Dwarf Expression opcode bytes pointer
            0     // Dwarf Expression opcode bytes length
        };

        reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type,
                                   &reg_name, &alt_name, &set_name, &value_regs,
                                   &invalidate_regs, &encoding_set, &format_set,
                                   &reg_info, &reg_offset, &dwarf_opcode_bytes](
                                      const llvm::StringRef &name,
                                      const llvm::StringRef &value) -> bool {
          if (name == "name") {
            reg_name.SetString(value);
          } else if (name == "bitsize") {
            reg_info.byte_size =
                StringConvert::ToUInt32(value.data(), 0, 0) / CHAR_BIT;
          } else if (name == "type") {
            gdb_type = value.str();
          } else if (name == "group") {
            gdb_group = value.str();
          } else if (name == "regnum") {
            const uint32_t regnum =
                StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
            if (regnum != LLDB_INVALID_REGNUM) {
              reg_info.kinds[eRegisterKindProcessPlugin] = regnum;
            }
          } else if (name == "offset") {
            reg_offset = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
          } else if (name == "altname") {
            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;
            Format format = eFormatInvalid;
            if (OptionArgParser::ToFormat(value.data(), format, NULL).Success())
              reg_info.format = format;
            else if (value == "vector-sint8")
              reg_info.format = eFormatVectorOfSInt8;
            else if (value == "vector-uint8")
              reg_info.format = eFormatVectorOfUInt8;
            else if (value == "vector-sint16")
              reg_info.format = eFormatVectorOfSInt16;
            else if (value == "vector-uint16")
              reg_info.format = eFormatVectorOfUInt16;
            else if (value == "vector-sint32")
              reg_info.format = eFormatVectorOfSInt32;
            else if (value == "vector-uint32")
              reg_info.format = eFormatVectorOfUInt32;
            else if (value == "vector-float32")
              reg_info.format = eFormatVectorOfFloat32;
            else if (value == "vector-uint64")
              reg_info.format = eFormatVectorOfUInt64;
            else if (value == "vector-uint128")
              reg_info.format = eFormatVectorOfUInt128;
          } else if (name == "group_id") {
            const uint32_t set_id =
                StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
            RegisterSetMap::const_iterator pos =
                target_info.reg_set_map.find(set_id);
            if (pos != target_info.reg_set_map.end())
              set_name = pos->second.name;
          } else if (name == "gcc_regnum" || name == "ehframe_regnum") {
            reg_info.kinds[eRegisterKindEHFrame] =
                StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
          } else if (name == "dwarf_regnum") {
            reg_info.kinds[eRegisterKindDWARF] =
                StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
          } else if (name == "generic") {
            reg_info.kinds[eRegisterKindGeneric] =
                Args::StringToGenericRegister(value);
          } else if (name == "value_regnums") {
            SplitCommaSeparatedRegisterNumberString(value, value_regs, 0);
          } else if (name == "invalidate_regnums") {
            SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0);
          } else if (name == "dynamic_size_dwarf_expr_bytes") {
            StringExtractor opcode_extractor;
            std::string opcode_string = value.str();
            size_t dwarf_opcode_len = opcode_string.length() / 2;
            assert(dwarf_opcode_len > 0);

            dwarf_opcode_bytes.resize(dwarf_opcode_len);
            reg_info.dynamic_size_dwarf_len = dwarf_opcode_len;
            opcode_extractor.GetStringRef().swap(opcode_string);
            uint32_t ret_val =
                opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes);
            assert(dwarf_opcode_len == ret_val);
            UNUSED_IF_ASSERT_DISABLED(ret_val);
            reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data();
          } else {
            printf("unhandled attribute %s = %s\n", name.data(), value.data());
          }
          return true; // Keep iterating through all attributes
        });

        if (!gdb_type.empty() && !(encoding_set || format_set)) {
          if (gdb_type.find("int") == 0) {
            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 == "i387_ext" || gdb_type == "float") {
            reg_info.format = eFormatFloat;
            reg_info.encoding = eEncodingIEEE754;
          }
        }

        // 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 (!set_name && !gdb_group.empty())
          set_name.SetCString(gdb_group.c_str());

        reg_info.byte_offset = reg_offset;
        assert(reg_info.byte_size != 0);
        reg_offset += reg_info.byte_size;
        if (!value_regs.empty()) {
          value_regs.push_back(LLDB_INVALID_REGNUM);
          reg_info.value_regs = value_regs.data();
        }
        if (!invalidate_regs.empty()) {
          invalidate_regs.push_back(LLDB_INVALID_REGNUM);
          reg_info.invalidate_regs = invalidate_regs.data();
        }

        ++cur_reg_num;
        AugmentRegisterInfoViaABI(reg_info, reg_name, abi_sp);
        dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);

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

} // namespace {}

// query the target of gdb-remote for extended target information return:
// 'true'  on success
//          'false' on failure
bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
  // Make sure LLDB has an XML parser it can use first
  if (!XMLDocument::XMLEnabled())
    return false;

  // redirect libxml2's error handler since the default prints to stdout

  GDBRemoteCommunicationClient &comm = m_gdb_comm;

  // check that we have extended feature read support
  if (!comm.GetQXferFeaturesReadSupported())
    return false;

  // request the target xml file
  std::string raw;
  lldb_private::Status lldberr;
  if (!comm.ReadExtFeature(ConstString("features"), ConstString("target.xml"),
                           raw, lldberr)) {
    return false;
  }

  XMLDocument xml_document;

  if (xml_document.ParseMemory(raw.c_str(), raw.size(), "target.xml")) {
    GdbServerTargetInfo target_info;

    XMLNode target_node = xml_document.GetRootElement("target");
    if (target_node) {
      std::vector<XMLNode> feature_nodes;
      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") {
          llvm::StringRef href = node.GetAttributeValue("href");
          if (!href.empty())
            target_info.includes.push_back(href.str());
        } 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 {
                      if (name == "id")
                        set_id = StringConvert::ToUInt32(value.data(),
                                                         UINT32_MAX, 0);
                      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
      });

      // If the target.xml includes an architecture entry like
      //   <architecture>i386:x86-64</architecture> (seen from VMWare ESXi)
      //   <architecture>arm</architecture> (seen from Segger JLink on unspecified arm board)
      // use that if we don't have anything better.
      if (!arch_to_use.IsValid() && !target_info.arch.empty()) {
        if (target_info.arch == "i386:x86-64")
        {
          // We don't have any information about vendor or OS.
          arch_to_use.SetTriple("x86_64--");
          GetTarget().MergeArchitecture(arch_to_use);
        }
      }

      // Initialize these outside of ParseRegisters, since they should not be
      // reset inside each include feature
      uint32_t cur_reg_num = 0;
      uint32_t reg_offset = 0;

      // 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.
      ABISP abi_to_use_sp = ABI::FindPlugin(shared_from_this(), arch_to_use);
      for (auto &feature_node : feature_nodes) {
        ParseRegisters(feature_node, target_info, this->m_register_info,
                       abi_to_use_sp, cur_reg_num, reg_offset);
      }

      for (const auto &include : target_info.includes) {
        // request register file
        std::string xml_data;
        if (!comm.ReadExtFeature(ConstString("features"), ConstString(include),
                                 xml_data, lldberr))
          continue;

        XMLDocument include_xml_document;
        include_xml_document.ParseMemory(xml_data.data(), xml_data.size(),
                                         include.c_str());
        XMLNode include_feature_node =
            include_xml_document.GetRootElement("feature");
        if (include_feature_node) {
          ParseRegisters(include_feature_node, target_info,
                         this->m_register_info, abi_to_use_sp, cur_reg_num,
                         reg_offset);
        }
      }
      this->m_register_info.Finalize(arch_to_use);
    }
  }

  return m_register_info.GetNumRegisters() > 0;
}

Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) {
  // Make sure LLDB has an XML parser it can use first
  if (!XMLDocument::XMLEnabled())
    return Status(0, ErrorType::eErrorTypeGeneric);

  Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS);
  if (log)
    log->Printf("ProcessGDBRemote::%s", __FUNCTION__);

  GDBRemoteCommunicationClient &comm = m_gdb_comm;

  // check that we have extended feature read support
  if (comm.GetQXferLibrariesSVR4ReadSupported()) {
    list.clear();

    // request the loaded library list
    std::string raw;
    lldb_private::Status lldberr;

    if (!comm.ReadExtFeature(ConstString("libraries-svr4"), ConstString(""),
                             raw, lldberr))
      return Status(0, ErrorType::eErrorTypeGeneric);

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

    if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
      return Status(0, ErrorType::eErrorTypeGeneric);

    XMLNode root_element = doc.GetRootElement("library-list-svr4");
    if (!root_element)
      return Status();

    // main link map structure
    llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm");
    if (!main_lm.empty()) {
      list.m_link_map =
          StringConvert::ToUInt64(main_lm.data(), LLDB_INVALID_ADDRESS, 0);
    }

    root_element.ForEachChildElementWithName(
        "library", [log, &list](const XMLNode &library) -> bool {

          LoadedModuleInfoList::LoadedModuleInfo module;

          library.ForEachAttribute(
              [&module](const llvm::StringRef &name,
                        const llvm::StringRef &value) -> bool {

                if (name == "name")
                  module.set_name(value.str());
                else if (name == "lm") {
                  // the address of the link_map struct.
                  module.set_link_map(StringConvert::ToUInt64(
                      value.data(), LLDB_INVALID_ADDRESS, 0));
                } else if (name == "l_addr") {
                  // the displacement as read from the field 'l_addr' of the
                  // link_map struct.
                  module.set_base(StringConvert::ToUInt64(
                      value.data(), LLDB_INVALID_ADDRESS, 0));
                  // 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_DYAMIC section.
                  module.set_dynamic(StringConvert::ToUInt64(
                      value.data(), LLDB_INVALID_ADDRESS, 0));
                }

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

            log->Printf("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)
      log->Printf("found %" PRId32 " modules in total",
                  (int)list.m_list.size());
  } else if (comm.GetQXferLibrariesReadSupported()) {
    list.clear();

    // request the loaded library list
    std::string raw;
    lldb_private::Status lldberr;

    if (!comm.ReadExtFeature(ConstString("libraries"), ConstString(""), raw,
                             lldberr))
      return Status(0, ErrorType::eErrorTypeGeneric);

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

    if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
      return Status(0, ErrorType::eErrorTypeGeneric);

    XMLNode root_element = doc.GetRootElement("library-list");
    if (!root_element)
      return Status();

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

          llvm::StringRef name = library.GetAttributeValue("name");
          module.set_name(name.str());

          // 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");
          llvm::StringRef address = section.GetAttributeValue("address");
          module.set_base(
              StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0));
          // 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);

            log->Printf("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)
      log->Printf("found %" PRId32 " modules in total",
                  (int)list.m_list.size());
  } else {
    return Status(0, ErrorType::eErrorTypeGeneric);
  }

  return Status();
}

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

size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) {
  using lldb_private::process_gdb_remote::ProcessGDBRemote;

  // request a list of loaded libraries from GDBServer
  if (GetLoadedModuleList(module_list).Fail())
    return 0;

  // 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, true);
    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) -> bool {
      lldb_private::ObjectFile *obj = module_sp->GetObjectFile();
      if (!obj)
        return true;

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

      lldb::ModuleSP module_copy_sp = module_sp;
      target.SetExecutableModule(module_copy_sp, false);
      return false;
    });

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

  return new_modules.GetSize();
}

size_t ProcessGDBRemote::LoadModules() {
  LoadedModuleInfoList module_list;
  return LoadModules(module_list);
}

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("Empty file name specified");

  StreamString packet;
  packet.PutCString("qFileLoadAddress:");
  packet.PutCStringAsRawHex8(file_path.c_str());

  StringExtractorGDBRemote response;
  if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
                                              false) !=
      GDBRemoteCommunication::PacketResult::Success)
    return Status("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(
        "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(
      "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.equals("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 = m_thread_id_to_used_usec_map[thread_id];
        }

        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_stream.str();
}

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

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

static StructuredData::ObjectSP
ParseStructuredDataPacket(llvm::StringRef packet) {
  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));

  if (!packet.consume_front(s_async_json_packet_prefix)) {
    if (log) {
      log->Printf(
          "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);
      json_str.Flush();
      log->Printf("ProcessGDBRemote::%s() "
                  "received Async StructuredData packet: %s",
                  __FUNCTION__, json_str.GetData());
    } else {
      log->Printf("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. ",
                            NULL),
        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() {}

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

  bool 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(
            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 true;
      }
    } else {
      result.AppendErrorWithFormat("'%s' takes no arguments",
                                   m_cmd_name.c_str());
    }
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

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. ", NULL) {}

  ~CommandObjectProcessGDBRemotePacketHistory() {}

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc == 0) {
      ProcessGDBRemote *process =
          (ProcessGDBRemote *)m_interpreter.GetExecutionContext()
              .GetProcessPtr();
      if (process) {
        process->GetGDBRemote().DumpHistory(result.GetOutputStream());
        result.SetStatus(eReturnStatusSuccessFinishResult);
        return true;
      }
    } else {
      result.AppendErrorWithFormat("'%s' takes no arguments",
                                   m_cmd_name.c_str());
    }
    result.SetStatus(eReturnStatusFailed);
    return false;
  }
};

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.",
            NULL) {}

  ~CommandObjectProcessGDBRemotePacketXferSize() {}

  bool 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());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    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, NULL, 10);
      if (errno == 0 && user_specified_max != 0) {
        process->SetUserSpecifiedMaxMemoryTransferSize(user_specified_max);
        result.SetStatus(eReturnStatusSuccessFinishResult);
        return true;
      }
    }
    result.SetStatus(eReturnStatusFailed);
    return false;
  }
};

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.",
                            NULL) {}

  ~CommandObjectProcessGDBRemotePacketSend() {}

  bool 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());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

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

        if (strstr(packet_cstr, "qGetProfileData") != NULL) {
          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().c_str());
      }
    }
    return true;
  }
};

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

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

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

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

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

class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword {
private:
public:
  CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "process plugin packet",
                               "Commands that deal with GDB remote packets.",
                               NULL) {
    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() {}
};

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

CommandObject *ProcessGDBRemote::GetPluginCommandObject() {
  if (!m_command_sp)
    m_command_sp.reset(new CommandObjectMultiwordProcessGDBRemote(
        GetTarget().GetDebugger().GetCommandInterpreter()));
  return m_command_sp.get();
}
