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

#include "PlatformRemoteGDBServer.h"
#include "lldb/Host/Config.h"

#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/ProcessInfo.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/UriParser.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/FormatAdapters.h"

#include "Plugins/Process/Utility/GDBRemoteSignals.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
#include <mutex>
#include <optional>

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_gdb_server;

LLDB_PLUGIN_DEFINE_ADV(PlatformRemoteGDBServer, PlatformGDB)

static bool g_initialized = false;
// UnixSignals does not store the signal names or descriptions itself.
// It holds onto StringRefs. Becaue we may get signal information dynamically
// from the remote, these strings need persistent storage client-side.
static std::mutex g_signal_string_mutex;
static llvm::StringSet<> g_signal_string_storage;

void PlatformRemoteGDBServer::Initialize() {
  Platform::Initialize();

  if (!g_initialized) {
    g_initialized = true;
    PluginManager::RegisterPlugin(
        PlatformRemoteGDBServer::GetPluginNameStatic(),
        PlatformRemoteGDBServer::GetDescriptionStatic(),
        PlatformRemoteGDBServer::CreateInstance);
  }
}

void PlatformRemoteGDBServer::Terminate() {
  if (g_initialized) {
    g_initialized = false;
    PluginManager::UnregisterPlugin(PlatformRemoteGDBServer::CreateInstance);
  }

  Platform::Terminate();
}

PlatformSP PlatformRemoteGDBServer::CreateInstance(bool force,
                                                   const ArchSpec *arch) {
  bool create = force;
  if (!create) {
    create = !arch->TripleVendorWasSpecified() && !arch->TripleOSWasSpecified();
  }
  if (create)
    return PlatformSP(new PlatformRemoteGDBServer());
  return PlatformSP();
}

llvm::StringRef PlatformRemoteGDBServer::GetDescriptionStatic() {
  return "A platform that uses the GDB remote protocol as the communication "
         "transport.";
}

llvm::StringRef PlatformRemoteGDBServer::GetDescription() {
  if (m_platform_description.empty()) {
    if (IsConnected()) {
      // Send the get description packet
    }
  }

  if (!m_platform_description.empty())
    return m_platform_description.c_str();
  return GetDescriptionStatic();
}

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

  const auto module_path = module_file_spec.GetPath(false);

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

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

  return true;
}

Status PlatformRemoteGDBServer::GetFileWithUUID(const FileSpec &platform_file,
                                                const UUID *uuid_ptr,
                                                FileSpec &local_file) {
  // Default to the local case
  local_file = platform_file;
  return Status();
}

/// Default Constructor
PlatformRemoteGDBServer::PlatformRemoteGDBServer()
    : Platform(/*is_host=*/false) {}

/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
PlatformRemoteGDBServer::~PlatformRemoteGDBServer() = default;

size_t PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode(
    Target &target, BreakpointSite *bp_site) {
  // This isn't needed if the z/Z packets are supported in the GDB remote
  // server. But we might need a packet to detect this.
  return 0;
}

bool PlatformRemoteGDBServer::GetRemoteOSVersion() {
  if (m_gdb_client_up)
    m_os_version = m_gdb_client_up->GetOSVersion();
  return !m_os_version.empty();
}

std::optional<std::string> PlatformRemoteGDBServer::GetRemoteOSBuildString() {
  if (!m_gdb_client_up)
    return std::nullopt;
  return m_gdb_client_up->GetOSBuildString();
}

std::optional<std::string>
PlatformRemoteGDBServer::GetRemoteOSKernelDescription() {
  if (!m_gdb_client_up)
    return std::nullopt;
  return m_gdb_client_up->GetOSKernelDescription();
}

// Remote Platform subclasses need to override this function
ArchSpec PlatformRemoteGDBServer::GetRemoteSystemArchitecture() {
  if (!m_gdb_client_up)
    return ArchSpec();
  return m_gdb_client_up->GetSystemArchitecture();
}

