diff options
Diffstat (limited to 'source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp')
-rw-r--r-- | source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp | 176 |
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() { |