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

#include <errno.h>

#include "lldb/Host/Config.h"

#include "GDBRemoteCommunicationServerLLGS.h"
#include "lldb/Utility/StreamGDBRemote.h"

// C Includes
// C++ Includes
#include <chrono>
#include <cstring>
#include <thread>

// Other libraries and framework includes
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/State.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Debug.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/UriParser.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ScopedPrinter.h"

// Project includes
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "Utility/StringExtractorGDBRemote.h"

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

//----------------------------------------------------------------------
// GDBRemote Errors
//----------------------------------------------------------------------

namespace {
enum GDBRemoteServerError {
  // Set to the first unused error number in literal form below
  eErrorFirst = 29,
  eErrorNoProcess = eErrorFirst,
  eErrorResume,
  eErrorExitStatus
};
}

//----------------------------------------------------------------------
// GDBRemoteCommunicationServerLLGS constructor
//----------------------------------------------------------------------
GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(
    MainLoop &mainloop)
    : GDBRemoteCommunicationServerCommon("gdb-remote.server",
                                         "gdb-remote.server.rx_packet"),
      m_mainloop(mainloop), m_current_tid(LLDB_INVALID_THREAD_ID),
      m_continue_tid(LLDB_INVALID_THREAD_ID), m_debugged_process_mutex(),
      m_debugged_process_sp(), m_stdio_communication("process.stdio"),
      m_inferior_prev_state(StateType::eStateInvalid),
      m_saved_registers_map(), m_next_saved_registers_id(1),
      m_handshake_completed(false) {
  RegisterPacketHandlers();
}

void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
  RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_C,
                                &GDBRemoteCommunicationServerLLGS::Handle_C);
  RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_c,
                                &GDBRemoteCommunicationServerLLGS::Handle_c);
  RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_D,
                                &GDBRemoteCommunicationServerLLGS::Handle_D);
  RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_H,
                                &GDBRemoteCommunicationServerLLGS::Handle_H);
  RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_I,
                                &GDBRemoteCommunicationServerLLGS::Handle_I);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_interrupt,
      &GDBRemoteCommunicationServerLLGS::Handle_interrupt);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_m,
      &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
  RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M,
                                &GDBRemoteCommunicationServerLLGS::Handle_M);
  RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p,
                                &GDBRemoteCommunicationServerLLGS::Handle_p);
  RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_P,
                                &GDBRemoteCommunicationServerLLGS::Handle_P);
  RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
                                &GDBRemoteCommunicationServerLLGS::Handle_qC);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qfThreadInfo,
      &GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qFileLoadAddress,
      &GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
      &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo,
      &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfoSupported,
      &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
      &GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qRegisterInfo,
      &GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState,
      &GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_QSaveRegisterState,
      &GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR,
      &GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
      &GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qsThreadInfo,
      &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo,
      &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_jThreadsInfo,
      &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo,
      &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read,
      &GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read);
  RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_s,
                                &GDBRemoteCommunicationServerLLGS::Handle_s);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_stop_reason,
      &GDBRemoteCommunicationServerLLGS::Handle_stop_reason); // ?
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_vAttach,
      &GDBRemoteCommunicationServerLLGS::Handle_vAttach);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_vCont,
      &GDBRemoteCommunicationServerLLGS::Handle_vCont);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_vCont_actions,
      &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_x,
      &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
  RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z,
                                &GDBRemoteCommunicationServerLLGS::Handle_Z);
  RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z,
                                &GDBRemoteCommunicationServerLLGS::Handle_z);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_QPassSignals,
      &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals);

  RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
                        [this](StringExtractorGDBRemote packet, Status &error,
                               bool &interrupt, bool &quit) {
                          quit = true;
                          return this->Handle_k(packet);
                        });
}

Status
GDBRemoteCommunicationServerLLGS::SetLaunchArguments(const char *const args[],
                                                     int argc) {
  if ((argc < 1) || !args || !args[0] || !args[0][0])
    return Status("%s: no process command line specified to launch",
                  __FUNCTION__);

  m_process_launch_info.SetArguments(const_cast<const char **>(args), true);
  return Status();
}

Status
GDBRemoteCommunicationServerLLGS::SetLaunchFlags(unsigned int launch_flags) {
  m_process_launch_info.GetFlags().Set(launch_flags);
  return Status();
}

Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  if (!m_process_launch_info.GetArguments().GetArgumentCount())
    return Status("%s: no process command line specified to launch",
                  __FUNCTION__);

  const bool should_forward_stdio =
      m_process_launch_info.GetFileActionForFD(STDIN_FILENO) == nullptr ||
      m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr ||
      m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr;
  m_process_launch_info.SetLaunchInSeparateProcessGroup(true);
  m_process_launch_info.GetFlags().Set(eLaunchFlagDebug);

  const bool default_to_use_pty = true;
  m_process_launch_info.FinalizeFileActions(nullptr, default_to_use_pty);

  Status error;
  {
    std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex);
    assert(!m_debugged_process_sp && "lldb-server creating debugged "
                                     "process but one already exists");
    error = NativeProcessProtocol::Launch(m_process_launch_info, *this,
                                          m_mainloop, m_debugged_process_sp);
  }

  if (!error.Success()) {
    fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
            m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
    return error;
  }

  // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol
  // as needed.
  // llgs local-process debugging may specify PTY paths, which will make these
  // file actions non-null
  // process launch -i/e/o will also make these file actions non-null
  // nullptr means that the traffic is expected to flow over gdb-remote protocol
  if (should_forward_stdio) {
    // nullptr means it's not redirected to file or pty (in case of LLGS local)
    // at least one of stdio will be transferred pty<->gdb-remote
    // we need to give the pty master handle to this object to read and/or write
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
          " setting up stdout/stderr redirection via $O gdb-remote commands",
          __FUNCTION__, m_debugged_process_sp->GetID());

    // Setup stdout/stderr mapping from inferior to $O
    auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor();
    if (terminal_fd >= 0) {
      if (log)
        log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting "
                    "inferior STDIO fd to %d",
                    __FUNCTION__, terminal_fd);
      error = SetSTDIOFileDescriptor(terminal_fd);
      if (error.Fail())
        return error;
    } else {
      if (log)
        log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring "
                    "inferior STDIO since terminal fd reported as %d",
                    __FUNCTION__, terminal_fd);
    }
  } else {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " skipping stdout/stderr redirection via $O: inferior will "
                  "communicate over client-provided file descriptors",
                  __FUNCTION__, m_debugged_process_sp->GetID());
  }

  printf("Launched '%s' as process %" PRIu64 "...\n",
         m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
         m_process_launch_info.GetProcessID());

  return error;
}

Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
  Status error;

  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
  if (log)
    log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64,
                __FUNCTION__, pid);

  // Before we try to attach, make sure we aren't already monitoring something
  // else.
  if (m_debugged_process_sp &&
      m_debugged_process_sp->GetID() != LLDB_INVALID_PROCESS_ID)
    return Status("cannot attach to a process %" PRIu64
                  " when another process with pid %" PRIu64
                  " is being debugged.",
                  pid, m_debugged_process_sp->GetID());

  // Try to attach.
  error = NativeProcessProtocol::Attach(pid, *this, m_mainloop,
                                        m_debugged_process_sp);
  if (!error.Success()) {
    fprintf(stderr, "%s: failed to attach to process %" PRIu64 ": %s",
            __FUNCTION__, pid, error.AsCString());
    return error;
  }

  // Setup stdout/stderr mapping from inferior.
  auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor();
  if (terminal_fd >= 0) {
    if (log)
      log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting "
                  "inferior STDIO fd to %d",
                  __FUNCTION__, terminal_fd);
    error = SetSTDIOFileDescriptor(terminal_fd);
    if (error.Fail())
      return error;
  } else {
    if (log)
      log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring "
                  "inferior STDIO since terminal fd reported as %d",
                  __FUNCTION__, terminal_fd);
  }

  printf("Attached to process %" PRIu64 "...\n", pid);

  return error;
}

void GDBRemoteCommunicationServerLLGS::InitializeDelegate(
    NativeProcessProtocol *process) {
  assert(process && "process cannot be NULL");
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
  if (log) {
    log->Printf("GDBRemoteCommunicationServerLLGS::%s called with "
                "NativeProcessProtocol pid %" PRIu64 ", current state: %s",
                __FUNCTION__, process->GetID(),
                StateAsCString(process->GetState()));
  }
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::SendWResponse(
    NativeProcessProtocol *process) {
  assert(process && "process cannot be NULL");
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  // send W notification
  ExitType exit_type = ExitType::eExitTypeInvalid;
  int return_code = 0;
  std::string exit_description;

  const bool got_exit_info =
      process->GetExitStatus(&exit_type, &return_code, exit_description);
  if (!got_exit_info) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  ", failed to retrieve process exit status",
                  __FUNCTION__, process->GetID());

    StreamGDBRemote response;
    response.PutChar('E');
    response.PutHex8(GDBRemoteServerError::eErrorExitStatus);
    return SendPacketNoLock(response.GetString());
  } else {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  ", returning exit type %d, return code %d [%s]",
                  __FUNCTION__, process->GetID(), exit_type, return_code,
                  exit_description.c_str());

    StreamGDBRemote response;

    char return_type_code;
    switch (exit_type) {
    case ExitType::eExitTypeExit:
      return_type_code = 'W';
      break;
    case ExitType::eExitTypeSignal:
      return_type_code = 'X';
      break;
    case ExitType::eExitTypeStop:
      return_type_code = 'S';
      break;
    case ExitType::eExitTypeInvalid:
      return_type_code = 'E';
      break;
    }
    response.PutChar(return_type_code);

    // POSIX exit status limited to unsigned 8 bits.
    response.PutHex8(return_code);

    return SendPacketNoLock(response.GetString());
  }
}

static void AppendHexValue(StreamString &response, const uint8_t *buf,
                           uint32_t buf_size, bool swap) {
  int64_t i;
  if (swap) {
    for (i = buf_size - 1; i >= 0; i--)
      response.PutHex8(buf[i]);
  } else {
    for (i = 0; i < buf_size; i++)
      response.PutHex8(buf[i]);
  }
}

static void WriteRegisterValueInHexFixedWidth(
    StreamString &response, NativeRegisterContextSP &reg_ctx_sp,
    const RegisterInfo &reg_info, const RegisterValue *reg_value_p,
    lldb::ByteOrder byte_order) {
  RegisterValue reg_value;
  if (!reg_value_p) {
    Status error = reg_ctx_sp->ReadRegister(&reg_info, reg_value);
    if (error.Success())
      reg_value_p = &reg_value;
    // else log.
  }

  if (reg_value_p) {
    AppendHexValue(response, (const uint8_t *)reg_value_p->GetBytes(),
                   reg_value_p->GetByteSize(),
                   byte_order == lldb::eByteOrderLittle);
  } else {
    // Zero-out any unreadable values.
    if (reg_info.byte_size > 0) {
      std::basic_string<uint8_t> zeros(reg_info.byte_size, '\0');
      AppendHexValue(response, zeros.data(), zeros.size(), false);
    }
  }
}