FileSpec PlatformRemoteGDBServer::GetRemoteWorkingDirectory() {
  if (IsConnected()) {
    Log *log = GetLog(LLDBLog::Platform);
    FileSpec working_dir;
    if (m_gdb_client_up->GetWorkingDir(working_dir) && log)
      LLDB_LOGF(log,
                "PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'",
                working_dir.GetPath().c_str());
    return working_dir;
  } else {
    return Platform::GetRemoteWorkingDirectory();
  }
}

bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory(
    const FileSpec &working_dir) {
  if (IsConnected()) {
    // Clear the working directory it case it doesn't get set correctly. This
    // will for use to re-read it
    Log *log = GetLog(LLDBLog::Platform);
    LLDB_LOGF(log, "PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')",
              working_dir.GetPath().c_str());
    return m_gdb_client_up->SetWorkingDir(working_dir) == 0;
  } else
    return Platform::SetRemoteWorkingDirectory(working_dir);
}

bool PlatformRemoteGDBServer::IsConnected() const {
  return m_gdb_client_up && m_gdb_client_up->IsConnected();
}

Status PlatformRemoteGDBServer::ConnectRemote(Args &args) {
  Status error;
  if (IsConnected())
    return Status::FromErrorStringWithFormat(
        "the platform is already connected to '%s', "
        "execute 'platform disconnect' to close the "
        "current connection",
        GetHostname());

  if (args.GetArgumentCount() != 1)
    return Status::FromErrorString(
        "\"platform connect\" takes a single argument: <connect-url>");

  const char *url = args.GetArgumentAtIndex(0);
  if (!url)
    return Status::FromErrorString("URL is null.");

  std::optional<URI> parsed_url = URI::Parse(url);
  if (!parsed_url)
    return Status::FromErrorStringWithFormat("Invalid URL: %s", url);

  // We're going to reuse the hostname when we connect to the debugserver.
  m_platform_scheme = parsed_url->scheme.str();
  m_platform_hostname = parsed_url->hostname.str();

  auto client_up =
      std::make_unique<process_gdb_remote::GDBRemoteCommunicationClient>();
  client_up->SetPacketTimeout(
      process_gdb_remote::ProcessGDBRemote::GetPacketTimeout());
  client_up->SetConnection(std::make_unique<ConnectionFileDescriptor>());
  client_up->Connect(url, &error);

  if (error.Fail())
    return error;

  if (client_up->HandshakeWithServer(&error)) {
    m_gdb_client_up = std::move(client_up);
    m_gdb_client_up->GetHostInfo();
    // If a working directory was set prior to connecting, send it down
    // now.
    if (m_working_dir)
      m_gdb_client_up->SetWorkingDir(m_working_dir);

    m_supported_architectures.clear();
    ArchSpec remote_arch = m_gdb_client_up->GetSystemArchitecture();
    if (remote_arch) {
      m_supported_architectures.push_back(remote_arch);
      if (remote_arch.GetTriple().isArch64Bit())
        m_supported_architectures.push_back(
            ArchSpec(remote_arch.GetTriple().get32BitArchVariant()));
    }
  } else {
    client_up->Disconnect();
    if (error.Success())
      error = Status::FromErrorString("handshake failed");
  }
  return error;
}

Status PlatformRemoteGDBServer::DisconnectRemote() {
  Status error;
  m_gdb_client_up.reset();
  m_remote_signals_sp.reset();
  return error;
}

const char *PlatformRemoteGDBServer::GetHostname() {
  if (m_gdb_client_up)
    m_gdb_client_up->GetHostname(m_hostname);
  if (m_hostname.empty())
    return nullptr;
  return m_hostname.c_str();
}

std::optional<std::string>
PlatformRemoteGDBServer::DoGetUserName(UserIDResolver::id_t uid) {
  std::string name;
  if (m_gdb_client_up && m_gdb_client_up->GetUserName(uid, name))
    return std::move(name);
  return std::nullopt;
}

std::optional<std::string>
PlatformRemoteGDBServer::DoGetGroupName(UserIDResolver::id_t gid) {
  std::string name;
  if (m_gdb_client_up && m_gdb_client_up->GetGroupName(gid, name))
    return std::move(name);
  return std::nullopt;
}

