summaryrefslogtreecommitdiff
path: root/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp')
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp176
1 files changed, 86 insertions, 90 deletions
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 72c1314a7c94..11052eff948f 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -1,9 +1,8 @@
//===-- GDBRemoteCommunication.cpp ------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -20,13 +19,14 @@
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Pipe.h"
+#include "lldb/Host/ProcessLaunchInfo.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/Event.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
@@ -42,8 +42,7 @@
#define DEBUGSERVER_BASENAME "lldb-server"
#endif
-#if defined(__APPLE__)
-#define HAVE_LIBCOMPRESSION
+#if defined(HAVE_LIBCOMPRESSION)
#include <compression.h>
#endif
@@ -55,9 +54,7 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
-//----------------------------------------------------------------------
// GDBRemoteCommunication constructor
-//----------------------------------------------------------------------
GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
const char *listener_name)
: Communication(comm_name),
@@ -68,22 +65,19 @@ 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_decompression_scratch_type(CompressionType::None),
- m_decompression_scratch(nullptr) {
- // Unused unless HAVE_LIBCOMPRESSION is defined.
- (void)m_decompression_scratch_type;
+ m_listen_url() {
}
-//----------------------------------------------------------------------
// Destructor
-//----------------------------------------------------------------------
GDBRemoteCommunication::~GDBRemoteCommunication() {
if (IsConnected()) {
Disconnect();
}
+#if defined(HAVE_LIBCOMPRESSION)
if (m_decompression_scratch)
free (m_decompression_scratch);
+#endif
// Stop the communications read thread which is used to parse all incoming
// packets. This function will block until the read thread returns.
@@ -104,7 +98,7 @@ size_t GDBRemoteCommunication::SendAck() {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
ConnectionStatus status = eConnectionStatusSuccess;
char ch = '+';
- const size_t bytes_written = Write(&ch, 1, status, NULL);
+ const size_t bytes_written = Write(&ch, 1, status, nullptr);
if (log)
log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
m_history.AddPacket(ch, GDBRemoteCommunicationHistory::ePacketTypeSend,
@@ -116,7 +110,7 @@ size_t GDBRemoteCommunication::SendNack() {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
ConnectionStatus status = eConnectionStatusSuccess;
char ch = '-';
- const size_t bytes_written = Write(&ch, 1, status, NULL);
+ const size_t bytes_written = Write(&ch, 1, status, nullptr);
if (log)
log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
m_history.AddPacket(ch, GDBRemoteCommunicationHistory::ePacketTypeSend,
@@ -126,14 +120,14 @@ size_t GDBRemoteCommunication::SendNack() {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunication::SendPacketNoLock(llvm::StringRef payload) {
- 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);
+ 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
@@ -144,7 +138,7 @@ GDBRemoteCommunication::SendRawPacketNoLock(llvm::StringRef packet,
ConnectionStatus status = eConnectionStatusSuccess;
const char *packet_data = packet.data();
const size_t packet_length = packet.size();
- size_t bytes_written = Write(packet_data, packet_length, status, NULL);
+ size_t bytes_written = Write(packet_data, packet_length, status, nullptr);
if (log) {
size_t binary_start_offset = 0;
if (strncmp(packet_data, "$vFile:pwrite:", strlen("$vFile:pwrite:")) ==
@@ -280,7 +274,7 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
// Check for a packet from our cache first without trying any reading...
- if (CheckForPacket(NULL, 0, packet) != PacketType::Invalid)
+ if (CheckForPacket(nullptr, 0, packet) != PacketType::Invalid)
return PacketResult::Success;
bool timed_out = false;
@@ -303,7 +297,6 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
case eConnectionStatusTimedOut:
case eConnectionStatusInterrupted:
if (sync_on_timeout) {
- //------------------------------------------------------------------
/// Sync the remote GDB server and make sure we get a response that
/// corresponds to what we send.
///
@@ -326,7 +319,6 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
/// packets. So if we timeout, we need to ensure that we can get
/// back on track. If we can't get back on track, we must
/// disconnect.
- //------------------------------------------------------------------
bool sync_success = false;
bool got_actual_response = false;
// We timed out, we need to sync back up with the
@@ -478,7 +470,7 @@ bool GDBRemoteCommunication::DecompressPacket() {
content_length = hash_mark_idx - content_start;
std::string bufsize_str(m_bytes.data() + 2, i - 2 - 1);
errno = 0;
- decompressed_bufsize = ::strtoul(bufsize_str.c_str(), NULL, 10);
+ decompressed_bufsize = ::strtoul(bufsize_str.c_str(), nullptr, 10);
if (errno != 0 || decompressed_bufsize == ULONG_MAX) {
m_bytes.erase(0, size_of_first_packet);
return false;
@@ -491,7 +483,7 @@ bool GDBRemoteCommunication::DecompressPacket() {
packet_checksum_cstr[0] = m_bytes[checksum_idx];
packet_checksum_cstr[1] = m_bytes[checksum_idx + 1];
packet_checksum_cstr[2] = '\0';
- long packet_checksum = strtol(packet_checksum_cstr, NULL, 16);
+ long packet_checksum = strtol(packet_checksum_cstr, nullptr, 16);
long actual_checksum = CalculcateChecksum(
llvm::StringRef(m_bytes).substr(1, hash_mark_idx - 1));
@@ -549,7 +541,7 @@ bool GDBRemoteCommunication::DecompressPacket() {
#if defined(HAVE_LIBCOMPRESSION)
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)
@@ -586,7 +578,7 @@ bool GDBRemoteCommunication::DecompressPacket() {
if (decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr) {
decompressed_bytes = compression_decode_buffer(
decompressed_buffer, decompressed_bufsize,
- (uint8_t *)unescaped_content.data(), unescaped_content.size(),
+ (uint8_t *)unescaped_content.data(), unescaped_content.size(),
m_decompression_scratch, compression_type);
}
}
@@ -856,7 +848,7 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
::isxdigit(m_bytes[checksum_idx + 1])) {
if (GetSendAcks()) {
const char *packet_checksum_cstr = &m_bytes[checksum_idx];
- char packet_checksum = strtol(packet_checksum_cstr, NULL, 16);
+ char packet_checksum = strtol(packet_checksum_cstr, nullptr, 16);
char actual_checksum = CalculcateChecksum(
llvm::StringRef(m_bytes).slice(content_start, content_end));
success = packet_checksum == actual_checksum;
@@ -896,22 +888,23 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
Status GDBRemoteCommunication::StartListenThread(const char *hostname,
uint16_t port) {
- Status error;
- if (m_listen_thread.IsJoinable()) {
- error.SetErrorString("listen thread already running");
- } else {
- char listen_url[512];
- if (hostname && hostname[0])
- snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname,
- port);
- else
- snprintf(listen_url, sizeof(listen_url), "listen://%i", port);
- m_listen_url = listen_url;
- SetConnection(new ConnectionFileDescriptor());
- m_listen_thread = ThreadLauncher::LaunchThread(
- listen_url, GDBRemoteCommunication::ListenThread, this, &error);
- }
- return error;
+ if (m_listen_thread.IsJoinable())
+ return Status("listen thread already running");
+
+ char listen_url[512];
+ if (hostname && hostname[0])
+ snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname, port);
+ else
+ snprintf(listen_url, sizeof(listen_url), "listen://%i", port);
+ m_listen_url = listen_url;
+ SetConnection(new ConnectionFileDescriptor());
+ llvm::Expected<HostThread> listen_thread = ThreadLauncher::LaunchThread(
+ listen_url, GDBRemoteCommunication::ListenThread, this);
+ if (!listen_thread)
+ return Status(listen_thread.takeError());
+ m_listen_thread = *listen_thread;
+
+ return Status();
}
bool GDBRemoteCommunication::JoinListenThread() {
@@ -931,9 +924,9 @@ GDBRemoteCommunication::ListenThread(lldb::thread_arg_t arg) {
// Do the listen on another thread so we can continue on...
if (connection->Connect(comm->m_listen_url.c_str(), &error) !=
eConnectionStatusSuccess)
- comm->SetConnection(NULL);
+ comm->SetConnection(nullptr);
}
- return NULL;
+ return {};
}
Status GDBRemoteCommunication::StartDebugserverProcess(
@@ -952,16 +945,18 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
char debugserver_path[PATH_MAX];
FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
+ Environment host_env = Host::GetEnvironment();
+
// Always check to see if we have an environment override for the path to the
// debugserver to use and use it if we do.
- const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
- if (env_debugserver_path) {
+ std::string env_debugserver_path = host_env.lookup("LLDB_DEBUGSERVER_PATH");
+ if (!env_debugserver_path.empty()) {
debugserver_file_spec.SetFile(env_debugserver_path,
FileSpec::Style::native);
if (log)
log->Printf("GDBRemoteCommunication::%s() gdb-remote stub exe path set "
"from environment variable: %s",
- __FUNCTION__, env_debugserver_path);
+ __FUNCTION__, env_debugserver_path.c_str());
} else
debugserver_file_spec = g_debugserver_file_spec;
bool debugserver_exists =
@@ -980,8 +975,11 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
g_debugserver_file_spec = debugserver_file_spec;
} else {
- debugserver_file_spec =
- platform->LocateExecutable(DEBUGSERVER_BASENAME);
+ if (platform)
+ debugserver_file_spec =
+ platform->LocateExecutable(DEBUGSERVER_BASENAME);
+ else
+ debugserver_file_spec.Clear();
if (debugserver_file_spec) {
// Platform::LocateExecutable() wouldn't return a path if it doesn't
// exist
@@ -1004,7 +1002,6 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
Args &debugserver_args = launch_info.GetArguments();
debugserver_args.Clear();
- char arg_cstr[PATH_MAX];
// Start args with "debugserver /file/path -r --"
debugserver_args.AppendArgument(llvm::StringRef(debugserver_path));
@@ -1114,29 +1111,27 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
}
}
}
-
- const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
- if (env_debugserver_log_file) {
- ::snprintf(arg_cstr, sizeof(arg_cstr), "--log-file=%s",
- env_debugserver_log_file);
- debugserver_args.AppendArgument(llvm::StringRef(arg_cstr));
+ std::string env_debugserver_log_file =
+ host_env.lookup("LLDB_DEBUGSERVER_LOG_FILE");
+ if (!env_debugserver_log_file.empty()) {
+ debugserver_args.AppendArgument(
+ llvm::formatv("--log-file={0}", env_debugserver_log_file).str());
}
#if defined(__APPLE__)
const char *env_debugserver_log_flags =
getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
if (env_debugserver_log_flags) {
- ::snprintf(arg_cstr, sizeof(arg_cstr), "--log-flags=%s",
- env_debugserver_log_flags);
- debugserver_args.AppendArgument(llvm::StringRef(arg_cstr));
+ debugserver_args.AppendArgument(
+ llvm::formatv("--log-flags={0}", env_debugserver_log_flags).str());
}
#else
- const char *env_debugserver_log_channels =
- getenv("LLDB_SERVER_LOG_CHANNELS");
- if (env_debugserver_log_channels) {
- ::snprintf(arg_cstr, sizeof(arg_cstr), "--log-channels=%s",
- env_debugserver_log_channels);
- debugserver_args.AppendArgument(llvm::StringRef(arg_cstr));
+ std::string env_debugserver_log_channels =
+ host_env.lookup("LLDB_SERVER_LOG_CHANNELS");
+ if (!env_debugserver_log_channels.empty()) {
+ debugserver_args.AppendArgument(
+ llvm::formatv("--log-channels={0}", env_debugserver_log_channels)
+ .str());
}
#endif
@@ -1148,15 +1143,15 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
char env_var_name[64];
snprintf(env_var_name, sizeof(env_var_name),
"LLDB_DEBUGSERVER_EXTRA_ARG_%" PRIu32, env_var_index++);
- const char *extra_arg = getenv(env_var_name);
- has_env_var = extra_arg != nullptr;
+ std::string extra_arg = host_env.lookup(env_var_name);
+ has_env_var = !extra_arg.empty();
if (has_env_var) {
debugserver_args.AppendArgument(llvm::StringRef(extra_arg));
if (log)
log->Printf("GDBRemoteCommunication::%s adding env var %s contents "
"to stub command line (%s)",
- __FUNCTION__, env_var_name, extra_arg);
+ __FUNCTION__, env_var_name, extra_arg.c_str());
}
} while (has_env_var);
@@ -1166,7 +1161,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
}
// Copy the current environment to the gdbserver/debugserver instance
- launch_info.GetEnvironment() = Host::GetEnvironment();
+ launch_info.GetEnvironment() = host_env;
// Close STDIN, STDOUT and STDERR.
launch_info.AppendCloseFileAction(STDIN_FILENO);
@@ -1266,7 +1261,7 @@ 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,
@@ -1284,13 +1279,14 @@ GDBRemoteCommunication::ConnectLocally(GDBRemoteCommunication &client,
llvm::SmallString<32> remote_addr;
llvm::raw_svector_ostream(remote_addr)
- << "connect://localhost:" << listen_socket.GetLocalPortNumber();
+ << "connect://127.0.0.1:" << 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());
+ Status status;
+ if (conn_up->Connect(remote_addr, &status) != lldb::eConnectionStatusSuccess)
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Unable to connect: %s", status.AsCString());
client.SetConnection(conn_up.release());
if (llvm::Error error = accept_status.get().ToError())
@@ -1302,14 +1298,14 @@ GDBRemoteCommunication::ConnectLocally(GDBRemoteCommunication &client,
GDBRemoteCommunication::ScopedTimeout::ScopedTimeout(
GDBRemoteCommunication &gdb_comm, std::chrono::seconds timeout)
- : m_gdb_comm(gdb_comm), m_timeout_modified(false) {
- auto curr_timeout = gdb_comm.GetPacketTimeout();
- // Only update the timeout if the timeout is greater than the current
- // timeout. If the current timeout is larger, then just use that.
- if (curr_timeout < timeout) {
- m_timeout_modified = true;
- m_saved_timeout = m_gdb_comm.SetPacketTimeout(timeout);
- }
+ : m_gdb_comm(gdb_comm), m_timeout_modified(false) {
+ auto curr_timeout = gdb_comm.GetPacketTimeout();
+ // Only update the timeout if the timeout is greater than the current
+ // timeout. If the current timeout is larger, then just use that.
+ if (curr_timeout < timeout) {
+ m_timeout_modified = true;
+ m_saved_timeout = m_gdb_comm.SetPacketTimeout(timeout);
+ }
}
GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout() {