static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));

  NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
  if (!reg_ctx_sp)
    return nullptr;

  JSONObject::SP register_object_sp = std::make_shared<JSONObject>();

#ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET
  // Expedite all registers in the first register set (i.e. should be GPRs) that
  // are not contained in other registers.
  const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0);
  if (!reg_set_p)
    return nullptr;
  for (const uint32_t *reg_num_p = reg_set_p->registers;
       *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) {
    uint32_t reg_num = *reg_num_p;
#else
  // Expedite only a couple of registers until we figure out why sending
  // registers is
  // expensive.
  static const uint32_t k_expedited_registers[] = {
      LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP,
      LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM};

  for (const uint32_t *generic_reg_p = k_expedited_registers;
       *generic_reg_p != LLDB_INVALID_REGNUM; ++generic_reg_p) {
    uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
        eRegisterKindGeneric, *generic_reg_p);
    if (reg_num == LLDB_INVALID_REGNUM)
      continue; // Target does not support the given register.
#endif

    const RegisterInfo *const reg_info_p =
        reg_ctx_sp->GetRegisterInfoAtIndex(reg_num);
    if (reg_info_p == nullptr) {
      if (log)
        log->Printf(
            "%s failed to get register info for register index %" PRIu32,
            __FUNCTION__, reg_num);
      continue;
    }

    if (reg_info_p->value_regs != nullptr)
      continue; // Only expedite registers that are not contained in other
                // registers.

    RegisterValue reg_value;
    Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value);
    if (error.Fail()) {
      if (log)
        log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s",
                    __FUNCTION__,
                    reg_info_p->name ? reg_info_p->name : "<unnamed-register>",
                    reg_num, error.AsCString());
      continue;
    }

    StreamString stream;
    WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p,
                                      &reg_value, lldb::eByteOrderBig);

    register_object_sp->SetObject(
        llvm::to_string(reg_num),
        std::make_shared<JSONString>(stream.GetString()));
  }

  return register_object_sp;
}

static const char *GetStopReasonString(StopReason stop_reason) {
  switch (stop_reason) {
  case eStopReasonTrace:
    return "trace";
  case eStopReasonBreakpoint:
    return "breakpoint";
  case eStopReasonWatchpoint:
    return "watchpoint";
  case eStopReasonSignal:
    return "signal";
  case eStopReasonException:
    return "exception";
  case eStopReasonExec:
    return "exec";
  case eStopReasonInstrumentation:
  case eStopReasonInvalid:
  case eStopReasonPlanComplete:
  case eStopReasonThreadExiting:
  case eStopReasonNone:
    break; // ignored
  }
  return nullptr;
}

static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process,
                                        bool abridged) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));

  JSONArray::SP threads_array_sp = std::make_shared<JSONArray>();

  // Ensure we can get info on the given thread.
  uint32_t thread_idx = 0;
  for (NativeThreadProtocolSP thread_sp;
       (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr;
       ++thread_idx) {

    lldb::tid_t tid = thread_sp->GetID();

    // Grab the reason this thread stopped.
    struct ThreadStopInfo tid_stop_info;
    std::string description;
    if (!thread_sp->GetStopReason(tid_stop_info, description))
      return nullptr;

    const int signum = tid_stop_info.details.signal.signo;
    if (log) {
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " tid %" PRIu64
                  " got signal signo = %d, reason = %d, exc_type = %" PRIu64,
                  __FUNCTION__, process.GetID(), tid, signum,
                  tid_stop_info.reason, tid_stop_info.details.exception.type);
    }

    JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>();
    threads_array_sp->AppendObject(thread_obj_sp);

    if (!abridged) {
      if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp))
        thread_obj_sp->SetObject("registers", registers_sp);
    }

    thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid));
    if (signum != 0)
      thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum));

    const std::string thread_name = thread_sp->GetName();
    if (!thread_name.empty())
      thread_obj_sp->SetObject("name",
                               std::make_shared<JSONString>(thread_name));

    if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason))
      thread_obj_sp->SetObject("reason",
                               std::make_shared<JSONString>(stop_reason_str));

    if (!description.empty())
      thread_obj_sp->SetObject("description",
                               std::make_shared<JSONString>(description));

    if ((tid_stop_info.reason == eStopReasonException) &&
        tid_stop_info.details.exception.type) {
      thread_obj_sp->SetObject(
          "metype",
          std::make_shared<JSONNumber>(tid_stop_info.details.exception.type));

      JSONArray::SP medata_array_sp = std::make_shared<JSONArray>();
      for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count;
           ++i) {
        medata_array_sp->AppendObject(std::make_shared<JSONNumber>(
            tid_stop_info.details.exception.data[i]));
      }
      thread_obj_sp->SetObject("medata", medata_array_sp);
    }

    // TODO: Expedite interesting regions of inferior memory
  }

  return threads_array_sp;
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
    lldb::tid_t tid) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));

  // Ensure we have a debugged process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
    return SendErrorResponse(50);

  if (log)
    log->Printf(
        "GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64
        " tid %" PRIu64,
        __FUNCTION__, m_debugged_process_sp->GetID(), tid);

  // Ensure we can get info on the given thread.
  NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadByID(tid));
  if (!thread_sp)
    return SendErrorResponse(51);

  // Grab the reason this thread stopped.
  struct ThreadStopInfo tid_stop_info;
  std::string description;
  if (!thread_sp->GetStopReason(tid_stop_info, description))
    return SendErrorResponse(52);

  // FIXME implement register handling for exec'd inferiors.
  // if (tid_stop_info.reason == eStopReasonExec)
  // {
  //     const bool force = true;
  //     InitializeRegisters(force);
  // }

  StreamString response;
  // Output the T packet with the thread
  response.PutChar('T');
  int signum = tid_stop_info.details.signal.signo;
  if (log) {
    log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                " tid %" PRIu64
                " got signal signo = %d, reason = %d, exc_type = %" PRIu64,
                __FUNCTION__, m_debugged_process_sp->GetID(), tid, signum,
                tid_stop_info.reason, tid_stop_info.details.exception.type);
  }

  // Print the signal number.
  response.PutHex8(signum & 0xff);

  // Include the tid.
  response.Printf("thread:%" PRIx64 ";", tid);

  // Include the thread name if there is one.
  const std::string thread_name = thread_sp->GetName();
  if (!thread_name.empty()) {
    size_t thread_name_len = thread_name.length();

    if (::strcspn(thread_name.c_str(), "$#+-;:") == thread_name_len) {
      response.PutCString("name:");
      response.PutCString(thread_name);
    } else {
      // The thread name contains special chars, send as hex bytes.
      response.PutCString("hexname:");
      response.PutCStringAsRawHex8(thread_name.c_str());
    }
    response.PutChar(';');
  }

  // If a 'QListThreadsInStopReply' was sent to enable this feature, we
  // will send all thread IDs back in the "threads" key whose value is
  // a list of hex thread IDs separated by commas:
  //  "threads:10a,10b,10c;"
  // This will save the debugger from having to send a pair of qfThreadInfo
  // and qsThreadInfo packets, but it also might take a lot of room in the
  // stop reply packet, so it must be enabled only on systems where there
  // are no limits on packet lengths.
  if (m_list_threads_in_stop_reply) {
    response.PutCString("threads:");

    uint32_t thread_index = 0;
    NativeThreadProtocolSP listed_thread_sp;
    for (listed_thread_sp =
             m_debugged_process_sp->GetThreadAtIndex(thread_index);
         listed_thread_sp; ++thread_index,
        listed_thread_sp = m_debugged_process_sp->GetThreadAtIndex(
            thread_index)) {
      if (thread_index > 0)
        response.PutChar(',');
      response.Printf("%" PRIx64, listed_thread_sp->GetID());
    }
    response.PutChar(';');

    // Include JSON info that describes the stop reason for any threads
    // that actually have stop reasons. We use the new "jstopinfo" key
    // whose values is hex ascii JSON that contains the thread IDs
    // thread stop info only for threads that have stop reasons. Only send
    // this if we have more than one thread otherwise this packet has all
    // the info it needs.
    if (thread_index > 0) {
      const bool threads_with_valid_stop_info_only = true;
      JSONArray::SP threads_info_sp = GetJSONThreadsInfo(
          *m_debugged_process_sp, threads_with_valid_stop_info_only);
      if (threads_info_sp) {
        response.PutCString("jstopinfo:");
        StreamString unescaped_response;
        threads_info_sp->Write(unescaped_response);
        response.PutCStringAsRawHex8(unescaped_response.GetData());
        response.PutChar(';');
      } else if (log)
        log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to prepare a "
                    "jstopinfo field for pid %" PRIu64,
                    __FUNCTION__, m_debugged_process_sp->GetID());
    }

    uint32_t i = 0;
    response.PutCString("thread-pcs");
    char delimiter = ':';
    for (NativeThreadProtocolSP thread_sp;
         (thread_sp = m_debugged_process_sp->GetThreadAtIndex(i)) != nullptr;
         ++i) {
      NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
      if (!reg_ctx_sp)
        continue;

      uint32_t reg_to_read = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
          eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
      const RegisterInfo *const reg_info_p =
          reg_ctx_sp->GetRegisterInfoAtIndex(reg_to_read);

      RegisterValue reg_value;
      Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value);
      if (error.Fail()) {
        if (log)
          log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s",
                      __FUNCTION__,
                      reg_info_p->name ? reg_info_p->name
                                       : "<unnamed-register>",
                      reg_to_read, error.AsCString());
        continue;
      }

      response.PutChar(delimiter);
      delimiter = ',';
      WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p,
                                        &reg_value, endian::InlHostByteOrder());
    }

    response.PutChar(';');
  }

  //
  // Expedite registers.
  //

  // Grab the register context.
  NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
  if (reg_ctx_sp) {
    // Expedite all registers in the first register set (i.e. should be GPRs)
    // that are not contained in other registers.
    const RegisterSet *reg_set_p;
    if (reg_ctx_sp->GetRegisterSetCount() > 0 &&
        ((reg_set_p = reg_ctx_sp->GetRegisterSet(0)) != nullptr)) {
      if (log)
        log->Printf("GDBRemoteCommunicationServerLLGS::%s expediting registers "
                    "from set '%s' (registers set count: %zu)",
                    __FUNCTION__,
                    reg_set_p->name ? reg_set_p->name : "<unnamed-set>",
                    reg_set_p->num_registers);

      for (const uint32_t *reg_num_p = reg_set_p->registers;
           *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) {
        const RegisterInfo *const reg_info_p =
            reg_ctx_sp->GetRegisterInfoAtIndex(*reg_num_p);
        if (reg_info_p == nullptr) {
          if (log)
            log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get "
                        "register info for register set '%s', register index "
                        "%" PRIu32,
                        __FUNCTION__,
                        reg_set_p->name ? reg_set_p->name : "<unnamed-set>",
                        *reg_num_p);
        } else if (reg_info_p->value_regs == nullptr) {
          // Only expediate registers that are not contained in other registers.
          RegisterValue reg_value;
          Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value);
          if (error.Success()) {
            response.Printf("%.02x:", *reg_num_p);
            WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p,
                                              &reg_value, lldb::eByteOrderBig);
            response.PutChar(';');
          } else {
            if (log)
              log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to read "
                          "register '%s' index %" PRIu32 ": %s",
                          __FUNCTION__, reg_info_p->name ? reg_info_p->name
                                                         : "<unnamed-register>",
                          *reg_num_p, error.AsCString());
          }
        }
      }
    }
  }

  const char *reason_str = GetStopReasonString(tid_stop_info.reason);
  if (reason_str != nullptr) {
    response.Printf("reason:%s;", reason_str);
  }

  if (!description.empty()) {
    // Description may contains special chars, send as hex bytes.
    response.PutCString("description:");
    response.PutCStringAsRawHex8(description.c_str());
    response.PutChar(';');
  } else if ((tid_stop_info.reason == eStopReasonException) &&
             tid_stop_info.details.exception.type) {
    response.PutCString("metype:");
    response.PutHex64(tid_stop_info.details.exception.type);
    response.PutCString(";mecount:");
    response.PutHex32(tid_stop_info.details.exception.data_count);
    response.PutChar(';');

    for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) {
      response.PutCString("medata:");
      response.PutHex64(tid_stop_info.details.exception.data[i]);
      response.PutChar(';');
    }
  }

  return SendPacketNoLock(response.GetString());
}

