diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 | 
| commit | 94994d372d014ce4c8758b9605d63fae651bd8aa (patch) | |
| tree | 51c0b708bd59f205d6b35cb2a8c24d62f0c33d77 /source/Plugins/Process/gdb-remote | |
| parent | 39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff) | |
Notes
Diffstat (limited to 'source/Plugins/Process/gdb-remote')
25 files changed, 952 insertions, 377 deletions
| diff --git a/source/Plugins/Process/gdb-remote/CMakeLists.txt b/source/Plugins/Process/gdb-remote/CMakeLists.txt index 7ae25f83c5f8a..4eb5291d54d5a 100644 --- a/source/Plugins/Process/gdb-remote/CMakeLists.txt +++ b/source/Plugins/Process/gdb-remote/CMakeLists.txt @@ -15,6 +15,8 @@ add_lldb_library(lldbPluginProcessGDBRemote PLUGIN    GDBRemoteClientBase.cpp    GDBRemoteCommunication.cpp    GDBRemoteCommunicationClient.cpp +  GDBRemoteCommunicationHistory.cpp +  GDBRemoteCommunicationReplayServer.cpp    GDBRemoteCommunicationServer.cpp    GDBRemoteCommunicationServerCommon.cpp    GDBRemoteCommunicationServerLLGS.cpp diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp index 4e20b56fb111b..a3a4aa053261b 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp @@ -379,7 +379,7 @@ void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {          log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");        m_comm.m_interrupt_time = steady_clock::now();      } -    m_comm.m_cv.wait(lock, [this] { return m_comm.m_is_running == false; }); +    m_comm.m_cv.wait(lock, [this] { return !m_comm.m_is_running; });      m_did_interrupt = true;    }    m_acquired = true; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index c335b60028619..72c1314a7c943 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -9,21 +9,22 @@  #include "GDBRemoteCommunication.h" -// C Includes +#include <future>  #include <limits.h>  #include <string.h>  #include <sys/stat.h> -// C++ Includes -// Other libraries and framework includes  #include "lldb/Core/StreamFile.h"  #include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/FileSystem.h"  #include "lldb/Host/Host.h"  #include "lldb/Host/HostInfo.h"  #include "lldb/Host/Pipe.h"  #include "lldb/Host/Socket.h"  #include "lldb/Host/StringConvert.h"  #include "lldb/Host/ThreadLauncher.h" +#include "lldb/Host/common/TCPSocket.h" +#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"  #include "lldb/Target/Platform.h"  #include "lldb/Target/Process.h"  #include "lldb/Utility/FileSpec.h" @@ -33,7 +34,6 @@  #include "llvm/ADT/SmallString.h"  #include "llvm/Support/ScopedPrinter.h" -// Project includes  #include "ProcessGDBRemoteLog.h"  #if defined(__APPLE__) @@ -42,7 +42,8 @@  #define DEBUGSERVER_BASENAME "lldb-server"  #endif -#if defined(HAVE_LIBCOMPRESSION) +#if defined(__APPLE__) +#define HAVE_LIBCOMPRESSION  #include <compression.h>  #endif @@ -54,78 +55,6 @@ using namespace lldb;  using namespace lldb_private;  using namespace lldb_private::process_gdb_remote; -GDBRemoteCommunication::History::History(uint32_t size) -    : m_packets(), m_curr_idx(0), m_total_packet_count(0), -      m_dumped_to_log(false) { -  m_packets.resize(size); -} - -GDBRemoteCommunication::History::~History() {} - -void GDBRemoteCommunication::History::AddPacket(char packet_char, -                                                PacketType type, -                                                uint32_t bytes_transmitted) { -  const size_t size = m_packets.size(); -  if (size > 0) { -    const uint32_t idx = GetNextIndex(); -    m_packets[idx].packet.assign(1, packet_char); -    m_packets[idx].type = type; -    m_packets[idx].bytes_transmitted = bytes_transmitted; -    m_packets[idx].packet_idx = m_total_packet_count; -    m_packets[idx].tid = llvm::get_threadid(); -  } -} - -void GDBRemoteCommunication::History::AddPacket(const std::string &src, -                                                uint32_t src_len, -                                                PacketType type, -                                                uint32_t bytes_transmitted) { -  const size_t size = m_packets.size(); -  if (size > 0) { -    const uint32_t idx = GetNextIndex(); -    m_packets[idx].packet.assign(src, 0, src_len); -    m_packets[idx].type = type; -    m_packets[idx].bytes_transmitted = bytes_transmitted; -    m_packets[idx].packet_idx = m_total_packet_count; -    m_packets[idx].tid = llvm::get_threadid(); -  } -} - -void GDBRemoteCommunication::History::Dump(Stream &strm) const { -  const uint32_t size = GetNumPacketsInHistory(); -  const uint32_t first_idx = GetFirstSavedPacketIndex(); -  const uint32_t stop_idx = m_curr_idx + size; -  for (uint32_t i = first_idx; i < stop_idx; ++i) { -    const uint32_t idx = NormalizeIndex(i); -    const Entry &entry = m_packets[idx]; -    if (entry.type == ePacketTypeInvalid || entry.packet.empty()) -      break; -    strm.Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n", -                entry.packet_idx, entry.tid, entry.bytes_transmitted, -                (entry.type == ePacketTypeSend) ? "send" : "read", -                entry.packet.c_str()); -  } -} - -void GDBRemoteCommunication::History::Dump(Log *log) const { -  if (log && !m_dumped_to_log) { -    m_dumped_to_log = true; -    const uint32_t size = GetNumPacketsInHistory(); -    const uint32_t first_idx = GetFirstSavedPacketIndex(); -    const uint32_t stop_idx = m_curr_idx + size; -    for (uint32_t i = first_idx; i < stop_idx; ++i) { -      const uint32_t idx = NormalizeIndex(i); -      const Entry &entry = m_packets[idx]; -      if (entry.type == ePacketTypeInvalid || entry.packet.empty()) -        break; -      log->Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s", -                  entry.packet_idx, entry.tid, entry.bytes_transmitted, -                  (entry.type == ePacketTypeSend) ? "send" : "read", -                  entry.packet.c_str()); -    } -  } -} -  //----------------------------------------------------------------------  // GDBRemoteCommunication constructor  //---------------------------------------------------------------------- @@ -139,7 +68,10 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,  #endif        m_echo_number(0), m_supports_qEcho(eLazyBoolCalculate), m_history(512),        m_send_acks(true), m_compression_type(CompressionType::None), -      m_listen_url() { +      m_listen_url(), m_decompression_scratch_type(CompressionType::None), +      m_decompression_scratch(nullptr) { +  // Unused unless HAVE_LIBCOMPRESSION is defined. +  (void)m_decompression_scratch_type;  }  //---------------------------------------------------------------------- @@ -150,6 +82,9 @@ GDBRemoteCommunication::~GDBRemoteCommunication() {      Disconnect();    } +  if (m_decompression_scratch) +    free (m_decompression_scratch); +    // Stop the communications read thread which is used to parse all incoming    // packets.  This function will block until the read thread returns.    if (m_read_thread_enabled) @@ -172,7 +107,8 @@ size_t GDBRemoteCommunication::SendAck() {    const size_t bytes_written = Write(&ch, 1, status, NULL);    if (log)      log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); -  m_history.AddPacket(ch, History::ePacketTypeSend, bytes_written); +  m_history.AddPacket(ch, GDBRemoteCommunicationHistory::ePacketTypeSend, +                      bytes_written);    return bytes_written;  } @@ -183,26 +119,31 @@ size_t GDBRemoteCommunication::SendNack() {    const size_t bytes_written = Write(&ch, 1, status, NULL);    if (log)      log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); -  m_history.AddPacket(ch, History::ePacketTypeSend, bytes_written); +  m_history.AddPacket(ch, GDBRemoteCommunicationHistory::ePacketTypeSend, +                      bytes_written);    return bytes_written;  }  GDBRemoteCommunication::PacketResult  GDBRemoteCommunication::SendPacketNoLock(llvm::StringRef payload) { -  if (IsConnected()) {      StreamString packet(0, 4, eByteOrderBig); -      packet.PutChar('$');      packet.Write(payload.data(), payload.size());      packet.PutChar('#');      packet.PutHex8(CalculcateChecksum(payload)); +    std::string packet_str = packet.GetString(); + +    return SendRawPacketNoLock(packet_str); +} +GDBRemoteCommunication::PacketResult +GDBRemoteCommunication::SendRawPacketNoLock(llvm::StringRef packet, +                                            bool skip_ack) { +  if (IsConnected()) {      Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));      ConnectionStatus status = eConnectionStatusSuccess; -    // TODO: Don't shimmy through a std::string, just use StringRef. -    std::string packet_str = packet.GetString(); -    const char *packet_data = packet_str.c_str(); -    const size_t packet_length = packet.GetSize(); +    const char *packet_data = packet.data(); +    const size_t packet_length = packet.size();      size_t bytes_written = Write(packet_data, packet_length, status, NULL);      if (log) {        size_t binary_start_offset = 0; @@ -241,11 +182,12 @@ GDBRemoteCommunication::SendPacketNoLock(llvm::StringRef payload) {                      (int)packet_length, packet_data);      } -    m_history.AddPacket(packet.GetString(), packet_length, -                        History::ePacketTypeSend, bytes_written); +    m_history.AddPacket(packet.str(), packet_length, +                        GDBRemoteCommunicationHistory::ePacketTypeSend, +                        bytes_written);      if (bytes_written == packet_length) { -      if (GetSendAcks()) +      if (!skip_ack && GetSendAcks())          return GetAck();        else          return PacketResult::Success; @@ -597,7 +539,7 @@ bool GDBRemoteCommunication::DecompressPacket() {    size_t decompressed_bytes = 0;    if (decompressed_bufsize != ULONG_MAX) { -    decompressed_buffer = (uint8_t *)malloc(decompressed_bufsize + 1); +    decompressed_buffer = (uint8_t *)malloc(decompressed_bufsize);      if (decompressed_buffer == nullptr) {        m_bytes.erase(0, size_of_first_packet);        return false; @@ -605,11 +547,10 @@ bool GDBRemoteCommunication::DecompressPacket() {    }  #if defined(HAVE_LIBCOMPRESSION) -  // libcompression is weak linked so check that compression_decode_buffer() is -  // available    if (m_compression_type == CompressionType::ZlibDeflate ||        m_compression_type == CompressionType::LZFSE || -      m_compression_type == CompressionType::LZ4) { +      m_compression_type == CompressionType::LZ4 ||  +      m_compression_type == CompressionType::LZMA) {      compression_algorithm compression_type;      if (m_compression_type == CompressionType::LZFSE)        compression_type = COMPRESSION_LZFSE; @@ -620,16 +561,33 @@ bool GDBRemoteCommunication::DecompressPacket() {      else if (m_compression_type == CompressionType::LZMA)        compression_type = COMPRESSION_LZMA; -    // If we have the expected size of the decompressed payload, we can -    // allocate the right-sized buffer and do it.  If we don't have that -    // information, we'll need to try decoding into a big buffer and if the -    // buffer wasn't big enough, increase it and try again. +    if (m_decompression_scratch_type != m_compression_type) { +      if (m_decompression_scratch) { +        free (m_decompression_scratch); +        m_decompression_scratch = nullptr; +      } +      size_t scratchbuf_size = 0; +      if (m_compression_type == CompressionType::LZFSE) +        scratchbuf_size = compression_decode_scratch_buffer_size (COMPRESSION_LZFSE); +      else if (m_compression_type == CompressionType::LZ4) +        scratchbuf_size = compression_decode_scratch_buffer_size (COMPRESSION_LZ4_RAW); +      else if (m_compression_type == CompressionType::ZlibDeflate) +        scratchbuf_size = compression_decode_scratch_buffer_size (COMPRESSION_ZLIB); +      else if (m_compression_type == CompressionType::LZMA) +        scratchbuf_size = compression_decode_scratch_buffer_size (COMPRESSION_LZMA); +      else if (m_compression_type == CompressionType::LZFSE) +        scratchbuf_size = compression_decode_scratch_buffer_size (COMPRESSION_LZFSE); +      if (scratchbuf_size > 0) { +        m_decompression_scratch = (void*) malloc (scratchbuf_size); +        m_decompression_scratch_type = m_compression_type; +      } +    }      if (decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr) {        decompressed_bytes = compression_decode_buffer( -          decompressed_buffer, decompressed_bufsize + 10, -          (uint8_t *)unescaped_content.data(), unescaped_content.size(), NULL, -          compression_type); +          decompressed_buffer, decompressed_bufsize, +          (uint8_t *)unescaped_content.data(), unescaped_content.size(),  +          m_decompression_scratch, compression_type);      }    }  #endif @@ -721,7 +679,7 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,      // Size of packet before it is decompressed, for logging purposes      size_t original_packet_size = m_bytes.size();      if (CompressionIsEnabled()) { -      if (DecompressPacket() == false) { +      if (!DecompressPacket()) {          packet.Clear();          return GDBRemoteCommunication::PacketType::Standard;        } @@ -860,7 +818,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,          }        } -      m_history.AddPacket(m_bytes, total_length, History::ePacketTypeRecv, +      m_history.AddPacket(m_bytes, total_length, +                          GDBRemoteCommunicationHistory::ePacketTypeRecv,                            total_length);        // Clear packet_str in case there is some existing data in it. @@ -997,7 +956,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(    // debugserver to use and use it if we do.    const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");    if (env_debugserver_path) { -    debugserver_file_spec.SetFile(env_debugserver_path, false, +    debugserver_file_spec.SetFile(env_debugserver_path,                                    FileSpec::Style::native);      if (log)        log->Printf("GDBRemoteCommunication::%s() gdb-remote stub exe path set " @@ -1005,13 +964,14 @@ Status GDBRemoteCommunication::StartDebugserverProcess(                    __FUNCTION__, env_debugserver_path);    } else      debugserver_file_spec = g_debugserver_file_spec; -  bool debugserver_exists = debugserver_file_spec.Exists(); +  bool debugserver_exists = +      FileSystem::Instance().Exists(debugserver_file_spec);    if (!debugserver_exists) {      // The debugserver binary is in the LLDB.framework/Resources directory.      debugserver_file_spec = HostInfo::GetSupportExeDir();      if (debugserver_file_spec) {        debugserver_file_spec.AppendPathComponent(DEBUGSERVER_BASENAME); -      debugserver_exists = debugserver_file_spec.Exists(); +      debugserver_exists = FileSystem::Instance().Exists(debugserver_file_spec);        if (debugserver_exists) {          if (log)            log->Printf( @@ -1074,7 +1034,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(        debugserver_args.AppendArgument(llvm::StringRef("--setsid"));      } -    llvm::SmallString<PATH_MAX> named_pipe_path; +    llvm::SmallString<128> named_pipe_path;      // socket_pipe is used by debug server to communicate back either      // TCP port or domain socket name which it listens on.      // The second purpose of the pipe to serve as a synchronization point - @@ -1114,9 +1074,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess(                          __FUNCTION__, error.AsCString());            return error;          } -        int write_fd = socket_pipe.GetWriteFileDescriptor(); +        pipe_t write = socket_pipe.GetWritePipe();          debugserver_args.AppendArgument(llvm::StringRef("--pipe")); -        debugserver_args.AppendArgument(llvm::to_string(write_fd)); +        debugserver_args.AppendArgument(llvm::to_string(write));          launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor());  #endif        } else { @@ -1304,6 +1264,42 @@ Status GDBRemoteCommunication::StartDebugserverProcess(  void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); } +void GDBRemoteCommunication::SetHistoryStream(llvm::raw_ostream *strm) { +  m_history.SetStream(strm); +}; + +llvm::Error +GDBRemoteCommunication::ConnectLocally(GDBRemoteCommunication &client, +                                       GDBRemoteCommunication &server) { +  const bool child_processes_inherit = false; +  const int backlog = 5; +  TCPSocket listen_socket(true, child_processes_inherit); +  if (llvm::Error error = +          listen_socket.Listen("127.0.0.1:0", backlog).ToError()) +    return error; + +  Socket *accept_socket; +  std::future<Status> accept_status = std::async( +      std::launch::async, [&] { return listen_socket.Accept(accept_socket); }); + +  llvm::SmallString<32> remote_addr; +  llvm::raw_svector_ostream(remote_addr) +      << "connect://localhost:" << listen_socket.GetLocalPortNumber(); + +  std::unique_ptr<ConnectionFileDescriptor> conn_up( +      new ConnectionFileDescriptor()); +  if (conn_up->Connect(remote_addr, nullptr) != lldb::eConnectionStatusSuccess) +    return llvm::make_error<llvm::StringError>("Unable to connect", +                                               llvm::inconvertibleErrorCode()); + +  client.SetConnection(conn_up.release()); +  if (llvm::Error error = accept_status.get().ToError()) +    return error; + +  server.SetConnection(new ConnectionFileDescriptor(accept_socket)); +  return llvm::Error::success(); +} +  GDBRemoteCommunication::ScopedTimeout::ScopedTimeout(      GDBRemoteCommunication &gdb_comm, std::chrono::seconds timeout)    : m_gdb_comm(gdb_comm), m_timeout_modified(false) { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index 67796e4c61ef2..369eb25b1dfac 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -10,24 +10,21 @@  #ifndef liblldb_GDBRemoteCommunication_h_  #define liblldb_GDBRemoteCommunication_h_ -// C Includes -// C++ Includes +#include "GDBRemoteCommunicationHistory.h" +  #include <condition_variable>  #include <mutex>  #include <queue>  #include <string>  #include <vector> -// Other libraries and framework includes -// Project includes  #include "lldb/Core/Communication.h" -#include "lldb/Core/Listener.h"  #include "lldb/Host/HostThread.h" -#include "lldb/Host/Predicate.h"  #include "lldb/Utility/Args.h" -#include "lldb/lldb-public.h" - +#include "lldb/Utility/Listener.h" +#include "lldb/Utility/Predicate.h"  #include "lldb/Utility/StringExtractorGDBRemote.h" +#include "lldb/lldb-public.h"  namespace lldb_private {  namespace process_gdb_remote { @@ -140,86 +137,16 @@ public:                           // fork/exec to avoid having to connect/accept    void DumpHistory(Stream &strm); +  void SetHistoryStream(llvm::raw_ostream *strm); -protected: -  class History { -  public: -    enum PacketType { -      ePacketTypeInvalid = 0, -      ePacketTypeSend, -      ePacketTypeRecv -    }; - -    struct Entry { -      Entry() -          : packet(), type(ePacketTypeInvalid), bytes_transmitted(0), -            packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {} - -      void Clear() { -        packet.clear(); -        type = ePacketTypeInvalid; -        bytes_transmitted = 0; -        packet_idx = 0; -        tid = LLDB_INVALID_THREAD_ID; -      } -      std::string packet; -      PacketType type; -      uint32_t bytes_transmitted; -      uint32_t packet_idx; -      lldb::tid_t tid; -    }; - -    History(uint32_t size); - -    ~History(); - -    // For single char packets for ack, nack and /x03 -    void AddPacket(char packet_char, PacketType type, -                   uint32_t bytes_transmitted); - -    void AddPacket(const std::string &src, uint32_t src_len, PacketType type, -                   uint32_t bytes_transmitted); - -    void Dump(Stream &strm) const; - -    void Dump(Log *log) const; - -    bool DidDumpToLog() const { return m_dumped_to_log; } - -  protected: -    uint32_t GetFirstSavedPacketIndex() const { -      if (m_total_packet_count < m_packets.size()) -        return 0; -      else -        return m_curr_idx + 1; -    } - -    uint32_t GetNumPacketsInHistory() const { -      if (m_total_packet_count < m_packets.size()) -        return m_total_packet_count; -      else -        return (uint32_t)m_packets.size(); -    } - -    uint32_t GetNextIndex() { -      ++m_total_packet_count; -      const uint32_t idx = m_curr_idx; -      m_curr_idx = NormalizeIndex(idx + 1); -      return idx; -    } - -    uint32_t NormalizeIndex(uint32_t i) const { return i % m_packets.size(); } - -    std::vector<Entry> m_packets; -    uint32_t m_curr_idx; -    uint32_t m_total_packet_count; -    mutable bool m_dumped_to_log; -  }; +  static llvm::Error ConnectLocally(GDBRemoteCommunication &client, +                                    GDBRemoteCommunication &server); +protected:    std::chrono::seconds m_packet_timeout;    uint32_t m_echo_number;    LazyBool m_supports_qEcho; -  History m_history; +  GDBRemoteCommunicationHistory m_history;    bool m_send_acks;    bool m_is_platform; // Set to true if this class represents a platform,                        // false if this class represents a debug session for @@ -228,6 +155,8 @@ protected:    CompressionType m_compression_type;    PacketResult SendPacketNoLock(llvm::StringRef payload); +  PacketResult SendRawPacketNoLock(llvm::StringRef payload, +                                   bool skip_ack = false);    PacketResult ReadPacket(StringExtractorGDBRemote &response,                            Timeout<std::micro> timeout, bool sync_on_timeout); @@ -289,6 +218,9 @@ private:    HostThread m_listen_thread;    std::string m_listen_url; +  CompressionType m_decompression_scratch_type; +  void *m_decompression_scratch; +    DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunication);  }; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index c8b59d5d236b9..1e12ea6b2d566 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -9,17 +9,13 @@  #include "GDBRemoteCommunicationClient.h" -// C Includes  #include <math.h>  #include <sys/stat.h> -// C++ Includes  #include <numeric>  #include <sstream> -// Other libraries and framework includes  #include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/State.h"  #include "lldb/Host/HostInfo.h"  #include "lldb/Host/XML.h"  #include "lldb/Symbol/Symbol.h" @@ -31,9 +27,9 @@  #include "lldb/Utility/JSON.h"  #include "lldb/Utility/LLDBAssert.h"  #include "lldb/Utility/Log.h" +#include "lldb/Utility/State.h"  #include "lldb/Utility/StreamString.h" -// Project includes  #include "ProcessGDBRemote.h"  #include "ProcessGDBRemoteLog.h"  #include "lldb/Host/Config.h" @@ -41,7 +37,8 @@  #include "llvm/ADT/StringSwitch.h" -#if defined(HAVE_LIBCOMPRESSION) +#if defined(__APPLE__) +#define HAVE_LIBCOMPRESSION  #include <compression.h>  #endif @@ -256,10 +253,7 @@ bool GDBRemoteCommunicationClient::GetVAttachOrWaitSupported() {          m_attach_or_wait_reply = eLazyBoolYes;      }    } -  if (m_attach_or_wait_reply == eLazyBoolYes) -    return true; -  else -    return false; +  return m_attach_or_wait_reply == eLazyBoolYes;  }  bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() { @@ -273,14 +267,11 @@ bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() {          m_prepare_for_reg_writing_reply = eLazyBoolYes;      }    } -  if (m_prepare_for_reg_writing_reply == eLazyBoolYes) -    return true; -  else -    return false; +  return m_prepare_for_reg_writing_reply == eLazyBoolYes;  }  void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) { -  if (did_exec == false) { +  if (!did_exec) {      // Hard reset everything, this is when we first connect to a GDB server      m_supports_not_sending_acks = eLazyBoolCalculate;      m_supports_thread_suffix = eLazyBoolCalculate; @@ -749,7 +740,7 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {        bool sequence_mutex_unavailable;        size_t size;        size = GetCurrentThreadIDs(thread_ids, sequence_mutex_unavailable); -      if (size && sequence_mutex_unavailable == false) { +      if (size && !sequence_mutex_unavailable) {          m_curr_pid = thread_ids.front();          m_curr_pid_is_valid = eLazyBoolYes;          return m_curr_pid; @@ -843,8 +834,8 @@ int GDBRemoteCommunicationClient::SendEnvironmentPacket(    if (name_equal_value && name_equal_value[0]) {      StreamString packet;      bool send_hex_encoding = false; -    for (const char *p = name_equal_value; -         *p != '\0' && send_hex_encoding == false; ++p) { +    for (const char *p = name_equal_value; *p != '\0' && !send_hex_encoding; +         ++p) {        if (isprint(*p)) {          switch (*p) {          case '$': @@ -1134,6 +1125,9 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {    Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS));    if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) { +    // host info computation can require DNS traffic and shelling out to external processes. +    // Increase the timeout to account for that. +    ScopedTimeout timeout(*this, seconds(10));      m_qHostInfo_is_valid = eLazyBoolNo;      StringExtractorGDBRemote response;      if (SendPacketAndWaitForResponse("qHostInfo", response, false) == @@ -1686,12 +1680,17 @@ Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) {        m_supports_watchpoint_support_info = eLazyBoolYes;        llvm::StringRef name;        llvm::StringRef value; +      bool found_num_field = false;        while (response.GetNameColonValue(name, value)) {          if (name.equals("num")) {            value.getAsInteger(0, m_num_supported_hardware_watchpoints);            num = m_num_supported_hardware_watchpoints; +          found_num_field = true;          }        } +      if (!found_num_field) { +        m_supports_watchpoint_support_info = eLazyBoolNo; +      }      } else {        m_supports_watchpoint_support_info = eLazyBoolNo;      } @@ -1724,12 +1723,10 @@ GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction(      // On targets like MIPS and ppc64le, watchpoint exceptions are always      // generated before the instruction is executed. The connected target may      // not support qHostInfo or qWatchpointSupportInfo packets. -    if (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || -        atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el || -        atype == llvm::Triple::ppc64le) -      after = false; -    else -      after = true; +    after = +        !(atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || +          atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el || +          atype == llvm::Triple::ppc64le);    } else {      // For MIPS and ppc64le, set m_watchpoints_trigger_after_instruction to      // eLazyBoolNo if it is not calculated before. @@ -1815,7 +1812,7 @@ bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) {        return false;      std::string cwd;      response.GetHexByteString(cwd); -    working_dir.SetFile(cwd, false, GetHostArchitecture().GetTriple()); +    working_dir.SetFile(cwd, GetHostArchitecture().GetTriple());      return !cwd.empty();    }    return false; @@ -1925,8 +1922,7 @@ bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse(          // characters in a process name          std::string name;          extractor.GetHexByteString(name); -        process_info.GetExecutableFile().SetFile(name, false, -                                                 FileSpec::Style::native); +        process_info.GetExecutableFile().SetFile(name, FileSpec::Style::native);        } else if (name.equals("cputype")) {          value.getAsInteger(0, cpu);        } else if (name.equals("cpusubtype")) { @@ -3559,7 +3555,7 @@ bool GDBRemoteCommunicationClient::GetModuleInfo(        StringExtractor extractor(value);        std::string path;        extractor.GetHexByteString(path); -      module_spec.GetFileSpec() = FileSpec(path, false, arch_spec.GetTriple()); +      module_spec.GetFileSpec() = FileSpec(path, arch_spec.GetTriple());      }    } @@ -3595,8 +3591,7 @@ ParseModuleSpec(StructuredData::Dictionary *dict) {    if (!dict->GetValueForKeyAsString("file_path", string))      return llvm::None; -  result.GetFileSpec() = -      FileSpec(string, false, result.GetArchitecture().GetTriple()); +  result.GetFileSpec() = FileSpec(string, result.GetArchitecture().GetTriple());    return result;  } @@ -3774,7 +3769,7 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(    // Is this the initial qSymbol:: packet?    bool first_qsymbol_query = true; -  if (m_supports_qSymbol && m_qSymbol_requests_done == false) { +  if (m_supports_qSymbol && !m_qSymbol_requests_done) {      Lock lock(*this, false);      if (lock) {        StreamString packet; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index cf1d249768d7a..37d53ab425f59 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -12,8 +12,6 @@  #include "GDBRemoteClientBase.h" -// C Includes -// C++ Includes  #include <chrono>  #include <map>  #include <mutex> diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp new file mode 100644 index 0000000000000..69b13f2a3acb6 --- /dev/null +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp @@ -0,0 +1,143 @@ +//===-- GDBRemoteCommunicationHistory.cpp -----------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "GDBRemoteCommunicationHistory.h" + +// Other libraries and framework includes +#include "lldb/Core/StreamFile.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Log.h" + +using namespace llvm; +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_gdb_remote; + +void GDBRemoteCommunicationHistory::Entry::Serialize(raw_ostream &strm) const { +  yaml::Output yout(strm); +  yout << const_cast<GDBRemoteCommunicationHistory::Entry &>(*this); +  strm.flush(); +} + +GDBRemoteCommunicationHistory::GDBRemoteCommunicationHistory(uint32_t size) +    : m_packets(), m_curr_idx(0), m_total_packet_count(0), +      m_dumped_to_log(false) { +  if (size) +    m_packets.resize(size); +} + +GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() {} + +void GDBRemoteCommunicationHistory::AddPacket(char packet_char, PacketType type, +                                              uint32_t bytes_transmitted) { +  const size_t size = m_packets.size(); +  if (size == 0) +    return; + +  const uint32_t idx = GetNextIndex(); +  m_packets[idx].packet.data.assign(1, packet_char); +  m_packets[idx].type = type; +  m_packets[idx].bytes_transmitted = bytes_transmitted; +  m_packets[idx].packet_idx = m_total_packet_count; +  m_packets[idx].tid = llvm::get_threadid(); +  if (m_stream && type == ePacketTypeRecv) +    m_packets[idx].Serialize(*m_stream); +} + +void GDBRemoteCommunicationHistory::AddPacket(const std::string &src, +                                              uint32_t src_len, PacketType type, +                                              uint32_t bytes_transmitted) { +  const size_t size = m_packets.size(); +  if (size == 0) +    return; + +  const uint32_t idx = GetNextIndex(); +  m_packets[idx].packet.data.assign(src, 0, src_len); +  m_packets[idx].type = type; +  m_packets[idx].bytes_transmitted = bytes_transmitted; +  m_packets[idx].packet_idx = m_total_packet_count; +  m_packets[idx].tid = llvm::get_threadid(); +  if (m_stream && type == ePacketTypeRecv) +    m_packets[idx].Serialize(*m_stream); +} + +void GDBRemoteCommunicationHistory::Dump(Stream &strm) const { +  const uint32_t size = GetNumPacketsInHistory(); +  const uint32_t first_idx = GetFirstSavedPacketIndex(); +  const uint32_t stop_idx = m_curr_idx + size; +  for (uint32_t i = first_idx; i < stop_idx; ++i) { +    const uint32_t idx = NormalizeIndex(i); +    const Entry &entry = m_packets[idx]; +    if (entry.type == ePacketTypeInvalid || entry.packet.data.empty()) +      break; +    strm.Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n", +                entry.packet_idx, entry.tid, entry.bytes_transmitted, +                (entry.type == ePacketTypeSend) ? "send" : "read", +                entry.packet.data.c_str()); +  } +} + +void GDBRemoteCommunicationHistory::Dump(Log *log) const { +  if (!log || m_dumped_to_log) +    return; + +  m_dumped_to_log = true; +  const uint32_t size = GetNumPacketsInHistory(); +  const uint32_t first_idx = GetFirstSavedPacketIndex(); +  const uint32_t stop_idx = m_curr_idx + size; +  for (uint32_t i = first_idx; i < stop_idx; ++i) { +    const uint32_t idx = NormalizeIndex(i); +    const Entry &entry = m_packets[idx]; +    if (entry.type == ePacketTypeInvalid || entry.packet.data.empty()) +      break; +    log->Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s", +                entry.packet_idx, entry.tid, entry.bytes_transmitted, +                (entry.type == ePacketTypeSend) ? "send" : "read", +                entry.packet.data.c_str()); +  } +} + +void yaml::ScalarEnumerationTraits<GDBRemoteCommunicationHistory::PacketType>:: +    enumeration(IO &io, GDBRemoteCommunicationHistory::PacketType &value) { +  io.enumCase(value, "Invalid", +              GDBRemoteCommunicationHistory::ePacketTypeInvalid); +  io.enumCase(value, "Send", GDBRemoteCommunicationHistory::ePacketTypeSend); +  io.enumCase(value, "Recv", GDBRemoteCommunicationHistory::ePacketTypeRecv); +} + +void yaml::ScalarTraits<GDBRemoteCommunicationHistory::Entry::BinaryData>:: +    output(const GDBRemoteCommunicationHistory::Entry::BinaryData &Val, void *, +           raw_ostream &Out) { +  Out << toHex(Val.data); +} + +StringRef +yaml::ScalarTraits<GDBRemoteCommunicationHistory::Entry::BinaryData>::input( +    StringRef Scalar, void *, +    GDBRemoteCommunicationHistory::Entry::BinaryData &Val) { +  Val.data = fromHex(Scalar); +  return {}; +} + +void yaml::MappingTraits<GDBRemoteCommunicationHistory::Entry>::mapping( +    IO &io, GDBRemoteCommunicationHistory::Entry &Entry) { +  io.mapRequired("packet", Entry.packet); +  io.mapRequired("type", Entry.type); +  io.mapRequired("bytes", Entry.bytes_transmitted); +  io.mapRequired("index", Entry.packet_idx); +  io.mapRequired("tid", Entry.tid); +} + +StringRef yaml::MappingTraits<GDBRemoteCommunicationHistory::Entry>::validate( +    IO &io, GDBRemoteCommunicationHistory::Entry &Entry) { +  if (Entry.bytes_transmitted != Entry.packet.data.size()) +    return "BinaryData size doesn't match bytes transmitted"; + +  return {}; +} diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h new file mode 100644 index 0000000000000..d0ca6a0235c9b --- /dev/null +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h @@ -0,0 +1,156 @@ +//===-- GDBRemoteCommunicationHistory.h--------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_GDBRemoteCommunicationHistory_h_ +#define liblldb_GDBRemoteCommunicationHistory_h_ + +#include <string> +#include <vector> + +#include "lldb/lldb-public.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" + +namespace lldb_private { +namespace process_gdb_remote { + +/// The history keeps a circular buffer of GDB remote packets. The history is +/// used for logging and replaying GDB remote packets. +class GDBRemoteCommunicationHistory { +public: +  friend llvm::yaml::MappingTraits<GDBRemoteCommunicationHistory>; + +  enum PacketType { ePacketTypeInvalid = 0, ePacketTypeSend, ePacketTypeRecv }; + +  /// Entry in the ring buffer containing the packet data, its type, size and +  /// index. Entries can be serialized to file. +  struct Entry { +    Entry() +        : packet(), type(ePacketTypeInvalid), bytes_transmitted(0), +          packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {} + +    void Clear() { +      packet.data.clear(); +      type = ePacketTypeInvalid; +      bytes_transmitted = 0; +      packet_idx = 0; +      tid = LLDB_INVALID_THREAD_ID; +    } + +    struct BinaryData { +      std::string data; +    }; + +    void Serialize(llvm::raw_ostream &strm) const; + +    BinaryData packet; +    PacketType type; +    uint32_t bytes_transmitted; +    uint32_t packet_idx; +    lldb::tid_t tid; +  }; + +  GDBRemoteCommunicationHistory(uint32_t size = 0); + +  ~GDBRemoteCommunicationHistory(); + +  // For single char packets for ack, nack and /x03 +  void AddPacket(char packet_char, PacketType type, uint32_t bytes_transmitted); + +  void AddPacket(const std::string &src, uint32_t src_len, PacketType type, +                 uint32_t bytes_transmitted); + +  void Dump(Stream &strm) const; +  void Dump(Log *log) const; +  bool DidDumpToLog() const { return m_dumped_to_log; } + +  void SetStream(llvm::raw_ostream *strm) { m_stream = strm; } + +private: +  uint32_t GetFirstSavedPacketIndex() const { +    if (m_total_packet_count < m_packets.size()) +      return 0; +    else +      return m_curr_idx + 1; +  } + +  uint32_t GetNumPacketsInHistory() const { +    if (m_total_packet_count < m_packets.size()) +      return m_total_packet_count; +    else +      return (uint32_t)m_packets.size(); +  } + +  uint32_t GetNextIndex() { +    ++m_total_packet_count; +    const uint32_t idx = m_curr_idx; +    m_curr_idx = NormalizeIndex(idx + 1); +    return idx; +  } + +  uint32_t NormalizeIndex(uint32_t i) const { +    return m_packets.empty() ? 0 : i % m_packets.size(); +  } + +  std::vector<Entry> m_packets; +  uint32_t m_curr_idx; +  uint32_t m_total_packet_count; +  mutable bool m_dumped_to_log; +  llvm::raw_ostream *m_stream = nullptr; +}; + +} // namespace process_gdb_remote +} // namespace lldb_private + +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR( +    lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry) + +namespace llvm { +namespace yaml { + +template <> +struct ScalarEnumerationTraits<lldb_private::process_gdb_remote:: +                                   GDBRemoteCommunicationHistory::PacketType> { +  static void enumeration(IO &io, +                          lldb_private::process_gdb_remote:: +                              GDBRemoteCommunicationHistory::PacketType &value); +}; + +template <> +struct ScalarTraits<lldb_private::process_gdb_remote:: +                        GDBRemoteCommunicationHistory::Entry::BinaryData> { +  static void output(const lldb_private::process_gdb_remote:: +                         GDBRemoteCommunicationHistory::Entry::BinaryData &, +                     void *, raw_ostream &); + +  static StringRef +  input(StringRef, void *, +        lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry:: +            BinaryData &); + +  static QuotingType mustQuote(StringRef S) { return QuotingType::None; } +}; + +template <> +struct MappingTraits< +    lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry> { +  static void +  mapping(IO &io, +          lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry +              &Entry); + +  static StringRef validate( +      IO &io, +      lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry &); +}; + +} // namespace yaml +} // namespace llvm + +#endif // liblldb_GDBRemoteCommunicationHistory_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp new file mode 100644 index 0000000000000..6a78eb20992e0 --- /dev/null +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp @@ -0,0 +1,204 @@ +//===-- GDBRemoteCommunicationReplayServer.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 "GDBRemoteCommunicationReplayServer.h" +#include "ProcessGDBRemoteLog.h" + +// C Includes +// C++ Includes +#include <cstring> + +// Project includes +#include "lldb/Host/ThreadLauncher.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Event.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/StringExtractorGDBRemote.h" + +using namespace llvm; +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_gdb_remote; + +GDBRemoteCommunicationReplayServer::GDBRemoteCommunicationReplayServer() +    : GDBRemoteCommunication("gdb-remote.server", +                             "gdb-remote.server.rx_packet"), +      m_async_broadcaster(nullptr, "lldb.gdb-remote.server.async-broadcaster"), +      m_async_listener_sp( +          Listener::MakeListener("lldb.gdb-remote.server.async-listener")), +      m_async_thread_state_mutex(), m_skip_acks(false) { +  m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, +                                   "async thread continue"); +  m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, +                                   "async thread should exit"); + +  const uint32_t async_event_mask = +      eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; +  m_async_listener_sp->StartListeningForEvents(&m_async_broadcaster, +                                               async_event_mask); +} + +GDBRemoteCommunicationReplayServer::~GDBRemoteCommunicationReplayServer() { +  StopAsyncThread(); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( +    Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) { +  StringExtractorGDBRemote packet; +  PacketResult packet_result = WaitForPacketNoLock(packet, timeout, false); + +  if (packet_result != PacketResult::Success) { +    if (!IsConnected()) { +      error.SetErrorString("lost connection"); +      quit = true; +    } else { +      error.SetErrorString("timeout"); +    } +    return packet_result; +  } + +  m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); + +  if (m_skip_acks) { +    const StringExtractorGDBRemote::ServerPacketType packet_type = +        packet.GetServerPacketType(); +    switch (packet_type) { +    case StringExtractorGDBRemote::eServerPacketType_nack: +    case StringExtractorGDBRemote::eServerPacketType_ack: +      return PacketResult::Success; +    default: +      break; +    } +  } else if (packet.GetStringRef() == "QStartNoAckMode") { +    m_skip_acks = true; +    m_send_acks = false; +  } + +  while (!m_packet_history.empty()) { +    // Pop last packet from the history. +    GDBRemoteCommunicationHistory::Entry entry = m_packet_history.back(); +    m_packet_history.pop_back(); + +    // We only care about what we received from the server. Skip everything +    // the client sent. +    if (entry.type != GDBRemoteCommunicationHistory::ePacketTypeRecv) +      continue; + +    return SendRawPacketNoLock(entry.packet.data, true); +  } + +  quit = true; + +  return packet_result; +} + +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR( +    std::vector< +        lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry>) + +llvm::Error +GDBRemoteCommunicationReplayServer::LoadReplayHistory(const FileSpec &path) { +  auto error_or_file = MemoryBuffer::getFile(path.GetPath()); +  if (auto err = error_or_file.getError()) +    return errorCodeToError(err); + +  yaml::Input yin((*error_or_file)->getBuffer()); +  yin >> m_packet_history; + +  if (auto err = yin.error()) +    return errorCodeToError(err); + +  // We want to manipulate the vector like a stack so we need to reverse the +  // order of the packets to have the oldest on at the back. +  std::reverse(m_packet_history.begin(), m_packet_history.end()); + +  return Error::success(); +} + +bool GDBRemoteCommunicationReplayServer::StartAsyncThread() { +  std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); +  if (!m_async_thread.IsJoinable()) { +    // Create a thread that watches our internal state and controls which +    // events make it to clients (into the DCProcess event queue). +    m_async_thread = ThreadLauncher::LaunchThread( +        "<lldb.gdb-remote.server.async>", +        GDBRemoteCommunicationReplayServer::AsyncThread, this, nullptr); +  } + +  // Wait for handshake. +  m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); + +  return m_async_thread.IsJoinable(); +} + +void GDBRemoteCommunicationReplayServer::StopAsyncThread() { +  std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); + +  if (!m_async_thread.IsJoinable()) +    return; + +  // Request thread to stop. +  m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); + +  // Disconnect client. +  Disconnect(); + +  // Stop the thread. +  m_async_thread.Join(nullptr); +  m_async_thread.Reset(); +} + +void GDBRemoteCommunicationReplayServer::ReceivePacket( +    GDBRemoteCommunicationReplayServer &server, bool &done) { +  Status error; +  bool interrupt; +  auto packet_result = server.GetPacketAndSendResponse(std::chrono::seconds(1), +                                                       error, interrupt, done); +  if (packet_result != GDBRemoteCommunication::PacketResult::Success && +      packet_result != +          GDBRemoteCommunication::PacketResult::ErrorReplyTimeout) { +    done = true; +  } else { +    server.m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); +  } +} + +thread_result_t GDBRemoteCommunicationReplayServer::AsyncThread(void *arg) { +  GDBRemoteCommunicationReplayServer *server = +      (GDBRemoteCommunicationReplayServer *)arg; + +  EventSP event_sp; +  bool done = false; + +  while (true) { +    if (server->m_async_listener_sp->GetEvent(event_sp, llvm::None)) { +      const uint32_t event_type = event_sp->GetType(); +      if (event_sp->BroadcasterIs(&server->m_async_broadcaster)) { +        switch (event_type) { +        case eBroadcastBitAsyncContinue: +          ReceivePacket(*server, done); +          if (done) +            return {}; +          break; +        case eBroadcastBitAsyncThreadShouldExit: +        default: +          return {}; +        } +      } +    } +  } + +  return {}; +} diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h new file mode 100644 index 0000000000000..5b840c8459b71 --- /dev/null +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h @@ -0,0 +1,83 @@ +//===-- GDBRemoteCommunicationReplayServer.h --------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_GDBRemoteCommunicationReplayServer_h_ +#define liblldb_GDBRemoteCommunicationReplayServer_h_ + +// Other libraries and framework includes +#include "GDBRemoteCommunication.h" +#include "GDBRemoteCommunicationHistory.h" + +// Project includes +#include "lldb/Host/HostThread.h" +#include "lldb/Utility/Broadcaster.h" +#include "lldb/lldb-private-forward.h" +#include "llvm/Support/Error.h" + +// C Includes +// C++ Includes +#include <functional> +#include <map> +#include <thread> + +class StringExtractorGDBRemote; + +namespace lldb_private { +namespace process_gdb_remote { + +class ProcessGDBRemote; + +/// Dummy GDB server that replays packets from the GDB Remote Communication +/// history. This is used to replay GDB packets. +class GDBRemoteCommunicationReplayServer : public GDBRemoteCommunication { +public: +  GDBRemoteCommunicationReplayServer(); + +  ~GDBRemoteCommunicationReplayServer() override; + +  PacketResult GetPacketAndSendResponse(Timeout<std::micro> timeout, +                                        Status &error, bool &interrupt, +                                        bool &quit); + +  bool HandshakeWithClient() { return GetAck() == PacketResult::Success; } + +  llvm::Error LoadReplayHistory(const FileSpec &path); + +  bool StartAsyncThread(); +  void StopAsyncThread(); + +protected: +  enum { +    eBroadcastBitAsyncContinue = (1 << 0), +    eBroadcastBitAsyncThreadShouldExit = (1 << 1), +  }; + +  static void ReceivePacket(GDBRemoteCommunicationReplayServer &server, +                            bool &done); +  static lldb::thread_result_t AsyncThread(void *arg); + +  /// Replay history with the oldest packet at the end. +  std::vector<GDBRemoteCommunicationHistory::Entry> m_packet_history; + +  /// Server thread. +  Broadcaster m_async_broadcaster; +  lldb::ListenerSP m_async_listener_sp; +  HostThread m_async_thread; +  std::recursive_mutex m_async_thread_state_mutex; + +  bool m_skip_acks; + +private: +  DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationReplayServer); +}; + +} // namespace process_gdb_remote +} // namespace lldb_private + +#endif // liblldb_GDBRemoteCommunicationReplayServer_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 4fc1fc7a1964e..026f78117a0c4 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -13,11 +13,8 @@  #include "GDBRemoteCommunicationServer.h" -// C Includes -// C++ Includes  #include <cstring> -// Project includes  #include "ProcessGDBRemoteLog.h"  #include "lldb/Utility/StreamString.h"  #include "lldb/Utility/StringExtractorGDBRemote.h" diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 880caacd64149..082fb0d854243 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -10,13 +10,9 @@  #ifndef liblldb_GDBRemoteCommunicationServer_h_  #define liblldb_GDBRemoteCommunicationServer_h_ -// C Includes -// C++ Includes  #include <functional>  #include <map> -// Other libraries and framework includes -// Project includes  #include "GDBRemoteCommunication.h"  #include "lldb/lldb-private-forward.h" diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index c5b478378faa4..f11ef4f1bbf84 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -11,23 +11,21 @@  #include <errno.h> -// C Includes  #ifdef __APPLE__  #include <TargetConditionals.h>  #endif -// C++ Includes  #include <chrono>  #include <cstring> -// Other libraries and framework includes  #include "lldb/Core/ModuleSpec.h"  #include "lldb/Host/Config.h"  #include "lldb/Host/File.h"  #include "lldb/Host/FileSystem.h"  #include "lldb/Host/Host.h"  #include "lldb/Host/HostInfo.h" +#include "lldb/Host/SafeMachO.h"  #include "lldb/Interpreter/OptionArgParser.h"  #include "lldb/Symbol/ObjectFile.h"  #include "lldb/Target/FileAction.h" @@ -36,12 +34,10 @@  #include "lldb/Utility/Endian.h"  #include "lldb/Utility/JSON.h"  #include "lldb/Utility/Log.h" -#include "lldb/Utility/SafeMachO.h"  #include "lldb/Utility/StreamGDBRemote.h"  #include "lldb/Utility/StreamString.h"  #include "llvm/ADT/Triple.h" -// Project includes  #include "ProcessGDBRemoteLog.h"  #include "lldb/Utility/StringExtractorGDBRemote.h" @@ -353,7 +349,7 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(          std::string file;          extractor.GetHexByteString(file);          match_info.GetProcessInfo().GetExecutableFile().SetFile( -            file, false, FileSpec::Style::native); +            file, FileSpec::Style::native);        } else if (key.equals("name_match")) {          NameMatch name_match = llvm::StringSwitch<NameMatch>(value)                                     .Case("equals", NameMatch::Equals) @@ -520,7 +516,8 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Open(        if (packet.GetChar() == ',') {          mode_t mode = packet.GetHexMaxU32(false, 0600);          Status error; -        const FileSpec path_spec{path, true}; +        FileSpec path_spec(path); +        FileSystem::Instance().Resolve(path_spec);          int fd = ::open(path_spec.GetCString(), flags, mode);          const int save_errno = fd == -1 ? errno : 0;          StreamString response; @@ -659,12 +656,14 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Mode(    std::string path;    packet.GetHexByteString(path);    if (!path.empty()) { -    Status error; -    const uint32_t mode = File::GetPermissions(FileSpec{path, true}, error); +    FileSpec file_spec(path); +    FileSystem::Instance().Resolve(file_spec); +    std::error_code ec; +    const uint32_t mode = FileSystem::Instance().GetPermissions(file_spec, ec);      StreamString response;      response.Printf("F%u", mode); -    if (mode == 0 || error.Fail()) -      response.Printf(",%i", (int)error.GetError()); +    if (mode == 0 || ec) +      response.Printf(",%i", (int)Status(ec).GetError());      return SendPacketNoLock(response.GetString());    }    return SendErrorResponse(23); @@ -698,7 +697,11 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_symlink(    packet.GetHexByteStringTerminatedBy(dst, ',');    packet.GetChar(); // Skip ',' char    packet.GetHexByteString(src); -  Status error = FileSystem::Symlink(FileSpec{src, true}, FileSpec{dst, false}); + +  FileSpec src_spec(src); +  FileSystem::Instance().Resolve(src_spec); +  Status error = FileSystem::Instance().Symlink(src_spec, FileSpec(dst)); +    StreamString response;    response.Printf("F%u,%u", error.GetError(), error.GetError());    return SendPacketNoLock(response.GetString()); @@ -731,9 +734,11 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell(          packet.GetHexByteString(working_dir);        int status, signo;        std::string output; -      Status err = Host::RunShellCommand( -          path.c_str(), FileSpec{working_dir, true}, &status, &signo, &output, -          std::chrono::seconds(10)); +      FileSpec working_spec(working_dir); +      FileSystem::Instance().Resolve(working_spec); +      Status err = +          Host::RunShellCommand(path.c_str(), working_spec, &status, &signo, +                                &output, std::chrono::seconds(10));        StreamGDBRemote response;        if (err.Fail()) {          response.PutCString("F,"); @@ -884,7 +889,7 @@ GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN(    packet.GetHexByteString(path);    const bool read = true;    const bool write = false; -  if (file_action.Open(STDIN_FILENO, FileSpec{path, false}, read, write)) { +  if (file_action.Open(STDIN_FILENO, FileSpec(path), read, write)) {      m_process_launch_info.AppendFileAction(file_action);      return SendOKResponse();    } @@ -900,7 +905,7 @@ GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT(    packet.GetHexByteString(path);    const bool read = false;    const bool write = true; -  if (file_action.Open(STDOUT_FILENO, FileSpec{path, false}, read, write)) { +  if (file_action.Open(STDOUT_FILENO, FileSpec(path), read, write)) {      m_process_launch_info.AppendFileAction(file_action);      return SendOKResponse();    } @@ -916,7 +921,7 @@ GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR(    packet.GetHexByteString(path);    const bool read = false;    const bool write = true; -  if (file_action.Open(STDERR_FILENO, FileSpec{path, false}, read, write)) { +  if (file_action.Open(STDERR_FILENO, FileSpec(path), read, write)) {      m_process_launch_info.AppendFileAction(file_action);      return SendOKResponse();    } @@ -1024,7 +1029,7 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {                if (success) {                  if (arg_idx == 0)                    m_process_launch_info.GetExecutableFile().SetFile( -                      arg, false, FileSpec::Style::native); +                      arg, FileSpec::Style::native);                  m_process_launch_info.GetArguments().AppendArgument(arg);                  if (log)                    log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"", @@ -1263,7 +1268,9 @@ FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile(  #ifdef __ANDROID__    return HostInfoAndroid::ResolveLibraryPath(module_path, arch);  #else -  return FileSpec(module_path, true); +  FileSpec file_spec(module_path); +  FileSystem::Instance().Resolve(file_spec); +  return file_spec;  #endif  } @@ -1272,7 +1279,9 @@ GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path,                                                    llvm::StringRef triple) {    ArchSpec arch(triple); -  const FileSpec req_module_path_spec(module_path, true); +  FileSpec req_module_path_spec(module_path); +  FileSystem::Instance().Resolve(req_module_path_spec); +    const FileSpec module_path_spec =        FindModuleFile(req_module_path_spec.GetPath(), arch);    const ModuleSpec module_spec(module_path_spec, arch); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h index e9ab8f1a11deb..f3825bb367917 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h @@ -10,12 +10,8 @@  #ifndef liblldb_GDBRemoteCommunicationServerCommon_h_  #define liblldb_GDBRemoteCommunicationServerCommon_h_ -// C Includes -// C++ Includes  #include <string> -// Other libraries and framework includes -// Project includes  #include "lldb/Target/Process.h"  #include "lldb/lldb-private-forward.h" diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 50392fa389562..cdb63e72f6bdb 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -14,15 +14,10 @@  #include "GDBRemoteCommunicationServerLLGS.h"  #include "lldb/Utility/StreamGDBRemote.h" -// C Includes -// C++ Includes  #include <chrono>  #include <cstring>  #include <thread> -// Other libraries and framework includes -#include "lldb/Core/RegisterValue.h" -#include "lldb/Core/State.h"  #include "lldb/Host/ConnectionFileDescriptor.h"  #include "lldb/Host/Debug.h"  #include "lldb/Host/File.h" @@ -41,12 +36,13 @@  #include "lldb/Utility/JSON.h"  #include "lldb/Utility/LLDBAssert.h"  #include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/State.h"  #include "lldb/Utility/StreamString.h"  #include "lldb/Utility/UriParser.h"  #include "llvm/ADT/Triple.h"  #include "llvm/Support/ScopedPrinter.h" -// Project includes  #include "ProcessGDBRemote.h"  #include "ProcessGDBRemoteLog.h"  #include "lldb/Utility/StringExtractorGDBRemote.h" @@ -222,8 +218,10 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {    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); +  if (should_forward_stdio) { +    if (llvm::Error Err = m_process_launch_info.SetUpPtyRedirection()) +      return Status(std::move(Err)); +  }    {      std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex); @@ -1333,7 +1331,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir(    packet.SetFilePos(::strlen("QSetWorkingDir:"));    std::string path;    packet.GetHexByteString(path); -  m_process_launch_info.SetWorkingDirectory(FileSpec{path, true}); +  m_process_launch_info.SetWorkingDirectory(FileSpec(path));    return SendOKResponse();  } @@ -3220,7 +3218,7 @@ GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path,      if (m_debugged_process_up              ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec)              .Success()) { -      if (file_spec.Exists()) +      if (FileSystem::Instance().Exists(file_spec))          return file_spec;      }    } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index 5a74d1acaa237..a085a3cc17dd1 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -10,18 +10,14 @@  #ifndef liblldb_GDBRemoteCommunicationServerLLGS_h_  #define liblldb_GDBRemoteCommunicationServerLLGS_h_ -// C Includes -// C++ Includes  #include <mutex>  #include <unordered_map> -// Other libraries and framework includes  #include "lldb/Core/Communication.h"  #include "lldb/Host/MainLoop.h"  #include "lldb/Host/common/NativeProcessProtocol.h"  #include "lldb/lldb-private-forward.h" -// Project includes  #include "GDBRemoteCommunicationServerCommon.h"  class StringExtractorGDBRemote; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 26e28a900320a..3521ddafbb166 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -11,15 +11,12 @@  #include <errno.h> -// C Includes -// C++ Includes  #include <chrono>  #include <csignal>  #include <cstring>  #include <mutex>  #include <sstream> -// Other libraries and framework includes  #include "llvm/Support/FileSystem.h"  #include "llvm/Support/Threading.h" @@ -38,7 +35,6 @@  #include "lldb/Utility/StructuredData.h"  #include "lldb/Utility/UriParser.h" -// Project includes  #include "lldb/Utility/StringExtractorGDBRemote.h"  using namespace lldb; @@ -168,9 +164,6 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(  GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(      StringExtractorGDBRemote &packet) { -#ifdef _WIN32 -  return SendErrorResponse(9); -#else    // Spawn a local debugserver as a platform so we can then attach or launch a    // process... @@ -221,10 +214,9 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(    PacketResult packet_result = SendPacketNoLock(response.GetString());    if (packet_result != PacketResult::Success) {      if (debugserver_pid != LLDB_INVALID_PROCESS_ID) -      ::kill(debugserver_pid, SIGINT); +      Host::Kill(debugserver_pid, SIGINT);    }    return packet_result; -#endif  }  GDBRemoteCommunication::PacketResult @@ -532,7 +524,7 @@ const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {      const char *domainsocket_dir_env =          ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");      if (domainsocket_dir_env != nullptr) -      g_domainsocket_dir = FileSpec(domainsocket_dir_env, false); +      g_domainsocket_dir = FileSpec(domainsocket_dir_env);      else        g_domainsocket_dir = HostInfo::GetProcessTempDir();    }); @@ -542,15 +534,15 @@ const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {  FileSpec  GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) { -  llvm::SmallString<PATH_MAX> socket_path; -  llvm::SmallString<PATH_MAX> socket_name( +  llvm::SmallString<128> socket_path; +  llvm::SmallString<128> socket_name(        (llvm::StringRef(prefix) + ".%%%%%%").str());    FileSpec socket_path_spec(GetDomainSocketDir());    socket_path_spec.AppendPathComponent(socket_name.c_str());    llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path); -  return FileSpec(socket_path.c_str(), false); +  return FileSpec(socket_path.c_str());  }  void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index aed5106272d1b..df51e0367d1d2 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -10,14 +10,10 @@  #ifndef liblldb_GDBRemoteCommunicationServerPlatform_h_  #define liblldb_GDBRemoteCommunicationServerPlatform_h_ -// C Includes -// C++ Includes  #include <map>  #include <mutex>  #include <set> -// Other libraries and framework includes -// Project includes  #include "GDBRemoteCommunicationServerCommon.h"  #include "lldb/Host/Socket.h" diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index 07dab751f4b90..e58f47f4befef 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -9,17 +9,13 @@  #include "GDBRemoteRegisterContext.h" -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/RegisterValue.h" -#include "lldb/Core/Scalar.h"  #include "lldb/Target/ExecutionContext.h"  #include "lldb/Target/Target.h"  #include "lldb/Utility/DataBufferHeap.h"  #include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Scalar.h"  #include "lldb/Utility/StreamString.h" -// Project includes  #include "ProcessGDBRemote.h"  #include "ProcessGDBRemoteLog.h"  #include "ThreadGDBRemote.h" @@ -462,7 +458,7 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues(        ((ProcessGDBRemote *)process)->GetGDBRemote());    const bool use_g_packet = -      gdb_comm.AvoidGPackets((ProcessGDBRemote *)process) == false; +      !gdb_comm.AvoidGPackets((ProcessGDBRemote *)process);    GDBRemoteClientBase::Lock lock(gdb_comm, false);    if (lock) { @@ -525,7 +521,7 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(        ((ProcessGDBRemote *)process)->GetGDBRemote());    const bool use_g_packet = -      gdb_comm.AvoidGPackets((ProcessGDBRemote *)process) == false; +      !gdb_comm.AvoidGPackets((ProcessGDBRemote *)process);    GDBRemoteClientBase::Lock lock(gdb_comm, false);    if (lock) { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h index 8ef91af55e0f8..6e8f3306669f3 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -10,12 +10,8 @@  #ifndef lldb_GDBRemoteRegisterContext_h_  #define lldb_GDBRemoteRegisterContext_h_ -// C Includes -// C++ Includes  #include <vector> -// Other libraries and framework includes -// Project includes  #include "Plugins/Process/Utility/DynamicRegisterInfo.h"  #include "lldb/Target/RegisterContext.h"  #include "lldb/Utility/ConstString.h" diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index b3d33b19bd666..797f63d537a17 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -9,12 +9,11 @@  #include "lldb/Host/Config.h" -// C Includes  #include <errno.h>  #include <stdlib.h>  #ifndef LLDB_DISABLE_POSIX  #include <netinet/in.h> -#include <sys/mman.h> // for mmap +#include <sys/mman.h>  #include <sys/socket.h>  #include <unistd.h>  #endif @@ -22,7 +21,6 @@  #include <sys/types.h>  #include <time.h> -// C++ Includes  #include <algorithm>  #include <csignal>  #include <map> @@ -34,7 +32,6 @@  #include "lldb/Core/Module.h"  #include "lldb/Core/ModuleSpec.h"  #include "lldb/Core/PluginManager.h" -#include "lldb/Core/State.h"  #include "lldb/Core/StreamFile.h"  #include "lldb/Core/Value.h"  #include "lldb/DataFormatters/FormatManager.h" @@ -68,10 +65,11 @@  #include "lldb/Utility/Args.h"  #include "lldb/Utility/CleanUp.h"  #include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Reproducer.h" +#include "lldb/Utility/State.h"  #include "lldb/Utility/StreamString.h"  #include "lldb/Utility/Timer.h" -// Project includes  #include "GDBRemoteRegisterContext.h"  #include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"  #include "Plugins/Process/Utility/GDBRemoteSignals.h" @@ -88,6 +86,7 @@  #include "llvm/Support/raw_ostream.h"  #define DEBUGSERVER_BASENAME "debugserver" +using namespace llvm;  using namespace lldb;  using namespace lldb_private;  using namespace lldb_private::process_gdb_remote; @@ -101,21 +100,21 @@ namespace lldb {  // and get the packet history dumped to a file.  void DumpProcessGDBRemotePacketHistory(void *p, const char *path) {    StreamFile strm; -  Status error(strm.GetFile().Open(path, File::eOpenOptionWrite | -                                             File::eOpenOptionCanCreate)); +  Status error = FileSystem::Instance().Open(strm.GetFile(), FileSpec(path), +                                             File::eOpenOptionWrite | +                                                 File::eOpenOptionCanCreate);    if (error.Success())      ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm);  } -} +} // namespace lldb  namespace { -static PropertyDefinition g_properties[] = { -    {"packet-timeout", OptionValue::eTypeUInt64, true, 1, NULL, NULL, +static constexpr PropertyDefinition g_properties[] = { +    {"packet-timeout", OptionValue::eTypeUInt64, true, 1, NULL, {},       "Specify the default packet timeout in seconds."}, -    {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, NULL, NULL, -     "The file that provides the description for remote target registers."}, -    {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; +    {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, NULL, {}, +     "The file that provides the description for remote target registers."}};  enum { ePropertyPacketTimeout, ePropertyTargetDefinitionFile }; @@ -158,7 +157,42 @@ static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() {    return g_settings_sp;  } -} // anonymous namespace end +class ProcessGDBRemoteProvider +    : public repro::Provider<ProcessGDBRemoteProvider> { +public: +  ProcessGDBRemoteProvider(const FileSpec &directory) : Provider(directory) { +    m_info.name = "gdb-remote"; +    m_info.files.push_back("gdb-remote.yaml"); +  } + +  raw_ostream *GetHistoryStream() { +    FileSpec history_file = +        GetRoot().CopyByAppendingPathComponent("gdb-remote.yaml"); + +    std::error_code EC; +    m_stream_up = llvm::make_unique<raw_fd_ostream>(history_file.GetPath(), EC, +                                                    sys::fs::OpenFlags::F_None); +    return m_stream_up.get(); +  } + +  void SetCallback(std::function<void()> callback) { +    m_callback = std::move(callback); +  } + +  void Keep() override { m_callback(); } + +  void Discard() override { m_callback(); } + +  static char ID; + +private: +  std::function<void()> m_callback; +  std::unique_ptr<raw_fd_ostream> m_stream_up; +}; + +char ProcessGDBRemoteProvider::ID = 0; + +} // namespace  // TODO Randomly assigning a port is unsafe.  We should get an unused  // ephemeral port from the kernel and make sure we reserve it before passing it @@ -234,7 +268,7 @@ bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp,      case ObjectFile::eTypeUnknown:        break;      } -    return exe_module->GetFileSpec().Exists(); +    return FileSystem::Instance().Exists(exe_module->GetFileSpec());    }    // However, if there is no executable module, we return true since we might    // be preparing to attach. @@ -259,8 +293,8 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,        m_addr_to_mmap_size(), m_thread_create_bp_sp(),        m_waiting_for_attach(false), m_destroy_tried_resuming(false),        m_command_sp(), m_breakpoint_pc_offset(0), -      m_initial_tid(LLDB_INVALID_THREAD_ID), m_allow_flash_writes(false), -      m_erased_flash_ranges() { +      m_initial_tid(LLDB_INVALID_THREAD_ID), m_replay_mode(false), +      m_allow_flash_writes(false), m_erased_flash_ranges() {    m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,                                     "async thread should exit");    m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, @@ -268,6 +302,15 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,    m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit,                                     "async thread did exit"); +  if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { +    ProcessGDBRemoteProvider &provider = +        g->GetOrCreate<ProcessGDBRemoteProvider>(); +    // Set the history stream to the stream owned by the provider. +    m_gdb_comm.SetHistoryStream(provider.GetHistoryStream()); +    // Make sure to clear the stream again when we're finished. +    provider.SetCallback([&]() { m_gdb_comm.SetHistoryStream(nullptr); }); +  } +    Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC));    const uint32_t async_event_mask = @@ -440,10 +483,10 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {    FileSpec target_definition_fspec =        GetGlobalPluginProperties()->GetTargetDefinitionFile(); -  if (!target_definition_fspec.Exists()) { +  if (!FileSystem::Instance().Exists(target_definition_fspec)) {      // If the filename doesn't exist, it may be a ~ not having been expanded -      // try to resolve it. -    target_definition_fspec.ResolvePath(); +    FileSystem::Instance().Resolve(target_definition_fspec);    }    if (target_definition_fspec) {      // See if we can get register definitions from a python file @@ -640,7 +683,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {    m_register_info.Finalize(GetTarget().GetArchitecture());  } -Status ProcessGDBRemote::WillLaunch(Module *module) { +Status ProcessGDBRemote::WillLaunch(lldb_private::Module *module) {    return WillLaunchOrAttach();  } @@ -689,7 +732,9 @@ Status ProcessGDBRemote::DoConnectRemote(Stream *strm,          if (m_gdb_comm.GetProcessArchitecture().IsValid()) {            target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());          } else { -          target.SetArchitecture(m_gdb_comm.GetHostArchitecture()); +          if (m_gdb_comm.GetHostArchitecture().IsValid()) { +            target.SetArchitecture(m_gdb_comm.GetHostArchitecture()); +          }          }        } @@ -754,7 +799,7 @@ Status ProcessGDBRemote::WillLaunchOrAttach() {  //----------------------------------------------------------------------  // Process Control  //---------------------------------------------------------------------- -Status ProcessGDBRemote::DoLaunch(Module *exe_module, +Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module,                                    ProcessLaunchInfo &launch_info) {    Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));    Status error; @@ -824,13 +869,13 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,        if (disable_stdio) {          // set to /dev/null unless redirected to a file above          if (!stdin_file_spec) -          stdin_file_spec.SetFile(FileSystem::DEV_NULL, false, +          stdin_file_spec.SetFile(FileSystem::DEV_NULL,                                    FileSpec::Style::native);          if (!stdout_file_spec) -          stdout_file_spec.SetFile(FileSystem::DEV_NULL, false, +          stdout_file_spec.SetFile(FileSystem::DEV_NULL,                                     FileSpec::Style::native);          if (!stderr_file_spec) -          stderr_file_spec.SetFile(FileSystem::DEV_NULL, false, +          stderr_file_spec.SetFile(FileSystem::DEV_NULL,                                     FileSpec::Style::native);        } else if (platform_sp && platform_sp->IsHost()) {          // If the debugserver is local and we aren't disabling STDIO, lets use @@ -839,7 +884,7 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,          // does a lot of output.          if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) &&              pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, NULL, 0)) { -          FileSpec slave_name{pty.GetSlaveName(NULL, 0), false}; +          FileSpec slave_name{pty.GetSlaveName(NULL, 0)};            if (!stdin_file_spec)              stdin_file_spec = slave_name; @@ -1058,9 +1103,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {        if (log)          log->Printf("ProcessGDBRemote::%s gdb-remote had process architecture, "                      "using %s %s", -                    __FUNCTION__, process_arch.GetArchitectureName() -                                      ? process_arch.GetArchitectureName() -                                      : "<null>", +                    __FUNCTION__, +                    process_arch.GetArchitectureName() +                        ? process_arch.GetArchitectureName() +                        : "<null>",                      process_arch.GetTriple().getTriple().c_str()                          ? process_arch.GetTriple().getTriple().c_str()                          : "<null>"); @@ -1069,9 +1115,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {        if (log)          log->Printf("ProcessGDBRemote::%s gdb-remote did not have process "                      "architecture, using gdb-remote host architecture %s %s", -                    __FUNCTION__, process_arch.GetArchitectureName() -                                      ? process_arch.GetArchitectureName() -                                      : "<null>", +                    __FUNCTION__, +                    process_arch.GetArchitectureName() +                        ? process_arch.GetArchitectureName() +                        : "<null>",                      process_arch.GetTriple().getTriple().c_str()                          ? process_arch.GetTriple().getTriple().c_str()                          : "<null>"); @@ -1083,9 +1130,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {          if (log)            log->Printf(                "ProcessGDBRemote::%s analyzing target arch, currently %s %s", -              __FUNCTION__, target_arch.GetArchitectureName() -                                ? target_arch.GetArchitectureName() -                                : "<null>", +              __FUNCTION__, +              target_arch.GetArchitectureName() +                  ? target_arch.GetArchitectureName() +                  : "<null>",                target_arch.GetTriple().getTriple().c_str()                    ? target_arch.GetTriple().getTriple().c_str()                    : "<null>"); @@ -1105,9 +1153,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {            if (log)              log->Printf("ProcessGDBRemote::%s remote process is ARM/Apple, "                          "setting target arch to %s %s", -                        __FUNCTION__, process_arch.GetArchitectureName() -                                          ? process_arch.GetArchitectureName() -                                          : "<null>", +                        __FUNCTION__, +                        process_arch.GetArchitectureName() +                            ? process_arch.GetArchitectureName() +                            : "<null>",                          process_arch.GetTriple().getTriple().c_str()                              ? process_arch.GetTriple().getTriple().c_str()                              : "<null>"); @@ -1135,9 +1184,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {          if (log)            log->Printf("ProcessGDBRemote::%s final target arch after "                        "adjustments for remote architecture: %s %s", -                      __FUNCTION__, target_arch.GetArchitectureName() -                                        ? target_arch.GetArchitectureName() -                                        : "<null>", +                      __FUNCTION__, +                      target_arch.GetArchitectureName() +                          ? target_arch.GetArchitectureName() +                          : "<null>",                        target_arch.GetTriple().getTriple().c_str()                            ? target_arch.GetTriple().getTriple().c_str()                            : "<null>"); @@ -1478,7 +1528,7 @@ Status ProcessGDBRemote::DoResume() {            new EventDataBytes(continue_packet.GetString().data(),                               continue_packet.GetSize())); -      if (listener_sp->GetEvent(event_sp, std::chrono::seconds(5)) == false) { +      if (!listener_sp->GetEvent(event_sp, std::chrono::seconds(5))) {          error.SetErrorString("Resume timed out.");          if (log)            log->Printf("ProcessGDBRemote::DoResume: Resume timed out."); @@ -1832,7 +1882,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(            bool handled = false;            bool did_exec = false;            if (!reason.empty()) { -            if (reason.compare("trace") == 0) { +            if (reason == "trace") {                addr_t pc = thread_sp->GetRegisterContext()->GetPC();                lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()                                                        ->GetBreakpointSiteList() @@ -1850,7 +1900,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(                  thread_sp->SetStopInfo(                      StopInfo::CreateStopReasonToTrace(*thread_sp));                handled = true; -            } else if (reason.compare("breakpoint") == 0) { +            } else if (reason == "breakpoint") {                addr_t pc = thread_sp->GetRegisterContext()->GetPC();                lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()                                                        ->GetBreakpointSiteList() @@ -1871,9 +1921,9 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(                    thread_sp->SetStopInfo(invalid_stop_info_sp);                  }                } -            } else if (reason.compare("trap") == 0) { +            } else if (reason == "trap") {                // Let the trap just use the standard signal stop reason below... -            } else if (reason.compare("watchpoint") == 0) { +            } else if (reason == "watchpoint") {                StringExtractor desc_extractor(description.c_str());                addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);                uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); @@ -1905,11 +1955,11 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(                thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID(                    *thread_sp, watch_id, wp_hit_addr));                handled = true; -            } else if (reason.compare("exception") == 0) { +            } else if (reason == "exception") {                thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException(                    *thread_sp, description.c_str()));                handled = true; -            } else if (reason.compare("exec") == 0) { +            } else if (reason == "exec") {                did_exec = true;                thread_sp->SetStopInfo(                    StopInfo::CreateStopReasonWithExec(*thread_sp)); @@ -1934,7 +1984,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(              }            } -          if (!handled && signo && did_exec == false) { +          if (!handled && signo && !did_exec) {              if (signo == SIGTRAP) {                // Currently we are going to assume SIGTRAP means we are either                // hitting a breakpoint or hardware single stepping. @@ -2648,7 +2698,7 @@ void ProcessGDBRemote::SetLastStopPacket(      // We are are not using non-stop mode, there can only be one last stop      // reply packet, so clear the list. -    if (GetTarget().GetNonStopModeEnabled() == false) +    if (!GetTarget().GetNonStopModeEnabled())        m_stop_packet_stack.clear();      // Add this stop packet to the stop packet stack This stack will get popped @@ -3378,6 +3428,43 @@ Status ProcessGDBRemote::DoSignal(int signo) {    return error;  } +Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) { +  if (!loader) +    return Status("No loader provided."); + +  auto provider_info = loader->GetProviderInfo("gdb-remote"); +  if (!provider_info) +    return Status("No provider for gdb-remote."); + +  if (provider_info->files.empty()) +    return Status("Provider for  gdb-remote contains no files."); + +  // Construct replay history path. +  FileSpec history_file = loader->GetRoot().CopyByAppendingPathComponent( +      provider_info->files.front()); + +  // Enable replay mode. +  m_replay_mode = true; + +  // Load replay history. +  if (auto error = m_gdb_replay_server.LoadReplayHistory(history_file)) +    return Status("Unable to load replay history"); + +  // Make a local connection. +  if (auto error = GDBRemoteCommunication::ConnectLocally(m_gdb_comm, +                                                          m_gdb_replay_server)) +    return Status("Unable to connect to replay server"); + +  // Start server thread. +  m_gdb_replay_server.StartAsyncThread(); + +  // Start client thread. +  StartAsyncThread(); + +  // Do the usual setup. +  return ConnectToDebugserver(""); +} +  Status  ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) {    // Make sure we aren't already connected? @@ -3388,6 +3475,9 @@ ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) {    if (platform_sp && !platform_sp->IsHost())      return Status("Lost debug server connection"); +  if (repro::Loader *loader = repro::Reproducer::Instance().GetLoader()) +    return ConnectToReplayServer(loader); +    auto error = LaunchAndConnectToDebugserver(process_info);    if (error.Fail()) {      const char *error_string = error.AsCString(); @@ -3497,7 +3587,7 @@ bool ProcessGDBRemote::MonitorDebugserverProcess(      bool exited,    // True if the process did exit      int signo,      // Zero for no signal      int exit_status // Exit value of process if signal is zero -    ) { +) {    // "debugserver_pid" argument passed in is the process ID for debugserver    // that we are tracking...    Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); @@ -4269,8 +4359,9 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,      return false;    feature_node.ForEachChildElementWithName( -      "reg", [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, -              &abi_sp](const XMLNode ®_node) -> bool { +      "reg", +      [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, +       &abi_sp](const XMLNode ®_node) -> bool {          std::string gdb_group;          std::string gdb_type;          ConstString reg_name; @@ -4432,7 +4523,7 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,    return true;  } -} // namespace {} +} // namespace  // query the target of gdb-remote for extended target information return:  // 'true'  on success @@ -4509,12 +4600,19 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {        //   <architecture>arm</architecture> (seen from Segger JLink on unspecified arm board)        // use that if we don't have anything better.        if (!arch_to_use.IsValid() && !target_info.arch.empty()) { -        if (target_info.arch == "i386:x86-64") -        { +        if (target_info.arch == "i386:x86-64") {            // We don't have any information about vendor or OS.            arch_to_use.SetTriple("x86_64--");            GetTarget().MergeArchitecture(arch_to_use);          } + +        // SEGGER J-Link jtag boards send this very-generic arch name, +        // we'll need to use this if we have absolutely nothing better +        // to work with or the register definitions won't be accepted. +        if (target_info.arch == "arm") { +          arch_to_use.SetTriple("arm--"); +          GetTarget().MergeArchitecture(arch_to_use); +        }        }        // Initialize these outside of ParseRegisters, since they should not be @@ -4760,7 +4858,8 @@ size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) {      if (!modInfo.get_link_map(link_map))        link_map = LLDB_INVALID_ADDRESS; -    FileSpec file(mod_name, true); +    FileSpec file(mod_name); +    FileSystem::Instance().Resolve(file);      lldb::ModuleSP module_sp =          LoadModuleAtAddress(file, link_map, mod_base, mod_base_is_offset); @@ -4802,7 +4901,7 @@ size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) {          return true;        lldb::ModuleSP module_copy_sp = module_sp; -      target.SetExecutableModule(module_copy_sp, false); +      target.SetExecutableModule(module_copy_sp, eLoadDependentsNo);        return false;      }); diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 45bb2d4c28e71..14a5237e43451 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -10,15 +10,12 @@  #ifndef liblldb_ProcessGDBRemote_h_  #define liblldb_ProcessGDBRemote_h_ -// C Includes -// C++ Includes  #include <atomic>  #include <map>  #include <mutex>  #include <string>  #include <vector> -#include "lldb/Core/Broadcaster.h"  #include "lldb/Core/LoadedModuleInfoList.h"  #include "lldb/Core/ModuleSpec.h"  #include "lldb/Core/ThreadSafeValue.h" @@ -26,6 +23,7 @@  #include "lldb/Target/Process.h"  #include "lldb/Target/Thread.h"  #include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/Broadcaster.h"  #include "lldb/Utility/ConstString.h"  #include "lldb/Utility/Status.h"  #include "lldb/Utility/StreamGDBRemote.h" @@ -36,11 +34,15 @@  #include "lldb/lldb-private-forward.h"  #include "GDBRemoteCommunicationClient.h" +#include "GDBRemoteCommunicationReplayServer.h"  #include "GDBRemoteRegisterContext.h"  #include "llvm/ADT/DenseMap.h"  namespace lldb_private { +namespace repro { +class Loader; +}  namespace process_gdb_remote {  class ThreadGDBRemote; @@ -264,6 +266,7 @@ protected:    };    GDBRemoteCommunicationClient m_gdb_comm; +  GDBRemoteCommunicationReplayServer m_gdb_replay_server;    std::atomic<lldb::pid_t> m_debugserver_pid;    std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet                                                               // stack replaces @@ -304,6 +307,7 @@ protected:    int64_t m_breakpoint_pc_offset;    lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach +  bool m_replay_mode;    bool m_allow_flash_writes;    using FlashRangeVector = lldb_private::RangeVector<lldb::addr_t, size_t>;    using FlashRange = FlashRangeVector::Entry; @@ -331,6 +335,8 @@ protected:    bool UpdateThreadList(ThreadList &old_thread_list,                          ThreadList &new_thread_list) override; +  Status ConnectToReplayServer(repro::Loader *loader); +    Status EstablishConnectionIfNeeded(const ProcessInfo &process_info);    Status LaunchAndConnectToDebugserver(const ProcessInfo &process_info); diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h index 3c58011766908..d4981df88d8da 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h @@ -10,11 +10,7 @@  #ifndef liblldb_ProcessGDBRemoteLog_h_  #define liblldb_ProcessGDBRemoteLog_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes  #include "lldb/Utility/Log.h"  #define GDBR_LOG_PROCESS (1u << 1) diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index a525c16b9f135..db7dc3eae0ba4 100644 --- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -10,7 +10,6 @@  #include "ThreadGDBRemote.h"  #include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Core/State.h"  #include "lldb/Target/Platform.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/RegisterContext.h" @@ -20,6 +19,7 @@  #include "lldb/Target/UnixSignals.h"  #include "lldb/Target/Unwind.h"  #include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/State.h"  #include "lldb/Utility/StreamString.h"  #include "ProcessGDBRemote.h" @@ -197,13 +197,10 @@ void ThreadGDBRemote::SetQueueLibdispatchQueueAddress(  }  bool ThreadGDBRemote::ThreadHasQueueInformation() const { -  if (m_thread_dispatch_qaddr != 0 && -      m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS && -      m_dispatch_queue_t != LLDB_INVALID_ADDRESS && -      m_queue_kind != eQueueKindUnknown && m_queue_serial_number != 0) { -    return true; -  } -  return false; +  return m_thread_dispatch_qaddr != 0 && +         m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS && +         m_dispatch_queue_t != LLDB_INVALID_ADDRESS && +         m_queue_kind != eQueueKindUnknown && m_queue_serial_number != 0;  }  LazyBool ThreadGDBRemote::GetAssociatedWithLibdispatchQueue() { diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index 1a5b60aea2887..4485a9cdc4c36 100644 --- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -10,12 +10,8 @@  #ifndef liblldb_ThreadGDBRemote_h_  #define liblldb_ThreadGDBRemote_h_ -// C Includes -// C++ Includes  #include <string> -// Other libraries and framework includes -// Project includes  #include "lldb/Target/Process.h"  #include "lldb/Target/Thread.h"  #include "lldb/Utility/StructuredData.h" | 
