summaryrefslogtreecommitdiff
path: root/source/Plugins/Process/gdb-remote
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:06:29 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:06:29 +0000
commit94994d372d014ce4c8758b9605d63fae651bd8aa (patch)
tree51c0b708bd59f205d6b35cb2a8c24d62f0c33d77 /source/Plugins/Process/gdb-remote
parent39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff)
Notes
Diffstat (limited to 'source/Plugins/Process/gdb-remote')
-rw-r--r--source/Plugins/Process/gdb-remote/CMakeLists.txt2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp212
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h98
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp57
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp143
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h156
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp204
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h83
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp3
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp51
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp18
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp18
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp12
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h4
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp215
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h12
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h4
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp13
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.h4
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, &reg_offset,
- &abi_sp](const XMLNode &reg_node) -> bool {
+ "reg",
+ [&target_info, &dyn_reg_info, &cur_reg_num, &reg_offset,
+ &abi_sp](const XMLNode &reg_node) -> bool {
std::string gdb_group;
std::string gdb_type;
ConstString reg_name;
@@ -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"