void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited(
    NativeProcessProtocol *process) {
  assert(process && "process cannot be NULL");

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

  PacketResult result = SendStopReasonForState(StateType::eStateExited);
  if (result != PacketResult::Success) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop "
                  "notification for PID %" PRIu64 ", state: eStateExited",
                  __FUNCTION__, process->GetID());
  }

  // Close the pipe to the inferior terminal i/o if we launched it
  // and set one up.
  MaybeCloseInferiorTerminalConnection();

  // We are ready to exit the debug monitor.
  m_exit_now = true;
}

void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped(
    NativeProcessProtocol *process) {
  assert(process && "process cannot be NULL");

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

  // Send the stop reason unless this is the stop after the
  // launch or attach.
  switch (m_inferior_prev_state) {
  case eStateLaunching:
  case eStateAttaching:
    // Don't send anything per debugserver behavior.
    break;
  default:
    // In all other cases, send the stop reason.
    PacketResult result = SendStopReasonForState(StateType::eStateStopped);
    if (result != PacketResult::Success) {
      if (log)
        log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop "
                    "notification for PID %" PRIu64 ", state: eStateExited",
                    __FUNCTION__, process->GetID());
    }
    break;
  }
}

void GDBRemoteCommunicationServerLLGS::ProcessStateChanged(
    NativeProcessProtocol *process, lldb::StateType state) {
  assert(process && "process cannot be NULL");
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
  if (log) {
    log->Printf("GDBRemoteCommunicationServerLLGS::%s called with "
                "NativeProcessProtocol pid %" PRIu64 ", state: %s",
                __FUNCTION__, process->GetID(), StateAsCString(state));
  }

  switch (state) {
  case StateType::eStateRunning:
    StartSTDIOForwarding();
    break;

  case StateType::eStateStopped:
    // Make sure we get all of the pending stdout/stderr from the inferior
    // and send it to the lldb host before we send the state change
    // notification
    SendProcessOutput();
    // Then stop the forwarding, so that any late output (see llvm.org/pr25652)
    // does not
    // interfere with our protocol.
    StopSTDIOForwarding();
    HandleInferiorState_Stopped(process);
    break;

  case StateType::eStateExited:
    // Same as above
    SendProcessOutput();
    StopSTDIOForwarding();
    HandleInferiorState_Exited(process);
    break;

  default:
    if (log) {
      log->Printf("GDBRemoteCommunicationServerLLGS::%s didn't handle state "
                  "change for pid %" PRIu64 ", new state: %s",
                  __FUNCTION__, process->GetID(), StateAsCString(state));
    }
    break;
  }

  // Remember the previous state reported to us.
  m_inferior_prev_state = state;
}

void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) {
  ClearProcessSpecificData();
}

void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() {
  Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM));

  if (!m_handshake_completed) {
    if (!HandshakeWithClient()) {
      if (log)
        log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with "
                    "client failed, exiting",
                    __FUNCTION__);
      m_mainloop.RequestTermination();
      return;
    }
    m_handshake_completed = true;
  }

  bool interrupt = false;
  bool done = false;
  Status error;
  while (true) {
    const PacketResult result = GetPacketAndSendResponse(
        std::chrono::microseconds(0), error, interrupt, done);
    if (result == PacketResult::ErrorReplyTimeout)
      break; // No more packets in the queue

    if ((result != PacketResult::Success)) {
      if (log)
        log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet "
                    "failed: %s",
                    __FUNCTION__, error.AsCString());
      m_mainloop.RequestTermination();
      break;
    }
  }
}

Status GDBRemoteCommunicationServerLLGS::InitializeConnection(
    std::unique_ptr<Connection> &&connection) {
  IOObjectSP read_object_sp = connection->GetReadObject();
  GDBRemoteCommunicationServer::SetConnection(connection.release());

  Status error;
  m_network_handle_up = m_mainloop.RegisterReadObject(
      read_object_sp, [this](MainLoopBase &) { DataAvailableCallback(); },
      error);
  return error;
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::SendONotification(const char *buffer,
                                                    uint32_t len) {
  if ((buffer == nullptr) || (len == 0)) {
    // Nothing to send.
    return PacketResult::Success;
  }

  StreamString response;
  response.PutChar('O');
  response.PutBytesAsRawHex8(buffer, len);

  return SendPacketNoLock(response.GetString());
}

Status GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) {
  Status error;

  // Set up the reading/handling of process I/O
  std::unique_ptr<ConnectionFileDescriptor> conn_up(
      new ConnectionFileDescriptor(fd, true));
  if (!conn_up) {
    error.SetErrorString("failed to create ConnectionFileDescriptor");
    return error;
  }

  m_stdio_communication.SetCloseOnEOF(false);
  m_stdio_communication.SetConnection(conn_up.release());
  if (!m_stdio_communication.IsConnected()) {
    error.SetErrorString(
        "failed to set connection for inferior I/O communication");
    return error;
  }

  return Status();
}

void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() {
  // Don't forward if not connected (e.g. when attaching).
  if (!m_stdio_communication.IsConnected())
    return;

  Status error;
  lldbassert(!m_stdio_handle_up);
  m_stdio_handle_up = m_mainloop.RegisterReadObject(
      m_stdio_communication.GetConnection()->GetReadObject(),
      [this](MainLoopBase &) { SendProcessOutput(); }, error);

  if (!m_stdio_handle_up) {
    // Not much we can do about the failure. Log it and continue without
    // forwarding.
    if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
      log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio "
                  "forwarding: %s",
                  __FUNCTION__, error.AsCString());
  }
}

void GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() {
  m_stdio_handle_up.reset();
}