uint32_t PlatformRemoteGDBServer::FindProcesses(
    const ProcessInstanceInfoMatch &match_info,
    ProcessInstanceInfoList &process_infos) {
  if (m_gdb_client_up)
    return m_gdb_client_up->FindProcesses(match_info, process_infos);
  return 0;
}

bool PlatformRemoteGDBServer::GetProcessInfo(
    lldb::pid_t pid, ProcessInstanceInfo &process_info) {
  if (m_gdb_client_up)
    return m_gdb_client_up->GetProcessInfo(pid, process_info);
  return false;
}

Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) {
  Log *log = GetLog(LLDBLog::Platform);
  Status error;

  LLDB_LOGF(log, "PlatformRemoteGDBServer::%s() called", __FUNCTION__);

  if (!IsConnected())
    return Status::FromErrorStringWithFormat("Not connected.");
  auto num_file_actions = launch_info.GetNumFileActions();
  for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) {
    const auto file_action = launch_info.GetFileActionAtIndex(i);
    if (file_action->GetAction() != FileAction::eFileActionOpen)
      continue;
    switch (file_action->GetFD()) {
    case STDIN_FILENO:
      m_gdb_client_up->SetSTDIN(file_action->GetFileSpec());
      break;
    case STDOUT_FILENO:
      m_gdb_client_up->SetSTDOUT(file_action->GetFileSpec());
      break;
    case STDERR_FILENO:
      m_gdb_client_up->SetSTDERR(file_action->GetFileSpec());
      break;
    }
  }

  m_gdb_client_up->SetDisableASLR(
      launch_info.GetFlags().Test(eLaunchFlagDisableASLR));
  m_gdb_client_up->SetDetachOnError(
      launch_info.GetFlags().Test(eLaunchFlagDetachOnError));

  FileSpec working_dir = launch_info.GetWorkingDirectory();
  if (working_dir) {
    m_gdb_client_up->SetWorkingDir(working_dir);
  }

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

  ArchSpec arch_spec = launch_info.GetArchitecture();
  const char *arch_triple = arch_spec.GetTriple().str().c_str();

  m_gdb_client_up->SendLaunchArchPacket(arch_triple);
  LLDB_LOGF(
      log,
      "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'",
      __FUNCTION__, arch_triple ? arch_triple : "<NULL>");

  {
    // Scope for the scoped timeout object
    process_gdb_remote::GDBRemoteCommunication::ScopedTimeout timeout(
        *m_gdb_client_up, std::chrono::seconds(5));
    // Since we can't send argv0 separate from the executable path, we need to
    // make sure to use the actual executable path found in the launch_info...
    Args args = launch_info.GetArguments();
    if (FileSpec exe_file = launch_info.GetExecutableFile())
      args.ReplaceArgumentAtIndex(0, exe_file.GetPath(false));
    if (llvm::Error err = m_gdb_client_up->LaunchProcess(args)) {
      error = Status::FromErrorStringWithFormatv(
          "Cannot launch '{0}': {1}", args.GetArgumentAtIndex(0),
          llvm::fmt_consume(std::move(err)));
      return error;
    }
  }

  const auto pid = m_gdb_client_up->GetCurrentProcessID(false);
  if (pid != LLDB_INVALID_PROCESS_ID) {
    launch_info.SetProcessID(pid);
    LLDB_LOGF(log,
              "PlatformRemoteGDBServer::%s() pid %" PRIu64
              " launched successfully",
              __FUNCTION__, pid);
  } else {
    LLDB_LOGF(log,
              "PlatformRemoteGDBServer::%s() launch succeeded but we "
              "didn't get a valid process id back!",
              __FUNCTION__);
    error = Status::FromErrorString("failed to get PID");
  }
  return error;
}

Status PlatformRemoteGDBServer::KillProcess(const lldb::pid_t pid) {
  if (!KillSpawnedProcess(pid))
    return Status::FromErrorStringWithFormat(
        "failed to kill remote spawned process");
  return Status();
}

