summaryrefslogtreecommitdiff
path: root/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
diff options
context:
space:
mode:
authorJonas Devlieghere <jonas@devlieghere.com>2018-11-13 19:18:16 +0000
committerJonas Devlieghere <jonas@devlieghere.com>2018-11-13 19:18:16 +0000
commit4a245e00ee7f47645eece875cd6cc4a69185eee8 (patch)
tree7a12758df8cf1760eb0dd06c837f7a847c97ce8a /source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
parent9dfc53a2aaabe9a10a1b9b5c2151014b590107ab (diff)
Add GDB remote packet reproducer.
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@346780 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp')
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp143
1 files changed, 59 insertions, 84 deletions
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 23b24baf9..0f32d6ead 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -9,6 +9,7 @@
#include "GDBRemoteCommunication.h"
+#include <future>
#include <limits.h>
#include <string.h>
#include <sys/stat.h>
@@ -22,6 +23,8 @@
#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"
@@ -51,78 +54,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
//----------------------------------------------------------------------
@@ -169,7 +100,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;
}
@@ -180,26 +112,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;
@@ -238,11 +175,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;
@@ -857,7 +795,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.
@@ -1302,6 +1241,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) {