void GDBRemoteCommunicationServerLLGS::SendProcessOutput() {
  char buffer[1024];
  ConnectionStatus status;
  Status error;
  while (true) {
    size_t bytes_read = m_stdio_communication.Read(
        buffer, sizeof buffer, std::chrono::microseconds(0), status, &error);
    switch (status) {
    case eConnectionStatusSuccess:
      SendONotification(buffer, bytes_read);
      break;
    case eConnectionStatusLostConnection:
    case eConnectionStatusEndOfFile:
    case eConnectionStatusError:
    case eConnectionStatusNoConnection:
      if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
        log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio "
                    "forwarding as communication returned status %d (error: "
                    "%s)",
                    __FUNCTION__, status, error.AsCString());
      m_stdio_handle_up.reset();
      return;

    case eConnectionStatusInterrupted:
    case eConnectionStatusTimedOut:
      return;
    }
  }
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
    StringExtractorGDBRemote &packet) {
  // Fail if we don't have a current process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
    return SendErrorResponse(68);

  lldb::pid_t pid = m_debugged_process_sp->GetID();

  if (pid == LLDB_INVALID_PROCESS_ID)
    return SendErrorResponse(1);

  ProcessInstanceInfo proc_info;
  if (!Host::GetProcessInfo(pid, proc_info))
    return SendErrorResponse(1);

  StreamString response;
  CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) {
  // Fail if we don't have a current process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
    return SendErrorResponse(68);

  // Make sure we set the current thread so g and p packets return
  // the data the gdb will expect.
  lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID();
  SetCurrentThreadID(tid);

  NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetCurrentThread();
  if (!thread_sp)
    return SendErrorResponse(69);

  StreamString response;
  response.Printf("QC%" PRIx64, thread_sp->GetID());

  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  StopSTDIOForwarding();

  if (!m_debugged_process_sp) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s No debugged process found.",
          __FUNCTION__);
    return PacketResult::Success;
  }

  Status error = m_debugged_process_sp->Kill();
  if (error.Fail() && log)
    log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to kill debugged "
                "process %" PRIu64 ": %s",
                __FUNCTION__, m_debugged_process_sp->GetID(),
                error.AsCString());

  // No OK response for kill packet.
  // return SendOKResponse ();
  return PacketResult::Success;
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR(
    StringExtractorGDBRemote &packet) {
  packet.SetFilePos(::strlen("QSetDisableASLR:"));
  if (packet.GetU32(0))
    m_process_launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
  else
    m_process_launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
  return SendOKResponse();
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir(
    StringExtractorGDBRemote &packet) {
  packet.SetFilePos(::strlen("QSetWorkingDir:"));
  std::string path;
  packet.GetHexByteString(path);
  m_process_launch_info.SetWorkingDirectory(FileSpec{path, true});
  return SendOKResponse();
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir(
    StringExtractorGDBRemote &packet) {
  FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()};
  if (working_dir) {
    StreamString response;
    response.PutCStringAsRawHex8(working_dir.GetCString());
    return SendPacketNoLock(response.GetString());
  }

  return SendErrorResponse(14);
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
  if (log)
    log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);

  // Ensure we have a native process.
  if (!m_debugged_process_sp) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process "
                  "shared pointer",
                  __FUNCTION__);
    return SendErrorResponse(0x36);
  }

  // Pull out the signal number.
  packet.SetFilePos(::strlen("C"));
  if (packet.GetBytesLeft() < 1) {
    // Shouldn't be using a C without a signal.
    return SendIllFormedResponse(packet, "C packet specified without signal.");
  }
  const uint32_t signo =
      packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
  if (signo == std::numeric_limits<uint32_t>::max())
    return SendIllFormedResponse(packet, "failed to parse signal number");

  // Handle optional continue address.
  if (packet.GetBytesLeft() > 0) {
    // FIXME add continue at address support for $C{signo}[;{continue-address}].
    if (*packet.Peek() == ';')
      return SendUnimplementedResponse(packet.GetStringRef().c_str());
    else
      return SendIllFormedResponse(
          packet, "unexpected content after $C{signal-number}");
  }

  ResumeActionList resume_actions(StateType::eStateRunning, 0);
  Status error;

  // We have two branches: what to do if a continue thread is specified (in
  // which case we target
  // sending the signal to that thread), or when we don't have a continue thread
  // set (in which
  // case we send a signal to the process).

  // TODO discuss with Greg Clayton, make sure this makes sense.

  lldb::tid_t signal_tid = GetContinueThreadID();
  if (signal_tid != LLDB_INVALID_THREAD_ID) {
    // The resume action for the continue thread (or all threads if a continue
    // thread is not set).
    ResumeAction action = {GetContinueThreadID(), StateType::eStateRunning,
                           static_cast<int>(signo)};

    // Add the action for the continue thread (or all threads when the continue
    // thread isn't present).
    resume_actions.Append(action);
  } else {
    // Send the signal to the process since we weren't targeting a specific
    // continue thread with the signal.
    error = m_debugged_process_sp->Signal(signo);
    if (error.Fail()) {
      if (log)
        log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send "
                    "signal for process %" PRIu64 ": %s",
                    __FUNCTION__, m_debugged_process_sp->GetID(),
                    error.AsCString());

      return SendErrorResponse(0x52);
    }
  }

  // Resume the threads.
  error = m_debugged_process_sp->Resume(resume_actions);
  if (error.Fail()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to resume "
                  "threads for process %" PRIu64 ": %s",
                  __FUNCTION__, m_debugged_process_sp->GetID(),
                  error.AsCString());

    return SendErrorResponse(0x38);
  }

  // Don't send an "OK" packet; response is the stopped/exited message.
  return PacketResult::Success;
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
  if (log)
    log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);

  packet.SetFilePos(packet.GetFilePos() + ::strlen("c"));

  // For now just support all continue.
  const bool has_continue_address = (packet.GetBytesLeft() > 0);
  if (has_continue_address) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s not implemented for "
                  "c{address} variant [%s remains]",
                  __FUNCTION__, packet.Peek());
    return SendUnimplementedResponse(packet.GetStringRef().c_str());
  }

  // Ensure we have a native process.
  if (!m_debugged_process_sp) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process "
                  "shared pointer",
                  __FUNCTION__);
    return SendErrorResponse(0x36);
  }

  // Build the ResumeActionList
  ResumeActionList actions(StateType::eStateRunning, 0);

  Status error = m_debugged_process_sp->Resume(actions);
  if (error.Fail()) {
    if (log) {
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s c failed for process %" PRIu64
          ": %s",
          __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString());
    }
    return SendErrorResponse(GDBRemoteServerError::eErrorResume);
  }

  if (log)
    log->Printf(
        "GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64,
        __FUNCTION__, m_debugged_process_sp->GetID());

  // No response required from continue.
  return PacketResult::Success;
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_vCont_actions(
    StringExtractorGDBRemote &packet) {
  StreamString response;
  response.Printf("vCont;c;C;s;S");

  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_vCont(
    StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
  if (log)
    log->Printf("GDBRemoteCommunicationServerLLGS::%s handling vCont packet",
                __FUNCTION__);

  packet.SetFilePos(::strlen("vCont"));

  if (packet.GetBytesLeft() == 0) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s missing action from "
                  "vCont package",
                  __FUNCTION__);
    return SendIllFormedResponse(packet, "Missing action from vCont package");
  }

  // Check if this is all continue (no options or ";c").
  if (::strcmp(packet.Peek(), ";c") == 0) {
    // Move past the ';', then do a simple 'c'.
    packet.SetFilePos(packet.GetFilePos() + 1);
    return Handle_c(packet);
  } else if (::strcmp(packet.Peek(), ";s") == 0) {
    // Move past the ';', then do a simple 's'.
    packet.SetFilePos(packet.GetFilePos() + 1);
    return Handle_s(packet);
  }

  // Ensure we have a native process.
  if (!m_debugged_process_sp) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process "
                  "shared pointer",
                  __FUNCTION__);
    return SendErrorResponse(0x36);
  }

  ResumeActionList thread_actions;

  while (packet.GetBytesLeft() && *packet.Peek() == ';') {
    // Skip the semi-colon.
    packet.GetChar();

    // Build up the thread action.
    ResumeAction thread_action;
    thread_action.tid = LLDB_INVALID_THREAD_ID;
    thread_action.state = eStateInvalid;
    thread_action.signal = 0;

    const char action = packet.GetChar();
    switch (action) {
    case 'C':
      thread_action.signal = packet.GetHexMaxU32(false, 0);
      if (thread_action.signal == 0)
        return SendIllFormedResponse(
            packet, "Could not parse signal in vCont packet C action");
      LLVM_FALLTHROUGH;

    case 'c':
      // Continue
      thread_action.state = eStateRunning;
      break;

    case 'S':
      thread_action.signal = packet.GetHexMaxU32(false, 0);
      if (thread_action.signal == 0)
        return SendIllFormedResponse(
            packet, "Could not parse signal in vCont packet S action");
      LLVM_FALLTHROUGH;

    case 's':
      // Step
      thread_action.state = eStateStepping;
      break;

    default:
      return SendIllFormedResponse(packet, "Unsupported vCont action");
      break;
    }

    // Parse out optional :{thread-id} value.
    if (packet.GetBytesLeft() && (*packet.Peek() == ':')) {
      // Consume the separator.
      packet.GetChar();

      thread_action.tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
      if (thread_action.tid == LLDB_INVALID_THREAD_ID)
        return SendIllFormedResponse(
            packet, "Could not parse thread number in vCont packet");
    }

    thread_actions.Append(thread_action);
  }

  Status error = m_debugged_process_sp->Resume(thread_actions);
  if (error.Fail()) {
    if (log) {
      log->Printf("GDBRemoteCommunicationServerLLGS::%s vCont failed for "
                  "process %" PRIu64 ": %s",
                  __FUNCTION__, m_debugged_process_sp->GetID(),
                  error.AsCString());
    }
    return SendErrorResponse(GDBRemoteServerError::eErrorResume);
  }

  if (log)
    log->Printf(
        "GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64,
        __FUNCTION__, m_debugged_process_sp->GetID());

  // No response required from vCont.
  return PacketResult::Success;
}

void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
  if (log)
    log->Printf("GDBRemoteCommunicationServerLLGS::%s setting current thread "
                "id to %" PRIu64,
                __FUNCTION__, tid);

  m_current_tid = tid;
  if (m_debugged_process_sp)
    m_debugged_process_sp->SetCurrentThreadID(m_current_tid);
}