lldb::ProcessSP
PlatformRemoteGDBServer::DebugProcess(ProcessLaunchInfo &launch_info,
                                      Debugger &debugger, Target &target,
                                      Status &error) {
  lldb::ProcessSP process_sp;
  if (IsRemote()) {
    if (IsConnected()) {
      lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
      std::string connect_url;
      if (!LaunchGDBServer(debugserver_pid, connect_url)) {
        error = Status::FromErrorStringWithFormat(
            "unable to launch a GDB server on '%s'", GetHostname());
      } else {
        // By default, we always use the GDB remote debugger plug-in.
        // Even when debugging locally, we are debugging remotely.
        llvm::StringRef process_plugin = GetDefaultProcessPluginName();

        // However, if a process plugin is specified by the attach info, we
        // should honor it.
        if (!launch_info.GetProcessPluginName().empty())
          process_plugin = launch_info.GetProcessPluginName();

        process_sp = target.CreateProcess(launch_info.GetListener(),
                                          process_plugin, nullptr, true);

        if (process_sp) {
          process_sp->HijackProcessEvents(launch_info.GetHijackListener());
          process_sp->SetShadowListener(launch_info.GetShadowListener());

          error = process_sp->ConnectRemote(connect_url.c_str());
          // Retry the connect remote one time...
          if (error.Fail())
            error = process_sp->ConnectRemote(connect_url.c_str());
          if (error.Success())
            error = process_sp->Launch(launch_info);
          else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) {
            printf("error: connect remote failed (%s)\n", error.AsCString());
            KillSpawnedProcess(debugserver_pid);
          }
        }
      }
    } else {
      error = Status::FromErrorString("not connected to remote gdb server");
    }
  }
  return process_sp;
}

bool PlatformRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid,
                                              std::string &connect_url) {
  assert(IsConnected());

  ArchSpec remote_arch = GetRemoteSystemArchitecture();
  llvm::Triple &remote_triple = remote_arch.GetTriple();

  uint16_t port = 0;
  std::string socket_name;
  bool launch_result = false;
  if (remote_triple.getVendor() == llvm::Triple::Apple &&
      remote_triple.getOS() == llvm::Triple::IOS) {
    // When remote debugging to iOS, we use a USB mux that always talks to
    // localhost, so we will need the remote debugserver to accept connections
    // only from localhost, no matter what our current hostname is
    launch_result =
        m_gdb_client_up->LaunchGDBServer("127.0.0.1", pid, port, socket_name);
  } else {
    // All other hosts should use their actual hostname
    launch_result =
        m_gdb_client_up->LaunchGDBServer(nullptr, pid, port, socket_name);
  }

  if (!launch_result)
    return false;

  connect_url =
      MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port,
                       (socket_name.empty()) ? nullptr : socket_name.c_str());
  return true;
}

bool PlatformRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) {
  assert(IsConnected());
  return m_gdb_client_up->KillSpawnedProcess(pid);
}

lldb::ProcessSP PlatformRemoteGDBServer::Attach(
    ProcessAttachInfo &attach_info, Debugger &debugger,
    Target *target, // Can be NULL, if NULL create a new target, else use
                    // existing one
    Status &error) {
  lldb::ProcessSP process_sp;
  if (IsRemote()) {
    if (IsConnected()) {
      lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
      std::string connect_url;
      if (!LaunchGDBServer(debugserver_pid, connect_url)) {
        error = Status::FromErrorStringWithFormat(
            "unable to launch a GDB server on '%s'", GetHostname());
      } else {
        if (target == nullptr) {
          TargetSP new_target_sp;

          error = debugger.GetTargetList().CreateTarget(
              debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);
          target = new_target_sp.get();
        } else
          error.Clear();

        if (target && error.Success()) {
          // By default, we always use the GDB remote debugger plug-in.
          // Even when debugging locally, we are debugging remotely.
          llvm::StringRef process_plugin = GetDefaultProcessPluginName();

          // However, if a process plugin is specified by the attach info, we
          // should honor it.
          if (!attach_info.GetProcessPluginName().empty())
            process_plugin = attach_info.GetProcessPluginName();

          process_sp =
              target->CreateProcess(attach_info.GetListenerForProcess(debugger),
                                    process_plugin, nullptr, true);
          if (process_sp) {
            error = process_sp->ConnectRemote(connect_url.c_str());
            if (error.Success()) {
              ListenerSP listener_sp = attach_info.GetHijackListener();
              if (listener_sp)
                process_sp->HijackProcessEvents(listener_sp);
              process_sp->SetShadowListener(attach_info.GetShadowListener());
              error = process_sp->Attach(attach_info);
            }

            if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID) {
              KillSpawnedProcess(debugserver_pid);
            }
          }
        }
      }
    } else {
      error = Status::FromErrorString("not connected to remote gdb server");
    }
  }
  return process_sp;
}

