//===-- 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/Core/StreamGDBRemote.h"

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

// Other libraries and framework includes
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Debug.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StringConvert.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/JSON.h"
#include "lldb/Utility/LLDBAssert.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ScopedPrinter.h"

// Project includes
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "Utility/StringExtractorGDBRemote.h"
#include "Utility/UriParser.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_active_auxv_buffer_sp(), m_saved_registers_mutex(),
      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);

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

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

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

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

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

  if (!m_process_launch_info.GetArguments().GetArgumentCount())
    return Error("%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);

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

Error GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
  Error 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 Error("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) {
  RegisterValue reg_value;
  if (!reg_value_p) {
    Error 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(), false);
  } 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,
                                         bool abridged) {
  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};
  static const uint32_t k_abridged_expedited_registers[] = {
      LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM};

  for (const uint32_t *generic_reg_p = abridged ? k_abridged_expedited_registers
                                                : 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;
    Error 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);

    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 (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp, abridged))
      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());
    }
  }

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

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

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

Error GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) {
  Error 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 Error();
}

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

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

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

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

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

  const GDBStoppointType stoppoint_type =
      GDBStoppointType(packet.GetS32(eStoppointInvalid));
  switch (stoppoint_type) {
  case eBreakpointHardware:
    want_breakpoint = 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 Error error = m_debugged_process_sp->RemoveBreakpoint(addr);
    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 Error 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);
  Error 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__)
  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_sp) {
    // 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.
    m_active_auxv_buffer_sp = Host::GetAuxvData(m_debugged_process_sp->GetID());
    if (!m_active_auxv_buffer_sp ||
        m_active_auxv_buffer_sp->GetByteSize() == 0) {
      // Hmm, no auxv data, call that an error.
      if (log)
        log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no auxv data "
                    "retrieved",
                    __FUNCTION__);
      m_active_auxv_buffer_sp.reset();
      return SendErrorResponse(0x11);
    }
  }

  // FIXME find out if/how I lock the stream here.

  StreamGDBRemote response;
  bool done_with_buffer = false;

  if (auxv_offset >= m_active_auxv_buffer_sp->GetByteSize()) {
    // 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.
    const uint64_t bytes_remaining =
        m_active_auxv_buffer_sp->GetByteSize() - auxv_offset;

    // Figure out how many bytes we're going to read.
    const uint64_t bytes_to_read =
        (auxv_length > bytes_remaining) ? bytes_remaining : auxv_length;

    // Mark the response type according to whether we're reading the remainder
    // of the auxv data.
    if (bytes_to_read >= bytes_remaining) {
      // 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');
    }

    // Now write the data in encoded binary form.
    response.PutEscapedBytes(m_active_auxv_buffer_sp->GetBytes() + auxv_offset,
                             bytes_to_read);
  }

  if (done_with_buffer)
    m_active_auxv_buffer_sp.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;
  Error 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);
  }

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

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

  uint32_t num = m_debugged_process_sp->GetMaxWatchpoints();
  StreamGDBRemote response;
  response.Printf("num:%d;", num);
  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;
  Error 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());
}

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) {
      Error 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 | GDBR_LOG_PROCESS));
  if (log)
    log->Printf("GDBRemoteCommunicationServerLLGS::%s()", __FUNCTION__);

// Clear any auxv cached data.
// *BSD impls should be able to do this too.
#if defined(__linux__)
  if (log)
    log->Printf("GDBRemoteCommunicationServerLLGS::%s clearing auxv buffer "
                "(previously %s)",
                __FUNCTION__,
                m_active_auxv_buffer_sp ? "was set" : "was not set");
  m_active_auxv_buffer_sp.reset();
#endif
}

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