void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
  if (log)
    log->Printf("GDBRemoteCommunicationServerLLGS::%s setting continue thread "
                "id to %" PRIu64,
                __FUNCTION__, tid);

  m_continue_tid = tid;
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_stop_reason(
    StringExtractorGDBRemote &packet) {
  // Handle the $? gdbremote command.

  // If no process, indicate error
  if (!m_debugged_process_sp)
    return SendErrorResponse(02);

  return SendStopReasonForState(m_debugged_process_sp->GetState());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
    lldb::StateType process_state) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  switch (process_state) {
  case eStateAttaching:
  case eStateLaunching:
  case eStateRunning:
  case eStateStepping:
  case eStateDetached:
    // NOTE: gdb protocol doc looks like it should return $OK
    // when everything is running (i.e. no stopped result).
    return PacketResult::Success; // Ignore

  case eStateSuspended:
  case eStateStopped:
  case eStateCrashed: {
    lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID();
    // Make sure we set the current thread so g and p packets return
    // the data the gdb will expect.
    SetCurrentThreadID(tid);
    return SendStopReplyPacketForThread(tid);
  }

  case eStateInvalid:
  case eStateUnloaded:
  case eStateExited:
    return SendWResponse(m_debugged_process_sp.get());

  default:
    if (log) {
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  ", current state reporting not handled: %s",
                  __FUNCTION__, m_debugged_process_sp->GetID(),
                  StateAsCString(process_state));
    }
    break;
  }

  return SendErrorResponse(0);
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo(
    StringExtractorGDBRemote &packet) {
  // Fail if we don't have a current process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
    return SendErrorResponse(68);

  // Ensure we have a thread.
  NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadAtIndex(0));
  if (!thread_sp)
    return SendErrorResponse(69);

  // Get the register context for the first thread.
  NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext());
  if (!reg_context_sp)
    return SendErrorResponse(69);

  // Parse out the register number from the request.
  packet.SetFilePos(strlen("qRegisterInfo"));
  const uint32_t reg_index =
      packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
  if (reg_index == std::numeric_limits<uint32_t>::max())
    return SendErrorResponse(69);

  // Return the end of registers response if we've iterated one past the end of
  // the register set.
  if (reg_index >= reg_context_sp->GetUserRegisterCount())
    return SendErrorResponse(69);

  const RegisterInfo *reg_info =
      reg_context_sp->GetRegisterInfoAtIndex(reg_index);
  if (!reg_info)
    return SendErrorResponse(69);

  // Build the reginfos response.
  StreamGDBRemote response;

  response.PutCString("name:");
  response.PutCString(reg_info->name);
  response.PutChar(';');

  if (reg_info->alt_name && reg_info->alt_name[0]) {
    response.PutCString("alt-name:");
    response.PutCString(reg_info->alt_name);
    response.PutChar(';');
  }

  response.Printf("bitsize:%" PRIu32 ";offset:%" PRIu32 ";",
                  reg_info->byte_size * 8, reg_info->byte_offset);

  switch (reg_info->encoding) {
  case eEncodingUint:
    response.PutCString("encoding:uint;");
    break;
  case eEncodingSint:
    response.PutCString("encoding:sint;");
    break;
  case eEncodingIEEE754:
    response.PutCString("encoding:ieee754;");
    break;
  case eEncodingVector:
    response.PutCString("encoding:vector;");
    break;
  default:
    break;
  }

  switch (reg_info->format) {
  case eFormatBinary:
    response.PutCString("format:binary;");
    break;
  case eFormatDecimal:
    response.PutCString("format:decimal;");
    break;
  case eFormatHex:
    response.PutCString("format:hex;");
    break;
  case eFormatFloat:
    response.PutCString("format:float;");
    break;
  case eFormatVectorOfSInt8:
    response.PutCString("format:vector-sint8;");
    break;
  case eFormatVectorOfUInt8:
    response.PutCString("format:vector-uint8;");
    break;
  case eFormatVectorOfSInt16:
    response.PutCString("format:vector-sint16;");
    break;
  case eFormatVectorOfUInt16:
    response.PutCString("format:vector-uint16;");
    break;
  case eFormatVectorOfSInt32:
    response.PutCString("format:vector-sint32;");
    break;
  case eFormatVectorOfUInt32:
    response.PutCString("format:vector-uint32;");
    break;
  case eFormatVectorOfFloat32:
    response.PutCString("format:vector-float32;");
    break;
  case eFormatVectorOfUInt64:
    response.PutCString("format:vector-uint64;");
    break;
  case eFormatVectorOfUInt128:
    response.PutCString("format:vector-uint128;");
    break;
  default:
    break;
  };

  const char *const register_set_name =
      reg_context_sp->GetRegisterSetNameForRegisterAtIndex(reg_index);
  if (register_set_name) {
    response.PutCString("set:");
    response.PutCString(register_set_name);
    response.PutChar(';');
  }

  if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] !=
      LLDB_INVALID_REGNUM)
    response.Printf("ehframe:%" PRIu32 ";",
                    reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);

  if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
    response.Printf("dwarf:%" PRIu32 ";",
                    reg_info->kinds[RegisterKind::eRegisterKindDWARF]);

  switch (reg_info->kinds[RegisterKind::eRegisterKindGeneric]) {
  case LLDB_REGNUM_GENERIC_PC:
    response.PutCString("generic:pc;");
    break;
  case LLDB_REGNUM_GENERIC_SP:
    response.PutCString("generic:sp;");
    break;
  case LLDB_REGNUM_GENERIC_FP:
    response.PutCString("generic:fp;");
    break;
  case LLDB_REGNUM_GENERIC_RA:
    response.PutCString("generic:ra;");
    break;
  case LLDB_REGNUM_GENERIC_FLAGS:
    response.PutCString("generic:flags;");
    break;
  case LLDB_REGNUM_GENERIC_ARG1:
    response.PutCString("generic:arg1;");
    break;
  case LLDB_REGNUM_GENERIC_ARG2:
    response.PutCString("generic:arg2;");
    break;
  case LLDB_REGNUM_GENERIC_ARG3:
    response.PutCString("generic:arg3;");
    break;
  case LLDB_REGNUM_GENERIC_ARG4:
    response.PutCString("generic:arg4;");
    break;
  case LLDB_REGNUM_GENERIC_ARG5:
    response.PutCString("generic:arg5;");
    break;
  case LLDB_REGNUM_GENERIC_ARG6:
    response.PutCString("generic:arg6;");
    break;
  case LLDB_REGNUM_GENERIC_ARG7:
    response.PutCString("generic:arg7;");
    break;
  case LLDB_REGNUM_GENERIC_ARG8:
    response.PutCString("generic:arg8;");
    break;
  default:
    break;
  }

  if (reg_info->value_regs && reg_info->value_regs[0] != LLDB_INVALID_REGNUM) {
    response.PutCString("container-regs:");
    int i = 0;
    for (const uint32_t *reg_num = reg_info->value_regs;
         *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) {
      if (i > 0)
        response.PutChar(',');
      response.Printf("%" PRIx32, *reg_num);
    }
    response.PutChar(';');
  }

  if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) {
    response.PutCString("invalidate-regs:");
    int i = 0;
    for (const uint32_t *reg_num = reg_info->invalidate_regs;
         *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) {
      if (i > 0)
        response.PutChar(',');
      response.Printf("%" PRIx32, *reg_num);
    }
    response.PutChar(';');
  }

  if (reg_info->dynamic_size_dwarf_expr_bytes) {
    const size_t dwarf_opcode_len = reg_info->dynamic_size_dwarf_len;
    response.PutCString("dynamic_size_dwarf_expr_bytes:");
    for (uint32_t i = 0; i < dwarf_opcode_len; ++i)
      response.PutHex8(reg_info->dynamic_size_dwarf_expr_bytes[i]);
    response.PutChar(';');
  }
  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo(
    StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));

  // Fail if we don't have a current process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s() no process (%s), "
                  "returning OK",
                  __FUNCTION__,
                  m_debugged_process_sp ? "invalid process id"
                                        : "null m_debugged_process_sp");
    return SendOKResponse();
  }

  StreamGDBRemote response;
  response.PutChar('m');

  if (log)
    log->Printf(
        "GDBRemoteCommunicationServerLLGS::%s() starting thread iteration",
        __FUNCTION__);

  NativeThreadProtocolSP thread_sp;
  uint32_t thread_index;
  for (thread_index = 0,
      thread_sp = m_debugged_process_sp->GetThreadAtIndex(thread_index);
       thread_sp; ++thread_index,
      thread_sp = m_debugged_process_sp->GetThreadAtIndex(thread_index)) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s() iterated thread %" PRIu32
          "(%s, tid=0x%" PRIx64 ")",
          __FUNCTION__, thread_index, thread_sp ? "is not null" : "null",
          thread_sp ? thread_sp->GetID() : LLDB_INVALID_THREAD_ID);
    if (thread_index > 0)
      response.PutChar(',');
    response.Printf("%" PRIx64, thread_sp->GetID());
  }

  if (log)
    log->Printf(
        "GDBRemoteCommunicationServerLLGS::%s() finished thread iteration",
        __FUNCTION__);

  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo(
    StringExtractorGDBRemote &packet) {
  // FIXME for now we return the full thread list in the initial packet and
  // always do nothing here.
  return SendPacketNoLock("l");
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));

  // Parse out the register number from the request.
  packet.SetFilePos(strlen("p"));
  const uint32_t reg_index =
      packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
  if (reg_index == std::numeric_limits<uint32_t>::max()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not "
                  "parse register number from request \"%s\"",
                  __FUNCTION__, packet.GetStringRef().c_str());
    return SendErrorResponse(0x15);
  }

  // Get the thread to use.
  NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet);
  if (!thread_sp) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, no thread available",
          __FUNCTION__);
    return SendErrorResponse(0x15);
  }

  // Get the thread's register context.
  NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext());
  if (!reg_context_sp) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64
          " failed, no register context available for the thread",
          __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID());
    return SendErrorResponse(0x15);
  }

  // Return the end of registers response if we've iterated one past the end of
  // the register set.
  if (reg_index >= reg_context_sp->GetUserRegisterCount()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested "
                  "register %" PRIu32 " beyond register count %" PRIu32,
                  __FUNCTION__, reg_index,
                  reg_context_sp->GetUserRegisterCount());
    return SendErrorResponse(0x15);
  }

  const RegisterInfo *reg_info =
      reg_context_sp->GetRegisterInfoAtIndex(reg_index);
  if (!reg_info) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested "
                  "register %" PRIu32 " returned NULL",
                  __FUNCTION__, reg_index);
    return SendErrorResponse(0x15);
  }

  // Build the reginfos response.
  StreamGDBRemote response;

  // Retrieve the value
  RegisterValue reg_value;
  Status error = reg_context_sp->ReadRegister(reg_info, reg_value);
  if (error.Fail()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, read of "
                  "requested register %" PRIu32 " (%s) failed: %s",
                  __FUNCTION__, reg_index, reg_info->name, error.AsCString());
    return SendErrorResponse(0x15);
  }

  const uint8_t *const data =
      reinterpret_cast<const uint8_t *>(reg_value.GetBytes());
  if (!data) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get data "
                  "bytes from requested register %" PRIu32,
                  __FUNCTION__, reg_index);
    return SendErrorResponse(0x15);
  }

  // FIXME flip as needed to get data in big/little endian format for this host.
  for (uint32_t i = 0; i < reg_value.GetByteSize(); ++i)
    response.PutHex8(data[i]);

  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));

  // Ensure there is more content.
  if (packet.GetBytesLeft() < 1)
    return SendIllFormedResponse(packet, "Empty P packet");

  // Parse out the register number from the request.
  packet.SetFilePos(strlen("P"));
  const uint32_t reg_index =
      packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
  if (reg_index == std::numeric_limits<uint32_t>::max()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not "
                  "parse register number from request \"%s\"",
                  __FUNCTION__, packet.GetStringRef().c_str());
    return SendErrorResponse(0x29);
  }

  // Note debugserver would send an E30 here.
  if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != '='))
    return SendIllFormedResponse(
        packet, "P packet missing '=' char after register number");

  // Get process architecture.
  ArchSpec process_arch;
  if (!m_debugged_process_sp ||
      !m_debugged_process_sp->GetArchitecture(process_arch)) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to retrieve "
                  "inferior architecture",
                  __FUNCTION__);
    return SendErrorResponse(0x49);
  }

  // Parse out the value.
  uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register
  size_t reg_size = packet.GetHexBytesAvail(reg_bytes);

  // Get the thread to use.
  NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet);
  if (!thread_sp) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no thread "
                  "available (thread index 0)",
                  __FUNCTION__);
    return SendErrorResponse(0x28);
  }

  // Get the thread's register context.
  NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext());
  if (!reg_context_sp) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64
          " failed, no register context available for the thread",
          __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID());
    return SendErrorResponse(0x15);
  }

  const RegisterInfo *reg_info =
      reg_context_sp->GetRegisterInfoAtIndex(reg_index);
  if (!reg_info) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested "
                  "register %" PRIu32 " returned NULL",
                  __FUNCTION__, reg_index);
    return SendErrorResponse(0x48);
  }

  // Return the end of registers response if we've iterated one past the end of
  // the register set.
  if (reg_index >= reg_context_sp->GetUserRegisterCount()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested "
                  "register %" PRIu32 " beyond register count %" PRIu32,
                  __FUNCTION__, reg_index,
                  reg_context_sp->GetUserRegisterCount());
    return SendErrorResponse(0x47);
  }

  // The dwarf expression are evaluate on host site
  // which may cause register size to change
  // Hence the reg_size may not be same as reg_info->bytes_size
  if ((reg_size != reg_info->byte_size) &&
      !(reg_info->dynamic_size_dwarf_expr_bytes)) {
    return SendIllFormedResponse(packet, "P packet register size is incorrect");
  }

  // Build the reginfos response.
  StreamGDBRemote response;

  RegisterValue reg_value(reg_bytes, reg_size, process_arch.GetByteOrder());
  Status error = reg_context_sp->WriteRegister(reg_info, reg_value);
  if (error.Fail()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, write of "
                  "requested register %" PRIu32 " (%s) failed: %s",
                  __FUNCTION__, reg_index, reg_info->name, error.AsCString());
    return SendErrorResponse(0x32);
  }

  return SendOKResponse();
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));

  // Fail if we don't have a current process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
          __FUNCTION__);
    return SendErrorResponse(0x15);
  }

  // Parse out which variant of $H is requested.
  packet.SetFilePos(strlen("H"));
  if (packet.GetBytesLeft() < 1) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, H command "
                  "missing {g,c} variant",
                  __FUNCTION__);
    return SendIllFormedResponse(packet, "H command missing {g,c} variant");
  }

  const char h_variant = packet.GetChar();
  switch (h_variant) {
  case 'g':
    break;

  case 'c':
    break;

  default:
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c",
          __FUNCTION__, h_variant);
    return SendIllFormedResponse(packet,
                                 "H variant unsupported, should be c or g");
  }

  // Parse out the thread number.
  // FIXME return a parse success/fail value.  All values are valid here.
  const lldb::tid_t tid =
      packet.GetHexMaxU64(false, std::numeric_limits<lldb::tid_t>::max());

  // Ensure we have the given thread when not specifying -1 (all threads) or 0
  // (any thread).
  if (tid != LLDB_INVALID_THREAD_ID && tid != 0) {
    NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadByID(tid));
    if (!thread_sp) {
      if (log)
        log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64
                    " not found",
                    __FUNCTION__, tid);
      return SendErrorResponse(0x15);
    }
  }

  // Now switch the given thread type.
  switch (h_variant) {
  case 'g':
    SetCurrentThreadID(tid);
    break;

  case 'c':
    SetContinueThreadID(tid);
    break;

  default:
    assert(false && "unsupported $H variant - shouldn't get here");
    return SendIllFormedResponse(packet,
                                 "H variant unsupported, should be c or g");
  }

  return SendOKResponse();
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));

  // Fail if we don't have a current process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
          __FUNCTION__);
    return SendErrorResponse(0x15);
  }

  packet.SetFilePos(::strlen("I"));
  uint8_t tmp[4096];
  for (;;) {
    size_t read = packet.GetHexBytesAvail(tmp);
    if (read == 0) {
      break;
    }
    // write directly to stdin *this might block if stdin buffer is full*
    // TODO: enqueue this block in circular buffer and send window size to
    // remote host
    ConnectionStatus status;
    Status error;
    m_stdio_communication.Write(tmp, read, status, &error);
    if (error.Fail()) {
      return SendErrorResponse(0x15);
    }
  }

  return SendOKResponse();
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_interrupt(
    StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));

  // Fail if we don't have a current process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
          __FUNCTION__);
    return SendErrorResponse(0x15);
  }

  // Interrupt the process.
  Status error = m_debugged_process_sp->Interrupt();
  if (error.Fail()) {
    if (log) {
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed for process %" PRIu64
          ": %s",
          __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString());
    }
    return SendErrorResponse(GDBRemoteServerError::eErrorResume);
  }

  if (log)
    log->Printf("GDBRemoteCommunicationServerLLGS::%s stopped process %" PRIu64,
                __FUNCTION__, m_debugged_process_sp->GetID());

  // No response required from stop all.
  return PacketResult::Success;
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_memory_read(
    StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
          __FUNCTION__);
    return SendErrorResponse(0x15);
  }

  // Parse out the memory address.
  packet.SetFilePos(strlen("m"));
  if (packet.GetBytesLeft() < 1)
    return SendIllFormedResponse(packet, "Too short m packet");

  // Read the address.  Punting on validation.
  // FIXME replace with Hex U64 read with no default value that fails on failed
  // read.
  const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);

  // Validate comma.
  if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
    return SendIllFormedResponse(packet, "Comma sep missing in m packet");

  // Get # bytes to read.
  if (packet.GetBytesLeft() < 1)
    return SendIllFormedResponse(packet, "Length missing in m packet");

  const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
  if (byte_count == 0) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s nothing to read: "
                  "zero-length packet",
                  __FUNCTION__);
    return SendOKResponse();
  }

  // Allocate the response buffer.
  std::string buf(byte_count, '\0');
  if (buf.empty())
    return SendErrorResponse(0x78);

  // Retrieve the process memory.
  size_t bytes_read = 0;
  Status error = m_debugged_process_sp->ReadMemoryWithoutTrap(
      read_addr, &buf[0], byte_count, bytes_read);
  if (error.Fail()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " mem 0x%" PRIx64 ": failed to read. Error: %s",
                  __FUNCTION__, m_debugged_process_sp->GetID(), read_addr,
                  error.AsCString());
    return SendErrorResponse(0x08);
  }

  if (bytes_read == 0) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes",
                  __FUNCTION__, m_debugged_process_sp->GetID(), read_addr,
                  byte_count);
    return SendErrorResponse(0x08);
  }

  StreamGDBRemote response;
  packet.SetFilePos(0);
  char kind = packet.GetChar('?');
  if (kind == 'x')
    response.PutEscapedBytes(buf.data(), byte_count);
  else {
    assert(kind == 'm');
    for (size_t i = 0; i < bytes_read; ++i)
      response.PutHex8(buf[i]);
  }

  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
          __FUNCTION__);
    return SendErrorResponse(0x15);
  }

  // Parse out the memory address.
  packet.SetFilePos(strlen("M"));
  if (packet.GetBytesLeft() < 1)
    return SendIllFormedResponse(packet, "Too short M packet");

  // Read the address.  Punting on validation.
  // FIXME replace with Hex U64 read with no default value that fails on failed
  // read.
  const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0);

  // Validate comma.
  if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
    return SendIllFormedResponse(packet, "Comma sep missing in M packet");

  // Get # bytes to read.
  if (packet.GetBytesLeft() < 1)
    return SendIllFormedResponse(packet, "Length missing in M packet");

  const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
  if (byte_count == 0) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s nothing to write: "
                  "zero-length packet",
                  __FUNCTION__);
    return PacketResult::Success;
  }

  // Validate colon.
  if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':'))
    return SendIllFormedResponse(
        packet, "Comma sep missing in M packet after byte length");

  // Allocate the conversion buffer.
  std::vector<uint8_t> buf(byte_count, 0);
  if (buf.empty())
    return SendErrorResponse(0x78);

  // Convert the hex memory write contents to bytes.
  StreamGDBRemote response;
  const uint64_t convert_count = packet.GetHexBytes(buf, 0);
  if (convert_count != byte_count) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " mem 0x%" PRIx64 ": asked to write %" PRIu64
                  " bytes, but only found %" PRIu64 " to convert.",
                  __FUNCTION__, m_debugged_process_sp->GetID(), write_addr,
                  byte_count, convert_count);
    return SendIllFormedResponse(packet, "M content byte length specified did "
                                         "not match hex-encoded content "
                                         "length");
  }

  // Write the process memory.
  size_t bytes_written = 0;
  Status error = m_debugged_process_sp->WriteMemory(write_addr, &buf[0],
                                                    byte_count, bytes_written);
  if (error.Fail()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " mem 0x%" PRIx64 ": failed to write. Error: %s",
                  __FUNCTION__, m_debugged_process_sp->GetID(), write_addr,
                  error.AsCString());
    return SendErrorResponse(0x09);
  }

  if (bytes_written == 0) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " mem 0x%" PRIx64 ": wrote 0 of %" PRIu64 " requested bytes",
                  __FUNCTION__, m_debugged_process_sp->GetID(), write_addr,
                  byte_count);
    return SendErrorResponse(0x09);
  }

  return SendOKResponse();
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
    StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  // Currently only the NativeProcessProtocol knows if it can handle a
  // qMemoryRegionInfoSupported
  // request, but we're not guaranteed to be attached to a process.  For now
  // we'll assume the
  // client only asks this when a process is being debugged.

  // Ensure we have a process running; otherwise, we can't figure this out
  // since we won't have a NativeProcessProtocol.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
          __FUNCTION__);
    return SendErrorResponse(0x15);
  }

  // Test if we can get any region back when asking for the region around NULL.
  MemoryRegionInfo region_info;
  const Status error =
      m_debugged_process_sp->GetMemoryRegionInfo(0, region_info);
  if (error.Fail()) {
    // We don't support memory region info collection for this
    // NativeProcessProtocol.
    return SendUnimplementedResponse("");
  }

  return SendOKResponse();
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
    StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  // Ensure we have a process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
          __FUNCTION__);
    return SendErrorResponse(0x15);
  }

  // Parse out the memory address.
  packet.SetFilePos(strlen("qMemoryRegionInfo:"));
  if (packet.GetBytesLeft() < 1)
    return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet");

  // Read the address.  Punting on validation.
  const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);

  StreamGDBRemote response;

  // Get the memory region info for the target address.
  MemoryRegionInfo region_info;
  const Status error =
      m_debugged_process_sp->GetMemoryRegionInfo(read_addr, region_info);
  if (error.Fail()) {
    // Return the error message.

    response.PutCString("error:");
    response.PutCStringAsRawHex8(error.AsCString());
    response.PutChar(';');
  } else {
    // Range start and size.
    response.Printf("start:%" PRIx64 ";size:%" PRIx64 ";",
                    region_info.GetRange().GetRangeBase(),
                    region_info.GetRange().GetByteSize());

    // Permissions.
    if (region_info.GetReadable() || region_info.GetWritable() ||
        region_info.GetExecutable()) {
      // Write permissions info.
      response.PutCString("permissions:");

      if (region_info.GetReadable())
        response.PutChar('r');
      if (region_info.GetWritable())
        response.PutChar('w');
      if (region_info.GetExecutable())
        response.PutChar('x');

      response.PutChar(';');
    }

    // Name
    ConstString name = region_info.GetName();
    if (name) {
      response.PutCString("name:");
      response.PutCStringAsRawHex8(name.AsCString());
      response.PutChar(';');
    }
  }

  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
  // Ensure we have a process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
          __FUNCTION__);
    return SendErrorResponse(0x15);
  }

  // Parse out software or hardware breakpoint or watchpoint requested.
  packet.SetFilePos(strlen("Z"));
  if (packet.GetBytesLeft() < 1)
    return SendIllFormedResponse(
        packet, "Too short Z packet, missing software/hardware specifier");

  bool want_breakpoint = true;
  bool want_hardware = false;
  uint32_t watch_flags = 0;

  const GDBStoppointType stoppoint_type =
      GDBStoppointType(packet.GetS32(eStoppointInvalid));
  switch (stoppoint_type) {
  case eBreakpointSoftware:
    want_hardware = false;
    want_breakpoint = true;
    break;
  case eBreakpointHardware:
    want_hardware = true;
    want_breakpoint = true;
    break;
  case eWatchpointWrite:
    watch_flags = 1;
    want_hardware = true;
    want_breakpoint = false;
    break;
  case eWatchpointRead:
    watch_flags = 2;
    want_hardware = true;
    want_breakpoint = false;
    break;
  case eWatchpointReadWrite:
    watch_flags = 3;
    want_hardware = true;
    want_breakpoint = false;
    break;
  case eStoppointInvalid:
    return SendIllFormedResponse(
        packet, "Z packet had invalid software/hardware specifier");
  }

  if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
    return SendIllFormedResponse(
        packet, "Malformed Z packet, expecting comma after stoppoint type");

  // Parse out the stoppoint address.
  if (packet.GetBytesLeft() < 1)
    return SendIllFormedResponse(packet, "Too short Z packet, missing address");
  const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);

  if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
    return SendIllFormedResponse(
        packet, "Malformed Z packet, expecting comma after address");

  // Parse out the stoppoint size (i.e. size hint for opcode size).
  const uint32_t size =
      packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
  if (size == std::numeric_limits<uint32_t>::max())
    return SendIllFormedResponse(
        packet, "Malformed Z packet, failed to parse size argument");

  if (want_breakpoint) {
    // Try to set the breakpoint.
    const Status error =
        m_debugged_process_sp->SetBreakpoint(addr, size, want_hardware);
    if (error.Success())
      return SendOKResponse();
    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " failed to set breakpoint: %s",
                  __FUNCTION__, m_debugged_process_sp->GetID(),
                  error.AsCString());
    return SendErrorResponse(0x09);
  } else {
    // Try to set the watchpoint.
    const Status error = m_debugged_process_sp->SetWatchpoint(
        addr, size, watch_flags, want_hardware);
    if (error.Success())
      return SendOKResponse();
    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " failed to set watchpoint: %s",
                  __FUNCTION__, m_debugged_process_sp->GetID(),
                  error.AsCString());
    return SendErrorResponse(0x09);
  }
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
  // Ensure we have a process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
          __FUNCTION__);
    return SendErrorResponse(0x15);
  }

  // Parse out software or hardware breakpoint or watchpoint requested.
  packet.SetFilePos(strlen("z"));
  if (packet.GetBytesLeft() < 1)
    return SendIllFormedResponse(
        packet, "Too short z packet, missing software/hardware specifier");

  bool want_breakpoint = true;
  bool want_hardware = false;

  const GDBStoppointType stoppoint_type =
      GDBStoppointType(packet.GetS32(eStoppointInvalid));
  switch (stoppoint_type) {
  case eBreakpointHardware:
    want_breakpoint = true;
    want_hardware = true;
    break;
  case eBreakpointSoftware:
    want_breakpoint = true;
    break;
  case eWatchpointWrite:
    want_breakpoint = false;
    break;
  case eWatchpointRead:
    want_breakpoint = false;
    break;
  case eWatchpointReadWrite:
    want_breakpoint = false;
    break;
  default:
    return SendIllFormedResponse(
        packet, "z packet had invalid software/hardware specifier");
  }

  if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
    return SendIllFormedResponse(
        packet, "Malformed z packet, expecting comma after stoppoint type");

  // Parse out the stoppoint address.
  if (packet.GetBytesLeft() < 1)
    return SendIllFormedResponse(packet, "Too short z packet, missing address");
  const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);

  if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
    return SendIllFormedResponse(
        packet, "Malformed z packet, expecting comma after address");

  /*
  // Parse out the stoppoint size (i.e. size hint for opcode size).
  const uint32_t size = packet.GetHexMaxU32 (false,
  std::numeric_limits<uint32_t>::max ());
  if (size == std::numeric_limits<uint32_t>::max ())
      return SendIllFormedResponse(packet, "Malformed z packet, failed to parse
  size argument");
  */

  if (want_breakpoint) {
    // Try to clear the breakpoint.
    const Status error =
        m_debugged_process_sp->RemoveBreakpoint(addr, want_hardware);
    if (error.Success())
      return SendOKResponse();
    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " failed to remove breakpoint: %s",
                  __FUNCTION__, m_debugged_process_sp->GetID(),
                  error.AsCString());
    return SendErrorResponse(0x09);
  } else {
    // Try to clear the watchpoint.
    const Status error = m_debugged_process_sp->RemoveWatchpoint(addr);
    if (error.Success())
      return SendOKResponse();
    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " failed to remove watchpoint: %s",
                  __FUNCTION__, m_debugged_process_sp->GetID(),
                  error.AsCString());
    return SendErrorResponse(0x09);
  }
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));

  // Ensure we have a process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
          __FUNCTION__);
    return SendErrorResponse(0x32);
  }

  // We first try to use a continue thread id.  If any one or any all set, use
  // the current thread.
  // Bail out if we don't have a thread id.
  lldb::tid_t tid = GetContinueThreadID();
  if (tid == 0 || tid == LLDB_INVALID_THREAD_ID)
    tid = GetCurrentThreadID();
  if (tid == LLDB_INVALID_THREAD_ID)
    return SendErrorResponse(0x33);

  // Double check that we have such a thread.
  // TODO investigate: on MacOSX we might need to do an UpdateThreads () here.
  NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetThreadByID(tid);
  if (!thread_sp || thread_sp->GetID() != tid)
    return SendErrorResponse(0x33);

  // Create the step action for the given thread.
  ResumeAction action = {tid, eStateStepping, 0};

  // Setup the actions list.
  ResumeActionList actions;
  actions.Append(action);

  // All other threads stop while we're single stepping a thread.
  actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
  Status error = m_debugged_process_sp->Resume(actions);
  if (error.Fail()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " tid %" PRIu64 " Resume() failed with error: %s",
                  __FUNCTION__, m_debugged_process_sp->GetID(), tid,
                  error.AsCString());
    return SendErrorResponse(0x49);
  }

  // No response here - the stop or exit will come from the resulting action.
  return PacketResult::Success;
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read(
    StringExtractorGDBRemote &packet) {
// *BSD impls should be able to do this too.
#if defined(__linux__) || defined(__NetBSD__)
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  // Parse out the offset.
  packet.SetFilePos(strlen("qXfer:auxv:read::"));
  if (packet.GetBytesLeft() < 1)
    return SendIllFormedResponse(packet,
                                 "qXfer:auxv:read:: packet missing offset");

  const uint64_t auxv_offset =
      packet.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max());
  if (auxv_offset == std::numeric_limits<uint64_t>::max())
    return SendIllFormedResponse(packet,
                                 "qXfer:auxv:read:: packet missing offset");

  // Parse out comma.
  if (packet.GetBytesLeft() < 1 || packet.GetChar() != ',')
    return SendIllFormedResponse(
        packet, "qXfer:auxv:read:: packet missing comma after offset");

  // Parse out the length.
  const uint64_t auxv_length =
      packet.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max());
  if (auxv_length == std::numeric_limits<uint64_t>::max())
    return SendIllFormedResponse(packet,
                                 "qXfer:auxv:read:: packet missing length");

  // Grab the auxv data if we need it.
  if (!m_active_auxv_buffer_up) {
    // Make sure we have a valid process.
    if (!m_debugged_process_sp ||
        (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
      if (log)
        log->Printf(
            "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
            __FUNCTION__);
      return SendErrorResponse(0x10);
    }

    // Grab the auxv data.
    auto buffer_or_error = m_debugged_process_sp->GetAuxvData();
    if (!buffer_or_error) {
      std::error_code ec = buffer_or_error.getError();
      LLDB_LOG(log, "no auxv data retrieved: {0}", ec.message());
      return SendErrorResponse(ec.value());
    }
    m_active_auxv_buffer_up = std::move(*buffer_or_error);
  }

  StreamGDBRemote response;
  bool done_with_buffer = false;

  llvm::StringRef buffer = m_active_auxv_buffer_up->getBuffer();
  if (auxv_offset >= buffer.size()) {
    // We have nothing left to send.  Mark the buffer as complete.
    response.PutChar('l');
    done_with_buffer = true;
  } else {
    // Figure out how many bytes are available starting at the given offset.
    buffer = buffer.drop_front(auxv_offset);

    // Mark the response type according to whether we're reading the remainder
    // of the auxv data.
    if (auxv_length >= buffer.size()) {
      // There will be nothing left to read after this
      response.PutChar('l');
      done_with_buffer = true;
    } else {
      // There will still be bytes to read after this request.
      response.PutChar('m');
      buffer = buffer.take_front(auxv_length);
    }

    // Now write the data in encoded binary form.
    response.PutEscapedBytes(buffer.data(), buffer.size());
  }

  if (done_with_buffer)
    m_active_auxv_buffer_up.reset();

  return SendPacketNoLock(response.GetString());
#else
  return SendUnimplementedResponse("not implemented on this platform");
#endif
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState(
    StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));

  // Move past packet name.
  packet.SetFilePos(strlen("QSaveRegisterState"));

  // Get the thread to use.
  NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet);
  if (!thread_sp) {
    if (m_thread_suffix_supported)
      return SendIllFormedResponse(
          packet, "No thread specified in QSaveRegisterState packet");
    else
      return SendIllFormedResponse(packet,
                                   "No thread was is set with the Hg packet");
  }

  // Grab the register context for the thread.
  NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext());
  if (!reg_context_sp) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64
          " failed, no register context available for the thread",
          __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID());
    return SendErrorResponse(0x15);
  }

  // Save registers to a buffer.
  DataBufferSP register_data_sp;
  Status error = reg_context_sp->ReadAllRegisterValues(register_data_sp);
  if (error.Fail()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " failed to save all register values: %s",
                  __FUNCTION__, m_debugged_process_sp->GetID(),
                  error.AsCString());
    return SendErrorResponse(0x75);
  }

  // Allocate a new save id.
  const uint32_t save_id = GetNextSavedRegistersID();
  assert((m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) &&
         "GetNextRegisterSaveID() returned an existing register save id");

  // Save the register data buffer under the save id.
  {
    std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
    m_saved_registers_map[save_id] = register_data_sp;
  }

  // Write the response.
  StreamGDBRemote response;
  response.Printf("%" PRIu32, save_id);
  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState(
    StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));

  // Parse out save id.
  packet.SetFilePos(strlen("QRestoreRegisterState:"));
  if (packet.GetBytesLeft() < 1)
    return SendIllFormedResponse(
        packet, "QRestoreRegisterState packet missing register save id");

  const uint32_t save_id = packet.GetU32(0);
  if (save_id == 0) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s QRestoreRegisterState "
                  "packet has malformed save id, expecting decimal uint32_t",
                  __FUNCTION__);
    return SendErrorResponse(0x76);
  }

  // Get the thread to use.
  NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet);
  if (!thread_sp) {
    if (m_thread_suffix_supported)
      return SendIllFormedResponse(
          packet, "No thread specified in QRestoreRegisterState packet");
    else
      return SendIllFormedResponse(packet,
                                   "No thread was is set with the Hg packet");
  }

  // Grab the register context for the thread.
  NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext());
  if (!reg_context_sp) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64
          " failed, no register context available for the thread",
          __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID());
    return SendErrorResponse(0x15);
  }

  // Retrieve register state buffer, then remove from the list.
  DataBufferSP register_data_sp;
  {
    std::lock_guard<std::mutex> guard(m_saved_registers_mutex);

    // Find the register set buffer for the given save id.
    auto it = m_saved_registers_map.find(save_id);
    if (it == m_saved_registers_map.end()) {
      if (log)
        log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                    " does not have a register set save buffer for id %" PRIu32,
                    __FUNCTION__, m_debugged_process_sp->GetID(), save_id);
      return SendErrorResponse(0x77);
    }
    register_data_sp = it->second;

    // Remove it from the map.
    m_saved_registers_map.erase(it);
  }

  Status error = reg_context_sp->WriteAllRegisterValues(register_data_sp);
  if (error.Fail()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
                  " failed to restore all register values: %s",
                  __FUNCTION__, m_debugged_process_sp->GetID(),
                  error.AsCString());
    return SendErrorResponse(0x77);
  }

  return SendOKResponse();
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_vAttach(
    StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  // Consume the ';' after vAttach.
  packet.SetFilePos(strlen("vAttach"));
  if (!packet.GetBytesLeft() || packet.GetChar() != ';')
    return SendIllFormedResponse(packet, "vAttach missing expected ';'");

  // Grab the PID to which we will attach (assume hex encoding).
  lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
  if (pid == LLDB_INVALID_PROCESS_ID)
    return SendIllFormedResponse(packet,
                                 "vAttach failed to parse the process id");

  // Attempt to attach.
  if (log)
    log->Printf("GDBRemoteCommunicationServerLLGS::%s attempting to attach to "
                "pid %" PRIu64,
                __FUNCTION__, pid);

  Status error = AttachToProcess(pid);

  if (error.Fail()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to attach to "
                  "pid %" PRIu64 ": %s\n",
                  __FUNCTION__, pid, error.AsCString());
    return SendErrorResponse(0x01);
  }

  // Notify we attached by sending a stop packet.
  return SendStopReasonForState(m_debugged_process_sp->GetState());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  StopSTDIOForwarding();

  // Fail if we don't have a current process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
    if (log)
      log->Printf(
          "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
          __FUNCTION__);
    return SendErrorResponse(0x15);
  }

  lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;

  // Consume the ';' after D.
  packet.SetFilePos(1);
  if (packet.GetBytesLeft()) {
    if (packet.GetChar() != ';')
      return SendIllFormedResponse(packet, "D missing expected ';'");

    // Grab the PID from which we will detach (assume hex encoding).
    pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
    if (pid == LLDB_INVALID_PROCESS_ID)
      return SendIllFormedResponse(packet, "D failed to parse the process id");
  }

  if (pid != LLDB_INVALID_PROCESS_ID && m_debugged_process_sp->GetID() != pid) {
    return SendIllFormedResponse(packet, "Invalid pid");
  }

  const Status error = m_debugged_process_sp->Detach();
  if (error.Fail()) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to detach from "
                  "pid %" PRIu64 ": %s\n",
                  __FUNCTION__, m_debugged_process_sp->GetID(),
                  error.AsCString());
    return SendErrorResponse(0x01);
  }

  return SendOKResponse();
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo(
    StringExtractorGDBRemote &packet) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));

  packet.SetFilePos(strlen("qThreadStopInfo"));
  const lldb::tid_t tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
  if (tid == LLDB_INVALID_THREAD_ID) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not "
                  "parse thread id from request \"%s\"",
                  __FUNCTION__, packet.GetStringRef().c_str());
    return SendErrorResponse(0x15);
  }
  return SendStopReplyPacketForThread(tid);
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo(
    StringExtractorGDBRemote &) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));

  // Ensure we have a debugged process.
  if (!m_debugged_process_sp ||
      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
    return SendErrorResponse(50);

  if (log)
    log->Printf("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid "
                "%" PRIu64,
                __FUNCTION__, m_debugged_process_sp->GetID());

  StreamString response;
  const bool threads_with_valid_stop_info_only = false;
  JSONArray::SP threads_array_sp = GetJSONThreadsInfo(
      *m_debugged_process_sp, threads_with_valid_stop_info_only);
  if (!threads_array_sp) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to prepare a "
                  "packet for pid %" PRIu64,
                  __FUNCTION__, m_debugged_process_sp->GetID());
    return SendErrorResponse(52);
  }

  threads_array_sp->Write(response);
  StreamGDBRemote escaped_response;
  escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
  return SendPacketNoLock(escaped_response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo(
    StringExtractorGDBRemote &packet) {
  // Fail if we don't have a current process.
  if (!m_debugged_process_sp ||
      m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)
    return SendErrorResponse(68);

  packet.SetFilePos(strlen("qWatchpointSupportInfo"));
  if (packet.GetBytesLeft() == 0)
    return SendOKResponse();
  if (packet.GetChar() != ':')
    return SendErrorResponse(67);

  auto hw_debug_cap = m_debugged_process_sp->GetHardwareDebugSupportInfo();

  StreamGDBRemote response;
  if (hw_debug_cap == llvm::None)
    response.Printf("num:0;");
  else
    response.Printf("num:%d;", hw_debug_cap->second);

  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress(
    StringExtractorGDBRemote &packet) {
  // Fail if we don't have a current process.
  if (!m_debugged_process_sp ||
      m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)
    return SendErrorResponse(67);

  packet.SetFilePos(strlen("qFileLoadAddress:"));
  if (packet.GetBytesLeft() == 0)
    return SendErrorResponse(68);

  std::string file_name;
  packet.GetHexByteString(file_name);

  lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS;
  Status error =
      m_debugged_process_sp->GetFileLoadAddress(file_name, file_load_address);
  if (error.Fail())
    return SendErrorResponse(69);

  if (file_load_address == LLDB_INVALID_ADDRESS)
    return SendErrorResponse(1); // File not loaded

  StreamGDBRemote response;
  response.PutHex64(file_load_address);
  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
    StringExtractorGDBRemote &packet) {
  std::vector<int> signals;
  packet.SetFilePos(strlen("QPassSignals:"));

  // Read sequence of hex signal numbers divided by a semicolon and
  // optionally spaces.
  while (packet.GetBytesLeft() > 0) {
    int signal = packet.GetS32(-1, 16);
    if (signal < 0)
      return SendIllFormedResponse(packet, "Failed to parse signal number.");
    signals.push_back(signal);

    packet.SkipSpaces();
    char separator = packet.GetChar();
    if (separator == '\0')
      break; // End of string
    if (separator != ';')
      return SendIllFormedResponse(packet, "Invalid separator,"
                                            " expected semicolon.");
  }

  // Fail if we don't have a current process.
  if (!m_debugged_process_sp)
    return SendErrorResponse(68);

  Status error = m_debugged_process_sp->IgnoreSignals(signals);
  if (error.Fail())
    return SendErrorResponse(69);

  return SendOKResponse();
}

void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  // Tell the stdio connection to shut down.
  if (m_stdio_communication.IsConnected()) {
    auto connection = m_stdio_communication.GetConnection();
    if (connection) {
      Status error;
      connection->Disconnect(&error);

      if (error.Success()) {
        if (log)
          log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process "
                      "terminal stdio - SUCCESS",
                      __FUNCTION__);
      } else {
        if (log)
          log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process "
                      "terminal stdio - FAIL: %s",
                      __FUNCTION__, error.AsCString());
      }
    }
  }
}

NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
    StringExtractorGDBRemote &packet) {
  NativeThreadProtocolSP thread_sp;

  // We have no thread if we don't have a process.
  if (!m_debugged_process_sp ||
      m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)
    return thread_sp;

  // If the client hasn't asked for thread suffix support, there will not be a
  // thread suffix.
  // Use the current thread in that case.
  if (!m_thread_suffix_supported) {
    const lldb::tid_t current_tid = GetCurrentThreadID();
    if (current_tid == LLDB_INVALID_THREAD_ID)
      return thread_sp;
    else if (current_tid == 0) {
      // Pick a thread.
      return m_debugged_process_sp->GetThreadAtIndex(0);
    } else
      return m_debugged_process_sp->GetThreadByID(current_tid);
  }

  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));

  // Parse out the ';'.
  if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse "
                  "error: expected ';' prior to start of thread suffix: packet "
                  "contents = '%s'",
                  __FUNCTION__, packet.GetStringRef().c_str());
    return thread_sp;
  }

  if (!packet.GetBytesLeft())
    return thread_sp;

  // Parse out thread: portion.
  if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) {
    if (log)
      log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse "
                  "error: expected 'thread:' but not found, packet contents = "
                  "'%s'",
                  __FUNCTION__, packet.GetStringRef().c_str());
    return thread_sp;
  }
  packet.SetFilePos(packet.GetFilePos() + strlen("thread:"));
  const lldb::tid_t tid = packet.GetHexMaxU64(false, 0);
  if (tid != 0)
    return m_debugged_process_sp->GetThreadByID(tid);

  return thread_sp;
}

lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const {
  if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) {
    // Use whatever the debug process says is the current thread id
    // since the protocol either didn't specify or specified we want
    // any/all threads marked as the current thread.
    if (!m_debugged_process_sp)
      return LLDB_INVALID_THREAD_ID;
    return m_debugged_process_sp->GetCurrentThreadID();
  }
  // Use the specific current thread id set by the gdb remote protocol.
  return m_current_tid;
}

uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() {
  std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
  return m_next_saved_registers_id++;
}

void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));

  LLDB_LOG(log, "clearing auxv buffer: {0}", m_active_auxv_buffer_up.get());
  m_active_auxv_buffer_up.reset();
}

FileSpec
GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path,
                                                 const ArchSpec &arch) {
  if (m_debugged_process_sp) {
    FileSpec file_spec;
    if (m_debugged_process_sp
            ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec)
            .Success()) {
      if (file_spec.Exists())
        return file_spec;
    }
  }

  return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch);
}