Status PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec,
                                              uint32_t mode) {
  if (!IsConnected())
    return Status::FromErrorStringWithFormat("Not connected.");
  Status error = m_gdb_client_up->MakeDirectory(file_spec, mode);
  Log *log = GetLog(LLDBLog::Platform);
  LLDB_LOGF(log,
            "PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) "
            "error = %u (%s)",
            file_spec.GetPath().c_str(), mode, error.GetError(),
            error.AsCString());
  return error;
}

Status PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec,
                                                   uint32_t &file_permissions) {
  if (!IsConnected())
    return Status::FromErrorStringWithFormat("Not connected.");
  Status error =
      m_gdb_client_up->GetFilePermissions(file_spec, file_permissions);
  Log *log = GetLog(LLDBLog::Platform);
  LLDB_LOGF(log,
            "PlatformRemoteGDBServer::GetFilePermissions(path='%s', "
            "file_permissions=%o) error = %u (%s)",
            file_spec.GetPath().c_str(), file_permissions, error.GetError(),
            error.AsCString());
  return error;
}

Status PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec,
                                                   uint32_t file_permissions) {
  if (!IsConnected())
    return Status::FromErrorStringWithFormat("Not connected.");
  Status error =
      m_gdb_client_up->SetFilePermissions(file_spec, file_permissions);
  Log *log = GetLog(LLDBLog::Platform);
  LLDB_LOGF(log,
            "PlatformRemoteGDBServer::SetFilePermissions(path='%s', "
            "file_permissions=%o) error = %u (%s)",
            file_spec.GetPath().c_str(), file_permissions, error.GetError(),
            error.AsCString());
  return error;
}

lldb::user_id_t PlatformRemoteGDBServer::OpenFile(const FileSpec &file_spec,
                                                  File::OpenOptions flags,
                                                  uint32_t mode,
                                                  Status &error) {
  if (IsConnected())
    return m_gdb_client_up->OpenFile(file_spec, flags, mode, error);
  return LLDB_INVALID_UID;
}

bool PlatformRemoteGDBServer::CloseFile(lldb::user_id_t fd, Status &error) {
  if (IsConnected())
    return m_gdb_client_up->CloseFile(fd, error);
  error = Status::FromErrorStringWithFormat("Not connected.");
  return false;
}

lldb::user_id_t
PlatformRemoteGDBServer::GetFileSize(const FileSpec &file_spec) {
  if (IsConnected())
    return m_gdb_client_up->GetFileSize(file_spec);
  return LLDB_INVALID_UID;
}

void PlatformRemoteGDBServer::AutoCompleteDiskFileOrDirectory(
    CompletionRequest &request, bool only_dir) {
  if (IsConnected())
    m_gdb_client_up->AutoCompleteDiskFileOrDirectory(request, only_dir);
}

uint64_t PlatformRemoteGDBServer::ReadFile(lldb::user_id_t fd, uint64_t offset,
                                           void *dst, uint64_t dst_len,
                                           Status &error) {
  if (IsConnected())
    return m_gdb_client_up->ReadFile(fd, offset, dst, dst_len, error);
  error = Status::FromErrorStringWithFormat("Not connected.");
  return 0;
}

uint64_t PlatformRemoteGDBServer::WriteFile(lldb::user_id_t fd, uint64_t offset,
                                            const void *src, uint64_t src_len,
                                            Status &error) {
  if (IsConnected())
    return m_gdb_client_up->WriteFile(fd, offset, src, src_len, error);
  error = Status::FromErrorStringWithFormat("Not connected.");
  return 0;
}

Status PlatformRemoteGDBServer::PutFile(const FileSpec &source,
                                        const FileSpec &destination,
                                        uint32_t uid, uint32_t gid) {
  return Platform::PutFile(source, destination, uid, gid);
}

Status PlatformRemoteGDBServer::CreateSymlink(
    const FileSpec &src, // The name of the link is in src
    const FileSpec &dst) // The symlink points to dst
{
  if (!IsConnected())
    return Status::FromErrorStringWithFormat("Not connected.");
  Status error = m_gdb_client_up->CreateSymlink(src, dst);
  Log *log = GetLog(LLDBLog::Platform);
  LLDB_LOGF(log,
            "PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') "
            "error = %u (%s)",
            src.GetPath().c_str(), dst.GetPath().c_str(), error.GetError(),
            error.AsCString());
  return error;
}

Status PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) {
  if (!IsConnected())
    return Status::FromErrorStringWithFormat("Not connected.");
  Status error = m_gdb_client_up->Unlink(file_spec);
  Log *log = GetLog(LLDBLog::Platform);
  LLDB_LOGF(log, "PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)",
            file_spec.GetPath().c_str(), error.GetError(), error.AsCString());
  return error;
}

bool PlatformRemoteGDBServer::GetFileExists(const FileSpec &file_spec) {
  if (IsConnected())
    return m_gdb_client_up->GetFileExists(file_spec);
  return false;
}

Status PlatformRemoteGDBServer::RunShellCommand(
    llvm::StringRef shell, llvm::StringRef command,
    const FileSpec &
        working_dir, // Pass empty FileSpec to use the current working directory
    int *status_ptr, // Pass NULL if you don't want the process exit status
    int *signo_ptr,  // Pass NULL if you don't want the signal that caused the
                     // process to exit
    std::string
        *command_output, // Pass nullptr if you don't want the command output
    std::string *separated_error_output, // Pass nullptr if you don't want the
                                         // error output
    const Timeout<std::micro> &timeout) {
  if (!IsConnected())
    return Status::FromErrorStringWithFormat("Not connected.");
  return m_gdb_client_up->RunShellCommand(command, working_dir, status_ptr,
                                          signo_ptr, command_output,
                                          separated_error_output, timeout);
}

llvm::ErrorOr<llvm::MD5::MD5Result>
PlatformRemoteGDBServer::CalculateMD5(const FileSpec &file_spec) {
  if (!IsConnected())
    return std::make_error_code(std::errc::not_connected);

  return m_gdb_client_up->CalculateMD5(file_spec);
}

void PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames() {
  m_trap_handlers.push_back(ConstString("_sigtramp"));
}

const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() {
  if (!IsConnected())
    return Platform::GetRemoteUnixSignals();

  if (m_remote_signals_sp)
    return m_remote_signals_sp;

  // If packet not implemented or JSON failed to parse, we'll guess the signal
  // set based on the remote architecture.
  m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture());

  StringExtractorGDBRemote response;
  auto result =
      m_gdb_client_up->SendPacketAndWaitForResponse("jSignalsInfo", response);

  if (result != decltype(result)::Success ||
      response.GetResponseType() != response.eResponse)
    return m_remote_signals_sp;

  auto object_sp = StructuredData::ParseJSON(response.GetStringRef());
  if (!object_sp || !object_sp->IsValid())
    return m_remote_signals_sp;

  auto array_sp = object_sp->GetAsArray();
  if (!array_sp || !array_sp->IsValid())
    return m_remote_signals_sp;

  auto remote_signals_sp = std::make_shared<lldb_private::GDBRemoteSignals>();

  bool done = array_sp->ForEach(
      [&remote_signals_sp](StructuredData::Object *object) -> bool {
        if (!object || !object->IsValid())
          return false;

        auto dict = object->GetAsDictionary();
        if (!dict || !dict->IsValid())
          return false;

        // Signal number and signal name are required.
        uint64_t signo;
        if (!dict->GetValueForKeyAsInteger("signo", signo))
          return false;

        llvm::StringRef name;
        if (!dict->GetValueForKeyAsString("name", name))
          return false;

        // We can live without short_name, description, etc.
        bool suppress{false};
        auto object_sp = dict->GetValueForKey("suppress");
        if (object_sp && object_sp->IsValid())
          suppress = object_sp->GetBooleanValue();

        bool stop{false};
        object_sp = dict->GetValueForKey("stop");
        if (object_sp && object_sp->IsValid())
          stop = object_sp->GetBooleanValue();

        bool notify{false};
        object_sp = dict->GetValueForKey("notify");
        if (object_sp && object_sp->IsValid())
          notify = object_sp->GetBooleanValue();

        std::string description;
        object_sp = dict->GetValueForKey("description");
        if (object_sp && object_sp->IsValid())
          description = std::string(object_sp->GetStringValue());

        llvm::StringRef name_backed, description_backed;
        {
          std::lock_guard<std::mutex> guard(g_signal_string_mutex);
          name_backed =
              g_signal_string_storage.insert(name).first->getKeyData();
          if (!description.empty())
            description_backed =
                g_signal_string_storage.insert(description).first->getKeyData();
        }

        remote_signals_sp->AddSignal(signo, name_backed, suppress, stop, notify,
                                     description_backed);
        return true;
      });

  if (done)
    m_remote_signals_sp = std::move(remote_signals_sp);

  return m_remote_signals_sp;
}

std::string PlatformRemoteGDBServer::MakeGdbServerUrl(
    const std::string &platform_scheme, const std::string &platform_hostname,
    uint16_t port, const char *socket_name) {
  const char *override_scheme =
      getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME");
  const char *override_hostname =
      getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
  const char *port_offset_c_str =
      getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
  int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;

  return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(),
                 override_hostname ? override_hostname
                                   : platform_hostname.c_str(),
                 port + port_offset, socket_name);
}

std::string PlatformRemoteGDBServer::MakeUrl(const char *scheme,
                                             const char *hostname,
                                             uint16_t port, const char *path) {
  StreamString result;
  result.Printf("%s://", scheme);
  if (strlen(hostname) > 0)
    result.Printf("[%s]", hostname);

  if (port != 0)
    result.Printf(":%u", port);
  if (path)
    result.Write(path, strlen(path));
  return std::string(result.GetString());
}

size_t PlatformRemoteGDBServer::ConnectToWaitingProcesses(Debugger &debugger,
                                                          Status &error) {
  std::vector<std::string> connection_urls;
  GetPendingGdbServerList(connection_urls);

  for (size_t i = 0; i < connection_urls.size(); ++i) {
    ConnectProcess(connection_urls[i].c_str(), GetDefaultProcessPluginName(),
                   debugger, nullptr, error);
    if (error.Fail())
      return i; // We already connected to i process successfully
  }
  return connection_urls.size();
}

size_t PlatformRemoteGDBServer::GetPendingGdbServerList(
    std::vector<std::string> &connection_urls) {
  std::vector<std::pair<uint16_t, std::string>> remote_servers;
  if (!IsConnected())
    return 0;
  m_gdb_client_up->QueryGDBServer(remote_servers);
  for (const auto &gdbserver : remote_servers) {
    const char *socket_name_cstr =
        gdbserver.second.empty() ? nullptr : gdbserver.second.c_str();
    connection_urls.emplace_back(
        MakeGdbServerUrl(m_platform_scheme, m_platform_hostname,
                         gdbserver.first, socket_name_cstr));
  }
  return connection_urls.size();
}
