diff options
Diffstat (limited to 'source/Plugins/Process/gdb-remote')
26 files changed, 850 insertions, 731 deletions
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp index a3a4aa053261..fe7ef6b3acea 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp @@ -1,9 +1,8 @@ //===-- GDBRemoteClientBase.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 // //===----------------------------------------------------------------------===// @@ -11,7 +10,6 @@ #include "llvm/ADT/StringExtras.h" -#include "lldb/Target/Process.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/LLDBAssert.h" @@ -287,7 +285,7 @@ bool GDBRemoteClientBase::ShouldStop(const UnixSignals &signals, void GDBRemoteClientBase::OnRunPacketSent(bool first) { if (first) - BroadcastEvent(eBroadcastBitRunPacketSent, NULL); + BroadcastEvent(eBroadcastBitRunPacketSent, nullptr); } /////////////////////////////////////// @@ -367,7 +365,7 @@ void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) { // packet. Let's interrupt it. const char ctrl_c = '\x03'; ConnectionStatus status = eConnectionStatusSuccess; - size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, NULL); + size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, nullptr); if (bytes_written == 0) { --m_comm.m_async_count; if (log) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h index 3d84ce0ebe18..54f69e8caac6 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h @@ -1,9 +1,8 @@ //===-- GDBRemoteClientBase.h -----------------------------------*- 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 // //===----------------------------------------------------------------------===// @@ -28,7 +27,7 @@ public: // ========================================================================= /// Process asynchronously-received structured data. /// - /// @param[in] data + /// \param[in] data /// The complete data packet, expected to start with JSON-async. // ========================================================================= virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data) = 0; 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() { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index 369eb25b1dfa..bb777a5c26a7 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunication.h --------------------------------*- 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 // //===----------------------------------------------------------------------===// @@ -19,6 +18,7 @@ #include <vector> #include "lldb/Core/Communication.h" +#include "lldb/Host/Config.h" #include "lldb/Host/HostThread.h" #include "lldb/Utility/Args.h" #include "lldb/Utility/Listener.h" @@ -29,14 +29,14 @@ namespace lldb_private { namespace process_gdb_remote { -typedef enum { +enum GDBStoppointType { eStoppointInvalid = -1, eBreakpointSoftware = 0, eBreakpointHardware, eWatchpointWrite, eWatchpointRead, eWatchpointReadWrite -} GDBStoppointType; +}; enum class CompressionType { None = 0, // no compression @@ -109,13 +109,11 @@ public: bool GetSendAcks() { return m_send_acks; } - //------------------------------------------------------------------ // Set the global packet timeout. // // For clients, this is the timeout that gets used when sending // packets and waiting for responses. For servers, this is used when waiting // for ACKs. - //------------------------------------------------------------------ std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) { const auto old_packet_timeout = m_packet_timeout; m_packet_timeout = packet_timeout; @@ -124,10 +122,8 @@ public: std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; } - //------------------------------------------------------------------ // Start a debugserver instance on the current host using the // supplied connection URL. - //------------------------------------------------------------------ Status StartDebugserverProcess( const char *url, Platform *platform, // If non nullptr, then check with the platform for @@ -218,8 +214,10 @@ private: HostThread m_listen_thread; std::string m_listen_url; - CompressionType m_decompression_scratch_type; - void *m_decompression_scratch; +#if defined(HAVE_LIBCOMPRESSION) + CompressionType m_decompression_scratch_type = CompressionType::None; + void *m_decompression_scratch = nullptr; +#endif DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunication); }; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 1e12ea6b2d56..9797184026e0 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationClient.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 // //===----------------------------------------------------------------------===// @@ -38,7 +37,9 @@ #include "llvm/ADT/StringSwitch.h" #if defined(__APPLE__) +#ifndef HAVE_LIBCOMPRESSION #define HAVE_LIBCOMPRESSION +#endif #include <compression.h> #endif @@ -47,9 +48,7 @@ using namespace lldb_private; using namespace lldb_private::process_gdb_remote; using namespace std::chrono; -//---------------------------------------------------------------------- // GDBRemoteCommunicationClient constructor -//---------------------------------------------------------------------- GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() : GDBRemoteClientBase("gdb-remote.client", "gdb-remote.client.rx_packet"), m_supports_not_sending_acks(eLazyBoolCalculate), @@ -104,9 +103,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() m_supported_async_json_packets_sp(), m_qXfer_memory_map(), m_qXfer_memory_map_loaded(false) {} -//---------------------------------------------------------------------- // Destructor -//---------------------------------------------------------------------- GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() { if (IsConnected()) Disconnect(); @@ -389,14 +386,14 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { std::vector<std::string> supported_compressions; compressions += sizeof("SupportedCompressions=") - 1; const char *end_of_compressions = strchr(compressions, ';'); - if (end_of_compressions == NULL) { + if (end_of_compressions == nullptr) { end_of_compressions = strchr(compressions, '\0'); } const char *current_compression = compressions; while (current_compression < end_of_compressions) { const char *next_compression_name = strchr(current_compression, ','); const char *end_of_this_word = next_compression_name; - if (next_compression_name == NULL || + if (next_compression_name == nullptr || end_of_compressions < next_compression_name) { end_of_this_word = end_of_compressions; } @@ -778,7 +775,7 @@ int GDBRemoteCommunicationClient::SendArgumentsPacket( std::vector<const char *> argv; FileSpec exe_file = launch_info.GetExecutableFile(); std::string exe_path; - const char *arg = NULL; + const char *arg = nullptr; const Args &launch_args = launch_info.GetArguments(); if (exe_file) exe_path = exe_file.GetPath(false); @@ -789,7 +786,7 @@ int GDBRemoteCommunicationClient::SendArgumentsPacket( } if (!exe_path.empty()) { argv.push_back(exe_path.c_str()); - for (uint32_t i = 1; (arg = launch_args.GetArgumentAtIndex(i)) != NULL; + for (uint32_t i = 1; (arg = launch_args.GetArgumentAtIndex(i)) != nullptr; ++i) { if (arg) argv.push_back(arg); @@ -1097,7 +1094,7 @@ const char *GDBRemoteCommunicationClient::GetGDBServerProgramName() { if (!m_gdb_server_name.empty()) return m_gdb_server_name.c_str(); } - return NULL; + return nullptr; } uint32_t GDBRemoteCommunicationClient::GetGDBServerProgramVersion() { @@ -1714,28 +1711,22 @@ lldb_private::Status GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction( bool &after, const ArchSpec &arch) { Status error; - llvm::Triple::ArchType atype = arch.GetMachine(); + llvm::Triple triple = arch.GetTriple(); // we assume watchpoints will happen after running the relevant opcode and we // only want to override this behavior if we have explicitly received a // qHostInfo telling us otherwise if (m_qHostInfo_is_valid != eLazyBoolYes) { - // On targets like MIPS and ppc64le, watchpoint exceptions are always + // On targets like MIPS and ppc64, watchpoint exceptions are always // generated before the instruction is executed. The connected target may // not support qHostInfo or qWatchpointSupportInfo packets. - after = - !(atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || - atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el || - atype == llvm::Triple::ppc64le); + after = !(triple.isMIPS() || triple.isPPC64()); } else { - // For MIPS and ppc64le, set m_watchpoints_trigger_after_instruction to + // For MIPS and ppc64, set m_watchpoints_trigger_after_instruction to // eLazyBoolNo if it is not calculated before. - if ((m_watchpoints_trigger_after_instruction == eLazyBoolCalculate && - (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || - atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el)) || - atype == llvm::Triple::ppc64le) { + if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate && + (triple.isMIPS() || triple.isPPC64())) m_watchpoints_trigger_after_instruction = eLazyBoolNo; - } after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo); } @@ -1747,7 +1738,7 @@ int GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) { std::string path{file_spec.GetPath(false)}; StreamString packet; packet.PutCString("QSetSTDIN:"); - packet.PutCStringAsRawHex8(path.c_str()); + packet.PutStringAsRawHex8(path); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == @@ -1767,7 +1758,7 @@ int GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec) { std::string path{file_spec.GetPath(false)}; StreamString packet; packet.PutCString("QSetSTDOUT:"); - packet.PutCStringAsRawHex8(path.c_str()); + packet.PutStringAsRawHex8(path); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == @@ -1787,7 +1778,7 @@ int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) { std::string path{file_spec.GetPath(false)}; StreamString packet; packet.PutCString("QSetSTDERR:"); - packet.PutCStringAsRawHex8(path.c_str()); + packet.PutStringAsRawHex8(path); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == @@ -1823,7 +1814,7 @@ int GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir) { std::string path{working_dir.GetPath(false)}; StreamString packet; packet.PutCString("QSetWorkingDir:"); - packet.PutCStringAsRawHex8(path.c_str()); + packet.PutStringAsRawHex8(path); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == @@ -2060,6 +2051,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat); assert(triple.getObjectFormat() != llvm::Triple::Wasm); + assert(triple.getObjectFormat() != llvm::Triple::XCOFF); switch (triple.getObjectFormat()) { case llvm::Triple::MachO: m_process_arch.SetArchitecture(eArchTypeMachO, cpu, sub); @@ -2071,6 +2063,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { m_process_arch.SetArchitecture(eArchTypeCOFF, cpu, sub); break; case llvm::Triple::Wasm: + case llvm::Triple::XCOFF: if (log) log->Printf("error: not supported target architecture"); return false; @@ -2793,7 +2786,7 @@ lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand( if (working_dir) { std::string path{working_dir.GetPath(false)}; stream.PutChar(','); - stream.PutCStringAsRawHex8(path.c_str()); + stream.PutStringAsRawHex8(path); } StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == @@ -2830,7 +2823,7 @@ Status GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec, stream.PutCString("qPlatform_mkdir:"); stream.PutHex32(file_permissions); stream.PutChar(','); - stream.PutCStringAsRawHex8(path.c_str()); + stream.PutStringAsRawHex8(path); llvm::StringRef packet = stream.GetString(); StringExtractorGDBRemote response; @@ -2852,7 +2845,7 @@ GDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec, stream.PutCString("qPlatform_chmod:"); stream.PutHex32(file_permissions); stream.PutChar(','); - stream.PutCStringAsRawHex8(path.c_str()); + stream.PutStringAsRawHex8(path); llvm::StringRef packet = stream.GetString(); StringExtractorGDBRemote response; @@ -2893,7 +2886,7 @@ GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec, stream.PutCString("vFile:open:"); if (path.empty()) return UINT64_MAX; - stream.PutCStringAsRawHex8(path.c_str()); + stream.PutStringAsRawHex8(path); stream.PutChar(','); stream.PutHex32(flags); stream.PutChar(','); @@ -2924,7 +2917,7 @@ lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize( std::string path(file_spec.GetPath(false)); lldb_private::StreamString stream; stream.PutCString("vFile:size:"); - stream.PutCStringAsRawHex8(path.c_str()); + stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { @@ -2943,7 +2936,7 @@ GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec, Status error; lldb_private::StreamString stream; stream.PutCString("vFile:mode:"); - stream.PutCStringAsRawHex8(path.c_str()); + stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { @@ -3045,9 +3038,9 @@ Status GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src, stream.PutCString("vFile:symlink:"); // the unix symlink() command reverses its parameters where the dst if first, // so we follow suit here - stream.PutCStringAsRawHex8(dst_path.c_str()); + stream.PutStringAsRawHex8(dst_path); stream.PutChar(','); - stream.PutCStringAsRawHex8(src_path.c_str()); + stream.PutStringAsRawHex8(src_path); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { @@ -3078,7 +3071,7 @@ Status GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) { stream.PutCString("vFile:unlink:"); // the unix symlink() command reverses its parameters where the dst if first, // so we follow suit here - stream.PutCStringAsRawHex8(path.c_str()); + stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { @@ -3108,7 +3101,7 @@ bool GDBRemoteCommunicationClient::GetFileExists( std::string path(file_spec.GetPath(false)); lldb_private::StreamString stream; stream.PutCString("vFile:exists:"); - stream.PutCStringAsRawHex8(path.c_str()); + stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { @@ -3127,7 +3120,7 @@ bool GDBRemoteCommunicationClient::CalculateMD5( std::string path(file_spec.GetPath(false)); lldb_private::StreamString stream; stream.PutCString("vFile:MD5:"); - stream.PutCStringAsRawHex8(path.c_str()); + stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { @@ -3508,10 +3501,10 @@ bool GDBRemoteCommunicationClient::GetModuleInfo( StreamString packet; packet.PutCString("qModuleInfo:"); - packet.PutCStringAsRawHex8(module_path.c_str()); + packet.PutStringAsRawHex8(module_path); packet.PutCString(";"); const auto &triple = arch_spec.GetTriple().getTriple(); - packet.PutCStringAsRawHex8(triple.c_str()); + packet.PutStringAsRawHex8(triple); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) != @@ -3955,7 +3948,7 @@ Status GDBRemoteCommunicationClient::SendSignalsToIgnore( } Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( - const ConstString &type_name, const StructuredData::ObjectSP &config_sp) { + ConstString type_name, const StructuredData::ObjectSP &config_sp) { Status error; if (type_name.GetLength() == 0) { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 37d53ab425f5..de85c9f8b67b 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationClient.h --------------------------*- 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 // //===----------------------------------------------------------------------===// @@ -18,12 +17,15 @@ #include <string> #include <vector> -#include "lldb/Target/Process.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StructuredData.h" +#if defined(_WIN32) +#include "lldb/Host/windows/PosixApi.h" +#endif #include "llvm/ADT/Optional.h" +#include "llvm/Support/VersionTuple.h" namespace lldb_private { namespace process_gdb_remote { @@ -34,10 +36,8 @@ public: ~GDBRemoteCommunicationClient() override; - //------------------------------------------------------------------ // After connecting, send the handshake to the server to make sure // we are communicating with it. - //------------------------------------------------------------------ bool HandshakeWithServer(Status *error_ptr); // For packets which specify a range of output to be returned, @@ -85,39 +85,35 @@ public: bool KillSpawnedProcess(lldb::pid_t pid); - //------------------------------------------------------------------ /// Sends a GDB remote protocol 'A' packet that delivers program /// arguments to the remote server. /// - /// @param[in] argv + /// \param[in] argv /// A NULL terminated array of const C strings to use as the /// arguments. /// - /// @return + /// \return /// Zero if the response was "OK", a positive value if the /// the response was "Exx" where xx are two hex digits, or /// -1 if the call is unsupported or any other unexpected /// response was received. - //------------------------------------------------------------------ int SendArgumentsPacket(const ProcessLaunchInfo &launch_info); - //------------------------------------------------------------------ /// Sends a "QEnvironment:NAME=VALUE" packet that will build up the /// environment that will get used when launching an application /// in conjunction with the 'A' packet. This function can be called /// multiple times in a row in order to pass on the desired /// environment that the inferior should be launched with. /// - /// @param[in] name_equal_value + /// \param[in] name_equal_value /// A NULL terminated C string that contains a single environment /// in the format "NAME=VALUE". /// - /// @return + /// \return /// Zero if the response was "OK", a positive value if the /// the response was "Exx" where xx are two hex digits, or /// -1 if the call is unsupported or any other unexpected /// response was received. - //------------------------------------------------------------------ int SendEnvironmentPacket(char const *name_equal_value); int SendEnvironment(const Environment &env); @@ -126,102 +122,88 @@ public: int SendLaunchEventDataPacket(const char *data, bool *was_supported = nullptr); - //------------------------------------------------------------------ /// Sends a "vAttach:PID" where PID is in hex. /// - /// @param[in] pid + /// \param[in] pid /// A process ID for the remote gdb server to attach to. /// - /// @param[out] response + /// \param[out] response /// The response received from the gdb server. If the return /// value is zero, \a response will contain a stop reply /// packet. /// - /// @return + /// \return /// Zero if the attach was successful, or an error indicating /// an error code. - //------------------------------------------------------------------ int SendAttach(lldb::pid_t pid, StringExtractorGDBRemote &response); - //------------------------------------------------------------------ /// Sends a GDB remote protocol 'I' packet that delivers stdin /// data to the remote process. /// - /// @param[in] data + /// \param[in] data /// A pointer to stdin data. /// - /// @param[in] data_len + /// \param[in] data_len /// The number of bytes available at \a data. /// - /// @return + /// \return /// Zero if the attach was successful, or an error indicating /// an error code. - //------------------------------------------------------------------ int SendStdinNotification(const char *data, size_t data_len); - //------------------------------------------------------------------ /// Sets the path to use for stdin/out/err for a process /// that will be launched with the 'A' packet. /// - /// @param[in] path + /// \param[in] path /// The path to use for stdin/out/err /// - /// @return + /// \return /// Zero if the for success, or an error code for failure. - //------------------------------------------------------------------ int SetSTDIN(const FileSpec &file_spec); int SetSTDOUT(const FileSpec &file_spec); int SetSTDERR(const FileSpec &file_spec); - //------------------------------------------------------------------ /// Sets the disable ASLR flag to \a enable for a process that will /// be launched with the 'A' packet. /// - /// @param[in] enable + /// \param[in] enable /// A boolean value indicating whether to disable ASLR or not. /// - /// @return + /// \return /// Zero if the for success, or an error code for failure. - //------------------------------------------------------------------ int SetDisableASLR(bool enable); - //------------------------------------------------------------------ /// Sets the DetachOnError flag to \a enable for the process controlled by the /// stub. /// - /// @param[in] enable + /// \param[in] enable /// A boolean value indicating whether to detach on error or not. /// - /// @return + /// \return /// Zero if the for success, or an error code for failure. - //------------------------------------------------------------------ int SetDetachOnError(bool enable); - //------------------------------------------------------------------ /// Sets the working directory to \a path for a process that will /// be launched with the 'A' packet for non platform based /// connections. If this packet is sent to a GDB server that /// implements the platform, it will change the current working /// directory for the platform process. /// - /// @param[in] working_dir + /// \param[in] working_dir /// The path to a directory to use when launching our process /// - /// @return + /// \return /// Zero if the for success, or an error code for failure. - //------------------------------------------------------------------ int SetWorkingDir(const FileSpec &working_dir); - //------------------------------------------------------------------ /// Gets the current working directory of a remote platform GDB /// server. /// - /// @param[out] working_dir + /// \param[out] working_dir /// The current working directory on the remote platform. /// - /// @return + /// \return /// Boolean for success - //------------------------------------------------------------------ bool GetWorkingDir(FileSpec &working_dir); lldb::addr_t AllocateMemory(size_t size, uint32_t permissions); @@ -456,21 +438,18 @@ public: // Sends QPassSignals packet to the server with given signals to ignore. Status SendSignalsToIgnore(llvm::ArrayRef<int32_t> signals); - //------------------------------------------------------------------ /// Return the feature set supported by the gdb-remote server. /// /// This method returns the remote side's response to the qSupported /// packet. The response is the complete string payload returned /// to the client. /// - /// @return + /// \return /// The string returned by the server to the qSupported query. - //------------------------------------------------------------------ const std::string &GetServerSupportedFeatures() const { return m_qSupported_response; } - //------------------------------------------------------------------ /// Return the array of async JSON packet types supported by the remote. /// /// This method returns the remote side's array of supported JSON @@ -486,18 +465,15 @@ public: /// A plugin indicates whether it knows how to handle a type_name. /// If so, it can be used to process the async JSON packet. /// - /// @return + /// \return /// The string returned by the server to the qSupported query. - //------------------------------------------------------------------ lldb_private::StructuredData::Array *GetSupportedStructuredDataPlugins(); - //------------------------------------------------------------------ /// Configure a StructuredData feature on the remote end. /// - /// @see \b Process::ConfigureStructuredData(...) for details. - //------------------------------------------------------------------ + /// \see \b Process::ConfigureStructuredData(...) for details. Status - ConfigureRemoteStructuredData(const ConstString &type_name, + ConfigureRemoteStructuredData(ConstString type_name, const StructuredData::ObjectSP &config_sp); lldb::user_id_t SendStartTracePacket(const TraceOptions &options, diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp index 69b13f2a3acb..bcddb4faf863 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationHistory.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 // //===----------------------------------------------------------------------===// @@ -46,7 +45,7 @@ void GDBRemoteCommunicationHistory::AddPacket(char packet_char, PacketType 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) + if (m_stream) m_packets[idx].Serialize(*m_stream); } @@ -63,7 +62,7 @@ void GDBRemoteCommunicationHistory::AddPacket(const std::string &src, 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) + if (m_stream) m_packets[idx].Serialize(*m_stream); } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h index d0ca6a0235c9..85f112b50623 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationHistory.h--------------------------*- 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 // //===----------------------------------------------------------------------===// diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp index 6a78eb20992e..417f5737a30f 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationReplayServer.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 // //===----------------------------------------------------------------------===// @@ -31,12 +30,49 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; +/// Check if the given expected packet matches the actual packet. +static bool unexpected(llvm::StringRef expected, llvm::StringRef actual) { + // The 'expected' string contains the raw data, including the leading $ and + // trailing checksum. The 'actual' string contains only the packet's content. + if (expected.contains(actual)) + return false; + // Contains a PID which might be different. + if (expected.contains("vAttach")) + return false; + // Contains a ascii-hex-path. + if (expected.contains("QSetSTD")) + return false; + // Contains environment values. + if (expected.contains("QEnvironment")) + return false; + + return true; +} + +/// Check if we should reply to the given packet. +static bool skip(llvm::StringRef data) { + assert(!data.empty() && "Empty packet?"); + + // We've already acknowledge the '+' packet so we're done here. + if (data == "+") + return true; + + /// Don't 't reply to ^C. We need this because of stop reply packets, which + /// are only returned when the target halts. Reproducers synchronize these + /// 'asynchronous' replies, by recording them as a regular replies to the + /// previous packet (e.g. vCont). As a result, we should ignore real + /// asynchronous requests. + if (data.data()[0] == 0x03) + return true; + + return false; +} + GDBRemoteCommunicationReplayServer::GDBRemoteCommunicationReplayServer() - : GDBRemoteCommunication("gdb-remote.server", - "gdb-remote.server.rx_packet"), - m_async_broadcaster(nullptr, "lldb.gdb-remote.server.async-broadcaster"), + : GDBRemoteCommunication("gdb-replay", "gdb-replay.rx_packet"), + m_async_broadcaster(nullptr, "lldb.gdb-replay.async-broadcaster"), m_async_listener_sp( - Listener::MakeListener("lldb.gdb-remote.server.async-listener")), + Listener::MakeListener("lldb.gdb-replay.async-listener")), m_async_thread_state_mutex(), m_skip_acks(false) { m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, "async thread continue"); @@ -56,6 +92,8 @@ GDBRemoteCommunicationReplayServer::~GDBRemoteCommunicationReplayServer() { GDBRemoteCommunication::PacketResult GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) { + std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); + StringExtractorGDBRemote packet; PacketResult packet_result = WaitForPacketNoLock(packet, timeout, false); @@ -71,32 +109,65 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( 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; + // Check if we should reply to this packet. + if (skip(packet.GetStringRef())) + return PacketResult::Success; + + // This completes the handshake. Since m_send_acks was true, we can unset it + // already. + if (packet.GetStringRef() == "QStartNoAckMode") m_send_acks = false; - } + // A QEnvironment packet is sent for every environment variable. If the + // number of environment variables is different during replay, the replies + // become out of sync. + if (packet.GetStringRef().find("QEnvironment") == 0) + return SendRawPacketNoLock("$OK#9a"); + + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); 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) + // We've handled the handshake implicitly before. Skip the packet and move + // on. + if (entry.packet.data == "+") + continue; + + if (entry.type == GDBRemoteCommunicationHistory::ePacketTypeSend) { + if (unexpected(entry.packet.data, packet.GetStringRef())) { + LLDB_LOG(log, + "GDBRemoteCommunicationReplayServer expected packet: '{0}'", + entry.packet.data); + LLDB_LOG(log, "GDBRemoteCommunicationReplayServer actual packet: '{0}'", + packet.GetStringRef()); + assert(false && "Encountered unexpected packet during replay"); + return PacketResult::ErrorSendFailed; + } + + // Ignore QEnvironment packets as they're handled earlier. + if (entry.packet.data.find("QEnvironment") == 1) { + assert(m_packet_history.back().type == + GDBRemoteCommunicationHistory::ePacketTypeRecv); + m_packet_history.pop_back(); + } + + continue; + } + + if (entry.type == GDBRemoteCommunicationHistory::ePacketTypeInvalid) { + LLDB_LOG( + log, + "GDBRemoteCommunicationReplayServer skipped invalid packet: '{0}'", + packet.GetStringRef()); continue; + } - return SendRawPacketNoLock(entry.packet.data, true); + LLDB_LOG(log, + "GDBRemoteCommunicationReplayServer replied to '{0}' with '{1}'", + packet.GetStringRef(), entry.packet.data); + return SendRawPacketNoLock(entry.packet.data); } quit = true; @@ -132,9 +203,16 @@ bool GDBRemoteCommunicationReplayServer::StartAsyncThread() { 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); + llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread( + "<lldb.gdb-replay.async>", + GDBRemoteCommunicationReplayServer::AsyncThread, this); + if (!async_thread) { + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + "failed to launch host thread: {}", + llvm::toString(async_thread.takeError())); + return false; + } + m_async_thread = *async_thread; } // Wait for handshake. diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h index 5b840c8459b7..26d65e265463 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationReplayServer.h --------------------*- 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 // //===----------------------------------------------------------------------===// diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 026f78117a0c..49cbeb023fd5 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationServer.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 // //===----------------------------------------------------------------------===// @@ -107,13 +106,29 @@ GDBRemoteCommunicationServer::SendErrorResponse(const Status &error) { if (m_send_error_strings) { lldb_private::StreamString packet; packet.Printf("E%2.2x;", static_cast<uint8_t>(error.GetError())); - packet.PutCStringAsRawHex8(error.AsCString()); + packet.PutStringAsRawHex8(error.AsCString()); return SendPacketNoLock(packet.GetString()); } else return SendErrorResponse(error.GetError()); } GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::SendErrorResponse(llvm::Error error) { + std::unique_ptr<llvm::ErrorInfoBase> EIB; + std::unique_ptr<PacketUnimplementedError> PUE; + llvm::handleAllErrors( + std::move(error), + [&](std::unique_ptr<PacketUnimplementedError> E) { PUE = std::move(E); }, + [&](std::unique_ptr<llvm::ErrorInfoBase> E) { EIB = std::move(E); }); + + if (EIB) + return SendErrorResponse(Status(llvm::Error(std::move(EIB)))); + if (PUE) + return SendUnimplementedResponse(PUE->message().c_str()); + return SendErrorResponse(Status("Unknown Error")); +} + +GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::Handle_QErrorStringEnable( StringExtractorGDBRemote &packet) { m_send_error_strings = true; @@ -139,3 +154,5 @@ GDBRemoteCommunicationServer::SendOKResponse() { bool GDBRemoteCommunicationServer::HandshakeWithClient() { return GetAck() == PacketResult::Success; } + +char PacketUnimplementedError::ID; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 082fb0d85424..86f0abf45e06 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationServer.h --------------------------*- 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 // //===----------------------------------------------------------------------===// @@ -16,6 +15,9 @@ #include "GDBRemoteCommunication.h" #include "lldb/lldb-private-forward.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" + class StringExtractorGDBRemote; namespace lldb_private { @@ -60,6 +62,8 @@ protected: PacketResult SendErrorResponse(const Status &error); + PacketResult SendErrorResponse(llvm::Error error); + PacketResult SendUnimplementedResponse(const char *packet); PacketResult SendErrorResponse(uint8_t error); @@ -73,6 +77,18 @@ private: DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServer); }; +class PacketUnimplementedError + : public llvm::ErrorInfo<PacketUnimplementedError, llvm::StringError> { +public: + static char ID; + using llvm::ErrorInfo<PacketUnimplementedError, + llvm::StringError>::ErrorInfo; // inherit constructors + PacketUnimplementedError(const llvm::Twine &S) + : ErrorInfo(S, llvm::errc::not_supported) {} + + PacketUnimplementedError() : ErrorInfo(llvm::errc::not_supported) {} +}; + } // namespace process_gdb_remote } // namespace lldb_private diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index f11ef4f1bbf8..d095c7a057ad 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationServerCommon.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 // //===----------------------------------------------------------------------===// @@ -11,7 +10,6 @@ #include <errno.h> - #ifdef __APPLE__ #include <TargetConditionals.h> #endif @@ -22,20 +20,20 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/Config.h" #include "lldb/Host/File.h" +#include "lldb/Host/FileAction.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" #include "lldb/Target/Platform.h" -#include "lldb/Target/Process.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/JSON.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StreamString.h" +#include "lldb/Utility/StructuredData.h" #include "llvm/ADT/Triple.h" #include "ProcessGDBRemoteLog.h" @@ -57,9 +55,7 @@ const static uint32_t g_default_packet_timeout_sec = 20; // seconds const static uint32_t g_default_packet_timeout_sec = 0; // not specified #endif -//---------------------------------------------------------------------- // GDBRemoteCommunicationServerCommon constructor -//---------------------------------------------------------------------- GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon( const char *comm_name, const char *listener_name) : GDBRemoteCommunicationServer(comm_name, listener_name), @@ -178,9 +174,7 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon( &GDBRemoteCommunicationServerCommon::Handle_vFile_unlink); } -//---------------------------------------------------------------------- // Destructor -//---------------------------------------------------------------------- GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() {} GDBRemoteCommunication::PacketResult @@ -193,13 +187,13 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( ArchSpec host_arch(HostInfo::GetArchitecture()); const llvm::Triple &host_triple = host_arch.GetTriple(); response.PutCString("triple:"); - response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); + response.PutStringAsRawHex8(host_triple.getTriple()); response.Printf(";ptrsize:%u;", host_arch.GetAddressByteSize()); const char *distribution_id = host_arch.GetDistributionId().AsCString(); if (distribution_id) { response.PutCString("distribution_id:"); - response.PutCStringAsRawHex8(distribution_id); + response.PutStringAsRawHex8(distribution_id); response.PutCString(";"); } @@ -215,8 +209,7 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( if (sub != LLDB_INVALID_CPUTYPE) response.Printf("cpusubtype:%u;", sub); - if (cpu == llvm::MachO::CPU_TYPE_ARM - || cpu == llvm::MachO::CPU_TYPE_ARM64) { + if (cpu == llvm::MachO::CPU_TYPE_ARM || cpu == llvm::MachO::CPU_TYPE_ARM64) { // Indicate the OS type. #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 response.PutCString("ostype:tvos;"); @@ -240,11 +233,7 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( if (host_arch.GetMachine() == llvm::Triple::aarch64 || host_arch.GetMachine() == llvm::Triple::aarch64_be || host_arch.GetMachine() == llvm::Triple::arm || - host_arch.GetMachine() == llvm::Triple::armeb || - host_arch.GetMachine() == llvm::Triple::mips64 || - host_arch.GetMachine() == llvm::Triple::mips64el || - host_arch.GetMachine() == llvm::Triple::mips || - host_arch.GetMachine() == llvm::Triple::mipsel) + host_arch.GetMachine() == llvm::Triple::armeb || host_arch.IsMIPS()) response.Printf("watchpoint_exceptions_received:before;"); else response.Printf("watchpoint_exceptions_received:after;"); @@ -274,12 +263,12 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( std::string s; if (HostInfo::GetOSBuildString(s)) { response.PutCString("os_build:"); - response.PutCStringAsRawHex8(s.c_str()); + response.PutStringAsRawHex8(s); response.PutChar(';'); } if (HostInfo::GetOSKernelDescription(s)) { response.PutCString("os_kernel:"); - response.PutCStringAsRawHex8(s.c_str()); + response.PutStringAsRawHex8(s); response.PutChar(';'); } @@ -290,12 +279,12 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( // actually have a hostname as far as the remote lldb that is connecting to // this lldb-platform is concerned response.PutCString("hostname:"); - response.PutCStringAsRawHex8("127.0.0.1"); + response.PutStringAsRawHex8("127.0.0.1"); response.PutChar(';'); #else // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) if (HostInfo::GetHostname(s)) { response.PutCString("hostname:"); - response.PutCStringAsRawHex8(s.c_str()); + response.PutStringAsRawHex8(s); response.PutChar(';'); } #endif // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) @@ -303,7 +292,7 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( #else // #if defined(__APPLE__) if (HostInfo::GetHostname(s)) { response.PutCString("hostname:"); - response.PutCStringAsRawHex8(s.c_str()); + response.PutStringAsRawHex8(s); response.PutChar(';'); } #endif // #if defined(__APPLE__) @@ -439,10 +428,10 @@ GDBRemoteCommunicationServerCommon::Handle_qUserName( packet.SetFilePos(::strlen("qUserName:")); uint32_t uid = packet.GetU32(UINT32_MAX); if (uid != UINT32_MAX) { - std::string name; - if (HostInfo::LookupUserName(uid, name)) { + if (llvm::Optional<llvm::StringRef> name = + HostInfo::GetUserIDResolver().GetUserName(uid)) { StreamString response; - response.PutCStringAsRawHex8(name.c_str()); + response.PutStringAsRawHex8(*name); return SendPacketNoLock(response.GetString()); } } @@ -460,10 +449,10 @@ GDBRemoteCommunicationServerCommon::Handle_qGroupName( packet.SetFilePos(::strlen("qGroupName:")); uint32_t gid = packet.GetU32(UINT32_MAX); if (gid != UINT32_MAX) { - std::string name; - if (HostInfo::LookupGroupName(gid, name)) { + if (llvm::Optional<llvm::StringRef> name = + HostInfo::GetUserIDResolver().GetGroupName(gid)) { StreamString response; - response.PutCStringAsRawHex8(name.c_str()); + response.PutStringAsRawHex8(*name); return SendPacketNoLock(response.GetString()); } } @@ -511,18 +500,19 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Open( packet.GetHexByteStringTerminatedBy(path, ','); if (!path.empty()) { if (packet.GetChar() == ',') { - uint32_t flags = - File::ConvertOpenOptionsForPOSIXOpen(packet.GetHexMaxU32(false, 0)); + uint32_t flags = packet.GetHexMaxU32(false, 0); if (packet.GetChar() == ',') { mode_t mode = packet.GetHexMaxU32(false, 0600); - Status error; 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; + File file; + // Do not close fd. + Status error = + FileSystem::Instance().Open(file, path_spec, flags, mode, false); + const int save_errno = error.GetError(); StreamString response; response.PutChar('F'); - response.Printf("%i", fd); + response.Printf("%i", file.GetDescriptor()); if (save_errno) response.Printf(",%i", save_errno); return SendPacketNoLock(response.GetString()); @@ -537,12 +527,13 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Close( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("vFile:close:")); int fd = packet.GetS32(-1); - Status error; int err = -1; int save_errno = 0; if (fd >= 0) { - err = close(fd); - save_errno = err == -1 ? errno : 0; + File file(fd, true); + Status error = file.Close(); + err = 0; + save_errno = error.GetError(); } else { save_errno = EINVAL; } @@ -557,26 +548,23 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Close( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_pRead( StringExtractorGDBRemote &packet) { -#ifdef _WIN32 - // Not implemented on Windows - return SendUnimplementedResponse( - "GDBRemoteCommunicationServerCommon::Handle_vFile_pRead() unimplemented"); -#else StreamGDBRemote response; packet.SetFilePos(::strlen("vFile:pread:")); int fd = packet.GetS32(-1); if (packet.GetChar() == ',') { - uint64_t count = packet.GetU64(UINT64_MAX); + size_t count = packet.GetU64(UINT64_MAX); if (packet.GetChar() == ',') { - uint64_t offset = packet.GetU64(UINT32_MAX); + off_t offset = packet.GetU64(UINT32_MAX); if (count == UINT64_MAX) { response.Printf("F-1:%i", EINVAL); return SendPacketNoLock(response.GetString()); } std::string buffer(count, 0); - const ssize_t bytes_read = ::pread(fd, &buffer[0], buffer.size(), offset); - const int save_errno = bytes_read == -1 ? errno : 0; + File file(fd, false); + Status error = file.Read(static_cast<void *>(&buffer[0]), count, offset); + const ssize_t bytes_read = error.Success() ? count : -1; + const int save_errno = error.GetError(); response.PutChar('F'); response.Printf("%zi", bytes_read); if (save_errno) @@ -589,17 +577,11 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_pRead( } } return SendErrorResponse(21); - -#endif } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite( StringExtractorGDBRemote &packet) { -#ifdef _WIN32 - return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_" - "vFile_pWrite() unimplemented"); -#else packet.SetFilePos(::strlen("vFile:pwrite:")); StreamGDBRemote response; @@ -611,9 +593,12 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite( if (packet.GetChar() == ',') { std::string buffer; if (packet.GetEscapedBinaryData(buffer)) { - const ssize_t bytes_written = - ::pwrite(fd, buffer.data(), buffer.size(), offset); - const int save_errno = bytes_written == -1 ? errno : 0; + File file(fd, false); + size_t count = buffer.size(); + Status error = + file.Write(static_cast<const void *>(&buffer[0]), count, offset); + const ssize_t bytes_written = error.Success() ? count : -1; + const int save_errno = error.GetError(); response.Printf("%zi", bytes_written); if (save_errno) response.Printf(",%i", save_errno); @@ -624,7 +609,6 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite( } } return SendErrorResponse(27); -#endif } GDBRemoteCommunication::PacketResult @@ -972,7 +956,8 @@ GDBRemoteCommunicationServerCommon::Handle_QLaunchArch( const uint32_t bytes_left = packet.GetBytesLeft(); if (bytes_left > 0) { const char *arch_triple = packet.Peek(); - m_process_launch_info.SetArchitecture(HostInfo::GetAugmentedArchSpec(arch_triple)); + m_process_launch_info.SetArchitecture( + HostInfo::GetAugmentedArchSpec(arch_triple)); return SendOKResponse(); } return SendErrorResponse(13); @@ -1086,24 +1071,25 @@ GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( StreamGDBRemote response; if (uuid_str.empty()) { - auto Result = llvm::sys::fs::md5_contents(matched_module_spec.GetFileSpec().GetPath()); + auto Result = llvm::sys::fs::md5_contents( + matched_module_spec.GetFileSpec().GetPath()); if (!Result) return SendErrorResponse(5); response.PutCString("md5:"); - response.PutCStringAsRawHex8(Result->digest().c_str()); + response.PutStringAsRawHex8(Result->digest()); } else { response.PutCString("uuid:"); - response.PutCStringAsRawHex8(uuid_str.c_str()); + response.PutStringAsRawHex8(uuid_str); } response.PutChar(';'); const auto &module_arch = matched_module_spec.GetArchitecture(); response.PutCString("triple:"); - response.PutCStringAsRawHex8(module_arch.GetTriple().getTriple().c_str()); + response.PutStringAsRawHex8(module_arch.GetTriple().getTriple()); response.PutChar(';'); response.PutCString("file_path:"); - response.PutCStringAsRawHex8(matched_module_spec.GetFileSpec().GetCString()); + response.PutStringAsRawHex8(matched_module_spec.GetFileSpec().GetCString()); response.PutChar(';'); response.PutCString("file_offset:"); response.PutHex64(file_offset); @@ -1181,13 +1167,13 @@ void GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse( proc_info.GetUserID(), proc_info.GetGroupID(), proc_info.GetEffectiveUserID(), proc_info.GetEffectiveGroupID()); response.PutCString("name:"); - response.PutCStringAsRawHex8(proc_info.GetExecutableFile().GetCString()); + response.PutStringAsRawHex8(proc_info.GetExecutableFile().GetCString()); response.PutChar(';'); const ArchSpec &proc_arch = proc_info.GetArchitecture(); if (proc_arch.IsValid()) { const llvm::Triple &proc_triple = proc_arch.GetTriple(); response.PutCString("triple:"); - response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); + response.PutStringAsRawHex8(proc_triple.getTriple()); response.PutChar(';'); } } @@ -1221,7 +1207,7 @@ void GDBRemoteCommunicationServerCommon:: #else // We'll send the triple. response.PutCString("triple:"); - response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); + response.PutStringAsRawHex8(proc_triple.getTriple()); response.PutChar(';'); #endif std::string ostype = proc_triple.getOSName(); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h index f3825bb36791..525546312470 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationServerCommon.h --------------------*- 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 // //===----------------------------------------------------------------------===// @@ -12,7 +11,7 @@ #include <string> -#include "lldb/Target/Process.h" +#include "lldb/Host/ProcessLaunchInfo.h" #include "lldb/lldb-private-forward.h" #include "GDBRemoteCommunicationServer.h" @@ -132,17 +131,15 @@ protected: }); } - //------------------------------------------------------------------ /// Launch a process with the current launch settings. /// /// This method supports running an lldb-gdbserver or similar /// server in a situation where the startup code has been provided /// with all the information for a child process to be launched. /// - /// @return + /// \return /// An Status object indicating the success or failure of the /// launch. - //------------------------------------------------------------------ virtual Status LaunchProcess() = 0; virtual FileSpec FindModuleFile(const std::string &module_path, diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index cdb63e72f6bd..196607665bba 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationServerLLGS.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 // //===----------------------------------------------------------------------===// @@ -21,6 +20,7 @@ #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Debug.h" #include "lldb/Host/File.h" +#include "lldb/Host/FileAction.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" @@ -28,7 +28,6 @@ #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/common/NativeThreadProtocol.h" -#include "lldb/Target/FileAction.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Utility/Args.h" #include "lldb/Utility/DataBuffer.h" @@ -52,9 +51,7 @@ using namespace lldb_private; using namespace lldb_private::process_gdb_remote; using namespace llvm; -//---------------------------------------------------------------------- // GDBRemote Errors -//---------------------------------------------------------------------- namespace { enum GDBRemoteServerError { @@ -66,9 +63,7 @@ enum GDBRemoteServerError { }; } -//---------------------------------------------------------------------- // GDBRemoteCommunicationServerLLGS constructor -//---------------------------------------------------------------------- GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory) : GDBRemoteCommunicationServerCommon("gdb-remote.server", @@ -149,8 +144,8 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo, &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo); RegisterMemberFunctionHandler( - StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read, - &GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read); + StringExtractorGDBRemote::eServerPacketType_qXfer, + &GDBRemoteCommunicationServerLLGS::Handle_qXfer); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_s, &GDBRemoteCommunicationServerLLGS::Handle_s); RegisterMemberFunctionHandler( @@ -192,6 +187,9 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead, &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g, + &GDBRemoteCommunicationServerLLGS::Handle_g); + RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k, [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt, bool &quit) { @@ -623,7 +621,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( } else { // The thread name contains special chars, send as hex bytes. response.PutCString("hexname:"); - response.PutCStringAsRawHex8(thread_name.c_str()); + response.PutStringAsRawHex8(thread_name); } response.PutChar(';'); } @@ -663,7 +661,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( response.PutCString("jstopinfo:"); StreamString unescaped_response; threads_info_sp->Write(unescaped_response); - response.PutCStringAsRawHex8(unescaped_response.GetData()); + response.PutStringAsRawHex8(unescaped_response.GetData()); response.PutChar(';'); } else LLDB_LOG(log, "failed to prepare a jstopinfo field for pid {0}", @@ -764,7 +762,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( if (!description.empty()) { // Description may contains special chars, send as hex bytes. response.PutCString("description:"); - response.PutCStringAsRawHex8(description.c_str()); + response.PutStringAsRawHex8(description); response.PutChar(';'); } else if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) { @@ -1341,7 +1339,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir( FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()}; if (working_dir) { StreamString response; - response.PutCStringAsRawHex8(working_dir.GetCString()); + response.PutStringAsRawHex8(working_dir.GetCString()); return SendPacketNoLock(response.GetString()); } @@ -1897,6 +1895,61 @@ GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo( } GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_g(StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + // Move past packet name. + packet.SetFilePos(strlen("g")); + + // Get the thread to use. + NativeThreadProtocol *thread = GetThreadFromSuffix(packet); + if (!thread) { + LLDB_LOG(log, "failed, no thread available"); + return SendErrorResponse(0x15); + } + + // Get the thread's register context. + NativeRegisterContext ®_ctx = thread->GetRegisterContext(); + + std::vector<uint8_t> regs_buffer; + for (uint32_t reg_num = 0; reg_num < reg_ctx.GetUserRegisterCount(); + ++reg_num) { + const RegisterInfo *reg_info = reg_ctx.GetRegisterInfoAtIndex(reg_num); + + if (reg_info == nullptr) { + LLDB_LOG(log, "failed to get register info for register index {0}", + reg_num); + return SendErrorResponse(0x15); + } + + if (reg_info->value_regs != nullptr) + continue; // skip registers that are contained in other registers + + RegisterValue reg_value; + Status error = reg_ctx.ReadRegister(reg_info, reg_value); + if (error.Fail()) { + LLDB_LOG(log, "failed to read register at index {0}", reg_num); + return SendErrorResponse(0x15); + } + + if (reg_info->byte_offset + reg_info->byte_size >= regs_buffer.size()) + // Resize the buffer to guarantee it can store the register offsetted + // data. + regs_buffer.resize(reg_info->byte_offset + reg_info->byte_size); + + // Copy the register offsetted data to the buffer. + memcpy(regs_buffer.data() + reg_info->byte_offset, reg_value.GetBytes(), + reg_info->byte_size); + } + + // Write the response. + StreamGDBRemote response; + response.PutBytesAsRawHex8(regs_buffer.data(), regs_buffer.size()); + + return SendPacketNoLock(response.GetString()); +} + +GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); @@ -2426,7 +2479,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( // Return the error message. response.PutCString("error:"); - response.PutCStringAsRawHex8(error.AsCString()); + response.PutStringAsRawHex8(error.AsCString()); response.PutChar(';'); } else { // Range start and size. @@ -2454,7 +2507,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( ConstString name = region_info.GetName(); if (name) { response.PutCString("name:"); - response.PutCStringAsRawHex8(name.AsCString()); + response.PutStringAsRawHex8(name.AsCString()); response.PutChar(';'); } } @@ -2694,94 +2747,99 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { return PacketResult::Success; } -GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read( - StringExtractorGDBRemote &packet) { -// *BSD impls should be able to do this too. -#if defined(__linux__) || defined(__NetBSD__) - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - - // Parse out the offset. - packet.SetFilePos(strlen("qXfer:auxv:read::")); - if (packet.GetBytesLeft() < 1) - return SendIllFormedResponse(packet, - "qXfer:auxv:read:: packet missing offset"); - - const uint64_t auxv_offset = - packet.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max()); - if (auxv_offset == std::numeric_limits<uint64_t>::max()) - return SendIllFormedResponse(packet, - "qXfer:auxv:read:: packet missing offset"); - - // Parse out comma. - if (packet.GetBytesLeft() < 1 || packet.GetChar() != ',') - return SendIllFormedResponse( - packet, "qXfer:auxv:read:: packet missing comma after offset"); - - // Parse out the length. - const uint64_t auxv_length = - packet.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max()); - if (auxv_length == std::numeric_limits<uint64_t>::max()) - return SendIllFormedResponse(packet, - "qXfer:auxv:read:: packet missing length"); - - // Grab the auxv data if we need it. - if (!m_active_auxv_buffer_up) { +llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> +GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object, + llvm::StringRef annex) { + if (object == "auxv") { // Make sure we have a valid process. if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); - return SendErrorResponse(0x10); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "No process available"); } // Grab the auxv data. auto buffer_or_error = m_debugged_process_up->GetAuxvData(); - if (!buffer_or_error) { - std::error_code ec = buffer_or_error.getError(); - LLDB_LOG(log, "no auxv data retrieved: {0}", ec.message()); - return SendErrorResponse(ec.value()); - } - m_active_auxv_buffer_up = std::move(*buffer_or_error); + if (!buffer_or_error) + return llvm::errorCodeToError(buffer_or_error.getError()); + return std::move(*buffer_or_error); } + return llvm::make_error<PacketUnimplementedError>( + "Xfer object not supported"); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_qXfer( + StringExtractorGDBRemote &packet) { + SmallVector<StringRef, 5> fields; + // The packet format is "qXfer:<object>:<action>:<annex>:offset,length" + StringRef(packet.GetStringRef()).split(fields, ':', 4); + if (fields.size() != 5) + return SendIllFormedResponse(packet, "malformed qXfer packet"); + StringRef &xfer_object = fields[1]; + StringRef &xfer_action = fields[2]; + StringRef &xfer_annex = fields[3]; + StringExtractor offset_data(fields[4]); + if (xfer_action != "read") + return SendUnimplementedResponse("qXfer action not supported"); + // Parse offset. + const uint64_t xfer_offset = + offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max()); + if (xfer_offset == std::numeric_limits<uint64_t>::max()) + return SendIllFormedResponse(packet, "qXfer packet missing offset"); + // Parse out comma. + if (offset_data.GetChar() != ',') + return SendIllFormedResponse(packet, + "qXfer packet missing comma after offset"); + // Parse out the length. + const uint64_t xfer_length = + offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max()); + if (xfer_length == std::numeric_limits<uint64_t>::max()) + return SendIllFormedResponse(packet, "qXfer packet missing length"); + + // Get a previously constructed buffer if it exists or create it now. + std::string buffer_key = (xfer_object + xfer_action + xfer_annex).str(); + auto buffer_it = m_xfer_buffer_map.find(buffer_key); + if (buffer_it == m_xfer_buffer_map.end()) { + auto buffer_up = ReadXferObject(xfer_object, xfer_annex); + if (!buffer_up) + return SendErrorResponse(buffer_up.takeError()); + buffer_it = m_xfer_buffer_map + .insert(std::make_pair(buffer_key, std::move(*buffer_up))) + .first; + } + + // Send back the response StreamGDBRemote response; bool done_with_buffer = false; - - llvm::StringRef buffer = m_active_auxv_buffer_up->getBuffer(); - if (auxv_offset >= buffer.size()) { + llvm::StringRef buffer = buffer_it->second->getBuffer(); + if (xfer_offset >= buffer.size()) { // We have nothing left to send. Mark the buffer as complete. response.PutChar('l'); done_with_buffer = true; } else { // Figure out how many bytes are available starting at the given offset. - buffer = buffer.drop_front(auxv_offset); - + buffer = buffer.drop_front(xfer_offset); // Mark the response type according to whether we're reading the remainder - // of the auxv data. - if (auxv_length >= buffer.size()) { + // of the data. + if (xfer_length >= buffer.size()) { // There will be nothing left to read after this response.PutChar('l'); done_with_buffer = true; } else { // There will still be bytes to read after this request. response.PutChar('m'); - buffer = buffer.take_front(auxv_length); + buffer = buffer.take_front(xfer_length); } - // Now write the data in encoded binary form. response.PutEscapedBytes(buffer.data(), buffer.size()); } if (done_with_buffer) - m_active_auxv_buffer_up.reset(); + m_xfer_buffer_map.erase(buffer_it); return SendPacketNoLock(response.GetString()); -#else - return SendUnimplementedResponse("not implemented on this platform"); -#endif } GDBRemoteCommunication::PacketResult @@ -3206,8 +3264,8 @@ uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() { void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - LLDB_LOG(log, "clearing auxv buffer: {0}", m_active_auxv_buffer_up.get()); - m_active_auxv_buffer_up.reset(); + LLDB_LOG(log, "clearing {0} xfer buffers", m_xfer_buffer_map.size()); + m_xfer_buffer_map.clear(); } FileSpec diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index a085a3cc17dd..068ea52caaaf 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationServerLLGS.h ----------------------*- 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 // //===----------------------------------------------------------------------===// @@ -32,43 +31,35 @@ class GDBRemoteCommunicationServerLLGS : public GDBRemoteCommunicationServerCommon, public NativeProcessProtocol::NativeDelegate { public: - //------------------------------------------------------------------ // Constructors and Destructors - //------------------------------------------------------------------ GDBRemoteCommunicationServerLLGS( MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory); void SetLaunchInfo(const ProcessLaunchInfo &info); - //------------------------------------------------------------------ /// Launch a process with the current launch settings. /// /// This method supports running an lldb-gdbserver or similar /// server in a situation where the startup code has been provided /// with all the information for a child process to be launched. /// - /// @return + /// \return /// An Status object indicating the success or failure of the /// launch. - //------------------------------------------------------------------ Status LaunchProcess() override; - //------------------------------------------------------------------ /// Attach to a process. /// /// This method supports attaching llgs to a process accessible via the /// configured Platform. /// - /// @return + /// \return /// An Status object indicating the success or failure of the /// attach operation. - //------------------------------------------------------------------ Status AttachToProcess(lldb::pid_t pid); - //------------------------------------------------------------------ // NativeProcessProtocol::NativeDelegate overrides - //------------------------------------------------------------------ void InitializeDelegate(NativeProcessProtocol *process) override; void ProcessStateChanged(NativeProcessProtocol *process, @@ -91,7 +82,7 @@ protected: MainLoop::ReadHandleUP m_stdio_handle_up; lldb::StateType m_inferior_prev_state = lldb::StateType::eStateInvalid; - std::unique_ptr<llvm::MemoryBuffer> m_active_auxv_buffer_up; + llvm::StringMap<std::unique_ptr<llvm::MemoryBuffer>> m_xfer_buffer_map; std::mutex m_saved_registers_mutex; std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map; uint32_t m_next_saved_registers_id = 1; @@ -159,7 +150,7 @@ protected: PacketResult Handle_s(StringExtractorGDBRemote &packet); - PacketResult Handle_qXfer_auxv_read(StringExtractorGDBRemote &packet); + PacketResult Handle_qXfer(StringExtractorGDBRemote &packet); PacketResult Handle_QSaveRegisterState(StringExtractorGDBRemote &packet); @@ -187,6 +178,8 @@ protected: PacketResult Handle_QPassSignals(StringExtractorGDBRemote &packet); + PacketResult Handle_g(StringExtractorGDBRemote &packet); + void SetCurrentThreadID(lldb::tid_t tid); lldb::tid_t GetCurrentThreadID() const; @@ -200,6 +193,9 @@ protected: FileSpec FindModuleFile(const std::string &module_path, const ArchSpec &arch) override; + llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> + ReadXferObject(llvm::StringRef object, llvm::StringRef annex); + private: void HandleInferiorState_Exited(NativeProcessProtocol *process); @@ -223,9 +219,7 @@ private: void StopSTDIOForwarding(); - //------------------------------------------------------------------ // For GDBRemoteCommunicationServerLLGS only - //------------------------------------------------------------------ DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServerLLGS); }; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 3521ddafbb16..6deb75f2f021 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationServerPlatform.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 // //===----------------------------------------------------------------------===// @@ -22,11 +21,10 @@ #include "lldb/Host/Config.h" #include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/FileAction.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" -#include "lldb/Target/Process.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/JSON.h" #include "lldb/Utility/Log.h" @@ -41,9 +39,7 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; -//---------------------------------------------------------------------- // GDBRemoteCommunicationServerPlatform constructor -//---------------------------------------------------------------------- GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform( const Socket::SocketProtocol socket_protocol, const char *socket_scheme) : GDBRemoteCommunicationServerCommon("gdb-remote.server", @@ -87,9 +83,7 @@ GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform( }); } -//---------------------------------------------------------------------- // Destructor -//---------------------------------------------------------------------- GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() {} Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer( @@ -121,25 +115,24 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer( this, std::placeholders::_1), false); - llvm::StringRef platform_scheme; - llvm::StringRef platform_ip; - int platform_port; - llvm::StringRef platform_path; - std::string platform_uri = GetConnection()->GetURI(); - bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip, - platform_port, platform_path); - UNUSED_IF_ASSERT_DISABLED(ok); - assert(ok); - std::ostringstream url; // debugserver does not accept the URL scheme prefix. #if !defined(__APPLE__) url << m_socket_scheme << "://"; #endif uint16_t *port_ptr = &port; - if (m_socket_protocol == Socket::ProtocolTcp) + if (m_socket_protocol == Socket::ProtocolTcp) { + llvm::StringRef platform_scheme; + llvm::StringRef platform_ip; + int platform_port; + llvm::StringRef platform_path; + std::string platform_uri = GetConnection()->GetURI(); + bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip, + platform_port, platform_path); + UNUSED_IF_ASSERT_DISABLED(ok); + assert(ok); url << platform_ip.str() << ":" << port; - else { + } else { socket_name = GetDomainSocketPath("gdbserver").GetPath(); url << socket_name; port_ptr = nullptr; @@ -207,7 +200,7 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( port + m_port_offset); if (!socket_name.empty()) { response.PutCString("socket_name:"); - response.PutCStringAsRawHex8(socket_name.c_str()); + response.PutStringAsRawHex8(socket_name); response.PutChar(';'); } @@ -399,7 +392,7 @@ GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo( StringExtractorGDBRemote &packet) { StructuredData::Array signal_array; - const auto &signals = Host::GetUnixSignals(); + lldb::UnixSignalsSP signals = UnixSignals::CreateForHost(); for (auto signo = signals->GetFirstSignalNumber(); signo != LLDB_INVALID_SIGNAL_NUMBER; signo = signals->GetNextSignalNumber(signo)) { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index df51e0367d1d..eacc99a012db 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -1,9 +1,8 @@ //===-- GDBRemoteCommunicationServerPlatform.h ------------------*- 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 // //===----------------------------------------------------------------------===// @@ -36,7 +35,6 @@ public: // a port chosen by the OS. void SetPortMap(PortMap &&port_map); - //---------------------------------------------------------------------- // If we are using a port map where we can only use certain ports, // get the next available port. // @@ -44,7 +42,6 @@ public: // // If we aren't using a port map, return 0 to indicate we should bind to // port 0 and then figure out which port we used. - //---------------------------------------------------------------------- uint16_t GetNextAvailablePort(); bool AssociatePortWithProcess(uint16_t port, lldb::pid_t pid); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index e58f47f4befe..a77e659a55fa 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -1,9 +1,8 @@ //===-- GDBRemoteRegisterContext.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 // //===----------------------------------------------------------------------===// @@ -23,13 +22,13 @@ #include "Utility/ARM_ehframe_Registers.h" #include "lldb/Utility/StringExtractorGDBRemote.h" +#include <memory> + using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; -//---------------------------------------------------------------------- // GDBRemoteRegisterContext constructor -//---------------------------------------------------------------------- GDBRemoteRegisterContext::GDBRemoteRegisterContext( ThreadGDBRemote &thread, uint32_t concrete_frame_idx, GDBRemoteDynamicRegisterInfo ®_info, bool read_all_at_once) @@ -47,9 +46,7 @@ GDBRemoteRegisterContext::GDBRemoteRegisterContext( m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder()); } -//---------------------------------------------------------------------- // Destructor -//---------------------------------------------------------------------- GDBRemoteRegisterContext::~GDBRemoteRegisterContext() {} void GDBRemoteRegisterContext::InvalidateAllRegisters() { @@ -101,7 +98,7 @@ bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info, bool GDBRemoteRegisterContext::PrivateSetRegisterValue( uint32_t reg, llvm::ArrayRef<uint8_t> data) { const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info == NULL) + if (reg_info == nullptr) return false; // Invalidate if needed @@ -125,7 +122,7 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue( bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg, uint64_t new_reg_val) { const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info == NULL) + if (reg_info == nullptr) return false; // Early in process startup, we can get a thread that has an invalid byte @@ -151,7 +148,7 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg, uint8_t *dst = const_cast<uint8_t *>( m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size)); - if (dst == NULL) + if (dst == nullptr) return false; if (data.CopyByteOrderedData(0, // src offset @@ -186,7 +183,7 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) + if (process == nullptr || thread == nullptr) return false; GDBRemoteCommunicationClient &gdb_comm( @@ -206,6 +203,14 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, if (buffer_sp->GetByteSize() >= m_reg_data.GetByteSize()) { SetAllRegisterValid(true); return true; + } else { + Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD | + GDBR_LOG_PACKETS)); + if (log) + log->Printf ("error: GDBRemoteRegisterContext::ReadRegisterBytes tried to read the " + "entire register context at once, expected at least %" PRId64 " bytes " + "but only got %" PRId64 " bytes.", m_reg_data.GetByteSize(), + buffer_sp->GetByteSize()); } } return false; @@ -223,7 +228,7 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, // We have a valid primordial register as our constituent. Grab the // corresponding register info. const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg); - if (prim_reg_info == NULL) + if (prim_reg_info == nullptr) success = false; else { // Read the containing register if it hasn't already been read @@ -248,10 +253,8 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, } if (&data != &m_reg_data) { -#if defined(LLDB_CONFIGURATION_DEBUG) assert(m_reg_data.GetByteSize() >= reg_info->byte_offset + reg_info->byte_size); -#endif // If our register context and our register info disagree, which should // never happen, don't read past the end of the buffer. if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size) @@ -298,16 +301,14 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) + if (process == nullptr || thread == nullptr) return false; GDBRemoteCommunicationClient &gdb_comm( ((ProcessGDBRemote *)process)->GetGDBRemote()); -#if defined(LLDB_CONFIGURATION_DEBUG) assert(m_reg_data.GetByteSize() >= reg_info->byte_offset + reg_info->byte_size); -#endif // If our register context and our register info disagree, which should never // happen, don't overwrite past the end of the buffer. @@ -318,7 +319,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, uint8_t *dst = const_cast<uint8_t *>( m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size)); - if (dst == NULL) + if (dst == nullptr) return false; if (data.CopyByteOrderedData(data_offset, // src offset @@ -360,7 +361,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, // We have a valid primordial register as our constituent. Grab the // corresponding register info. const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg); - if (value_reg_info == NULL) + if (value_reg_info == nullptr) success = false; else success = SetPrimordialRegister(value_reg_info, gdb_comm); @@ -408,7 +409,7 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) + if (process == nullptr || thread == nullptr) return false; GDBRemoteCommunicationClient &gdb_comm( @@ -433,7 +434,7 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) + if (process == nullptr || thread == nullptr) return false; GDBRemoteCommunicationClient &gdb_comm( @@ -451,7 +452,7 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) + if (process == nullptr || thread == nullptr) return false; GDBRemoteCommunicationClient &gdb_comm( @@ -473,7 +474,8 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( // individually and store them as binary data in a buffer. const RegisterInfo *reg_info; - for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != NULL; i++) { + for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != nullptr; + i++) { if (reg_info ->value_regs) // skip registers that are slices of real registers continue; @@ -481,8 +483,8 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( // ReadRegisterBytes saves the contents of the register in to the // m_reg_data buffer } - data_sp.reset(new DataBufferHeap(m_reg_data.GetDataStart(), - m_reg_info.GetRegisterDataByteSize())); + data_sp = std::make_shared<DataBufferHeap>( + m_reg_data.GetDataStart(), m_reg_info.GetRegisterDataByteSize()); return true; } else { @@ -507,14 +509,14 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( bool GDBRemoteRegisterContext::WriteAllRegisterValues( const lldb::DataBufferSP &data_sp) { - if (!data_sp || data_sp->GetBytes() == NULL || data_sp->GetByteSize() == 0) + if (!data_sp || data_sp->GetBytes() == nullptr || data_sp->GetByteSize() == 0) return false; ExecutionContext exe_ctx(CalculateThread()); Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) + if (process == nullptr || thread == nullptr) return false; GDBRemoteCommunicationClient &gdb_comm( @@ -556,9 +558,9 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( uint64_t size_by_highest_offset = 0; for (uint32_t reg_idx = 0; - (reg_info = GetRegisterInfoAtIndex(reg_idx)) != NULL; ++reg_idx) { + (reg_info = GetRegisterInfoAtIndex(reg_idx)) != nullptr; ++reg_idx) { size_including_slice_registers += reg_info->byte_size; - if (reg_info->value_regs == NULL) + if (reg_info->value_regs == nullptr) size_not_including_slice_registers += reg_info->byte_size; if (reg_info->byte_offset >= size_by_highest_offset) size_by_highest_offset = reg_info->byte_offset + reg_info->byte_size; @@ -590,7 +592,7 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( // keep track of the size of each reg & compute offset based on that. uint32_t running_byte_offset = 0; for (uint32_t reg_idx = 0; - (reg_info = GetRegisterInfoAtIndex(reg_idx)) != NULL; + (reg_info = GetRegisterInfoAtIndex(reg_idx)) != nullptr; ++reg_idx, running_byte_offset += reg_info->byte_size) { // Skip composite aka slice registers (e.g. eax is a slice of rax). if (reg_info->value_regs) @@ -636,7 +638,7 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( } uint32_t num_restored = 0; const RegisterInfo *reg_info; - for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != NULL; + for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != nullptr; i++) { if (reg_info->value_regs) // skip registers that are slices of real // registers diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h index 6e8f3306669f..25e9b716f8cb 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -1,9 +1,8 @@ //===-- GDBRemoteRegisterContext.h ------------------------------*- 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 // //===----------------------------------------------------------------------===// diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 797f63d537a1..a6fdd8dd0707 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1,9 +1,8 @@ //===-- ProcessGDBRemote.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 // //===----------------------------------------------------------------------===// @@ -24,6 +23,7 @@ #include <algorithm> #include <csignal> #include <map> +#include <memory> #include <mutex> #include <sstream> @@ -41,7 +41,6 @@ #include "lldb/Host/PosixApi.h" #include "lldb/Host/PseudoTerminal.h" #include "lldb/Host/StringConvert.h" -#include "lldb/Host/Symbols.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/XML.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -54,6 +53,7 @@ #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/Property.h" +#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" @@ -111,12 +111,40 @@ void DumpProcessGDBRemotePacketHistory(void *p, const char *path) { namespace { static constexpr PropertyDefinition g_properties[] = { - {"packet-timeout", OptionValue::eTypeUInt64, true, 1, NULL, {}, + {"packet-timeout", + OptionValue::eTypeUInt64, + true, + 5 +#if defined(__has_feature) +#if __has_feature(address_sanitizer) + * 2 +#endif +#endif + , + nullptr, + {}, "Specify the default packet timeout in seconds."}, - {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, NULL, {}, - "The file that provides the description for remote target registers."}}; - -enum { ePropertyPacketTimeout, ePropertyTargetDefinitionFile }; + {"target-definition-file", + OptionValue::eTypeFileSpec, + true, + 0, + nullptr, + {}, + "The file that provides the description for remote target registers."}, + {"use-libraries-svr4", + OptionValue::eTypeBoolean, + true, + false, + nullptr, + {}, + "If true, the libraries-svr4 feature will be used to get a hold of the " + "process's loaded modules."}}; + +enum { + ePropertyPacketTimeout, + ePropertyTargetDefinitionFile, + ePropertyUseSVR4 +}; class PluginProperties : public Properties { public: @@ -125,26 +153,32 @@ public: } PluginProperties() : Properties() { - m_collection_sp.reset(new OptionValueProperties(GetSettingName())); + m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); m_collection_sp->Initialize(g_properties); } - virtual ~PluginProperties() {} + ~PluginProperties() override {} uint64_t GetPacketTimeout() { const uint32_t idx = ePropertyPacketTimeout; return m_collection_sp->GetPropertyAtIndexAsUInt64( - NULL, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_properties[idx].default_uint_value); } bool SetPacketTimeout(uint64_t timeout) { const uint32_t idx = ePropertyPacketTimeout; - return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout); + return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, timeout); } FileSpec GetTargetDefinitionFile() const { const uint32_t idx = ePropertyTargetDefinitionFile; - return m_collection_sp->GetPropertyAtIndexAsFileSpec(NULL, idx); + return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx); + } + + bool GetUseSVR4() const { + const uint32_t idx = ePropertyUseSVR4; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); } }; @@ -153,25 +187,27 @@ typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { static ProcessKDPPropertiesSP g_settings_sp; if (!g_settings_sp) - g_settings_sp.reset(new PluginProperties()); + g_settings_sp = std::make_shared<PluginProperties>(); return g_settings_sp; } class ProcessGDBRemoteProvider : public repro::Provider<ProcessGDBRemoteProvider> { public: + struct Info { + static const char *name; + static const char *file; + }; + 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"); + FileSpec history_file = GetRoot().CopyByAppendingPathComponent(Info::file); std::error_code EC; m_stream_up = llvm::make_unique<raw_fd_ostream>(history_file.GetPath(), EC, - sys::fs::OpenFlags::F_None); + sys::fs::OpenFlags::F_Text); return m_stream_up.get(); } @@ -191,6 +227,8 @@ private: }; char ProcessGDBRemoteProvider::ID = 0; +const char *ProcessGDBRemoteProvider::Info::name = "gdb-remote"; +const char *ProcessGDBRemoteProvider::Info::file = "gdb-remote.yaml"; } // namespace @@ -239,8 +277,8 @@ ProcessGDBRemote::CreateInstance(lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec *crash_file_path) { lldb::ProcessSP process_sp; - if (crash_file_path == NULL) - process_sp.reset(new ProcessGDBRemote(target_sp, listener_sp)); + if (crash_file_path == nullptr) + process_sp = std::make_shared<ProcessGDBRemote>(target_sp, listener_sp); return process_sp; } @@ -275,15 +313,13 @@ bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp, return true; } -//---------------------------------------------------------------------- // ProcessGDBRemote constructor -//---------------------------------------------------------------------- ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, ListenerSP listener_sp) : Process(target_sp, listener_sp), m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_last_stop_packet_mutex(), m_register_info(), - m_async_broadcaster(NULL, "lldb.process.gdb-remote.async-broadcaster"), + m_async_broadcaster(nullptr, "lldb.process.gdb-remote.async-broadcaster"), m_async_listener_sp( Listener::MakeListener("lldb.process.gdb-remote.async-listener")), m_async_thread_state_mutex(), m_thread_ids(), m_thread_pcs(), @@ -340,9 +376,7 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, m_gdb_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); } -//---------------------------------------------------------------------- // Destructor -//---------------------------------------------------------------------- ProcessGDBRemote::~ProcessGDBRemote() { // m_mach_process.UnregisterNotificationCallbacks (this); Clear(); @@ -360,9 +394,7 @@ ProcessGDBRemote::~ProcessGDBRemote() { KillDebugserverProcess(); } -//---------------------------------------------------------------------- // PluginInterface -//---------------------------------------------------------------------- ConstString ProcessGDBRemote::GetPluginName() { return GetPluginNameStatic(); } uint32_t ProcessGDBRemote::GetPluginVersion() { return 1; } @@ -370,7 +402,7 @@ uint32_t ProcessGDBRemote::GetPluginVersion() { return 1; } bool ProcessGDBRemote::ParsePythonTargetDefinition( const FileSpec &target_definition_fspec) { ScriptInterpreter *interpreter = - GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + GetTarget().GetDebugger().GetScriptInterpreter(); Status error; StructuredData::ObjectSP module_object_sp( interpreter->LoadPluginModule(target_definition_fspec, error)); @@ -540,8 +572,8 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { std::vector<uint32_t> invalidate_regs; std::vector<uint8_t> dwarf_opcode_bytes; RegisterInfo reg_info = { - NULL, // Name - NULL, // Alt name + nullptr, // Name + nullptr, // Alt name 0, // byte size reg_offset, // offset eEncodingUint, // encoding @@ -553,10 +585,10 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { reg_num, // process plugin reg num reg_num // native register number }, - NULL, - NULL, - NULL, // Dwarf expression opcode bytes pointer - 0 // Dwarf expression opcode bytes length + nullptr, + nullptr, + nullptr, // Dwarf expression opcode bytes pointer + 0 // Dwarf expression opcode bytes length }; while (response.GetNameColonValue(name, value)) { @@ -576,7 +608,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { reg_info.encoding = encoding; } else if (name.equals("format")) { Format format = eFormatInvalid; - if (OptionArgParser::ToFormat(value.str().c_str(), format, NULL) + if (OptionArgParser::ToFormat(value.str().c_str(), format, nullptr) .Success()) reg_info.format = format; else { @@ -796,9 +828,7 @@ Status ProcessGDBRemote::WillLaunchOrAttach() { return error; } -//---------------------------------------------------------------------- // Process Control -//---------------------------------------------------------------------- Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, ProcessLaunchInfo &launch_info) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); @@ -883,8 +913,8 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, // since 'O' packets can really slow down debugging if the inferior // 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)}; + pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, nullptr, 0)) { + FileSpec slave_name{pty.GetSlaveName(nullptr, 0)}; if (!stdin_file_spec) stdin_file_spec = slave_name; @@ -928,7 +958,7 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, GetTarget().GetArchitecture().GetArchitectureName()); const char *launch_event_data = launch_info.GetLaunchEventData(); - if (launch_event_data != NULL && *launch_event_data != '\0') + if (launch_event_data != nullptr && *launch_event_data != '\0') m_gdb_comm.SendLaunchEventDataPacket(launch_event_data); if (working_dir) { @@ -1013,14 +1043,14 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { if (log) log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, connect_url.str().c_str()); - std::unique_ptr<ConnectionFileDescriptor> conn_ap( + std::unique_ptr<ConnectionFileDescriptor> conn_up( new ConnectionFileDescriptor()); - if (conn_ap.get()) { + if (conn_up) { const uint32_t max_retry_count = 50; uint32_t retry_count = 0; while (!m_gdb_comm.IsConnected()) { - if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess) { - m_gdb_comm.SetConnection(conn_ap.release()); + if (conn_up->Connect(connect_url, &error) == eConnectionStatusSuccess) { + m_gdb_comm.SetConnection(conn_up.release()); break; } else if (error.WasInterrupted()) { // If we were interrupted, don't keep retrying. @@ -1702,7 +1732,7 @@ bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list, ThreadSP thread_sp( old_thread_list_copy.RemoveThreadByProtocolID(tid, false)); if (!thread_sp) { - thread_sp.reset(new ThreadGDBRemote(*this, tid)); + thread_sp = std::make_shared<ThreadGDBRemote>(*this, tid); LLDB_LOGV(log, "Making new thread: {0} for thread ID: {1:x}.", thread_sp.get(), thread_sp->GetID()); } else { @@ -1818,7 +1848,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( if (!thread_sp) { // Create the thread if we need to - thread_sp.reset(new ThreadGDBRemote(*this, tid)); + thread_sp = std::make_shared<ThreadGDBRemote>(*this, tid); m_thread_list_real.AddThread(thread_sp); } } @@ -1842,7 +1872,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData()); } - thread_sp->SetName(thread_name.empty() ? NULL : thread_name.c_str()); + thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str()); gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr); // Check if the GDB server was able to provide the queue name, kind and @@ -2421,6 +2451,15 @@ void ProcessGDBRemote::RefreshStateAfterStop() { // Scope for the lock { + // Check to see if SetThreadStopInfo() filled in m_thread_ids? + if (m_thread_ids.empty()) { + // No, we need to fetch the thread list manually + UpdateThreadIDList(); + } + // We might set some stop info's so make sure the thread list is up to + // date before we do that or we might overwrite what was computed here. + UpdateThreadListIfNeeded(); + // Lock the thread stack while we access it std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex); // Get the number of stop packets on the stack @@ -2435,13 +2474,7 @@ void ProcessGDBRemote::RefreshStateAfterStop() { // Clear the thread stop stack m_stop_packet_stack.clear(); } - - // Check to see if SetThreadStopInfo() filled in m_thread_ids? - if (m_thread_ids.empty()) { - // No, we need to fetch the thread list manually - UpdateThreadIDList(); - } - + // If we have queried for a default thread id if (m_initial_tid != LLDB_INVALID_THREAD_ID) { m_thread_list.SetSelectedThreadByID(m_initial_tid); @@ -2711,9 +2744,7 @@ void ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp) { Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp)); } -//------------------------------------------------------------------ // Process Queries -//------------------------------------------------------------------ bool ProcessGDBRemote::IsAlive() { return m_gdb_comm.IsConnected() && Process::IsAlive(); @@ -2757,9 +2788,7 @@ void ProcessGDBRemote::WillPublicStop() { } } -//------------------------------------------------------------------ // Process Memory -//------------------------------------------------------------------ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, Status &error) { GetMaxMemorySize(); @@ -3120,14 +3149,12 @@ Status ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) { return error; } -//------------------------------------------------------------------ // Process STDIO -//------------------------------------------------------------------ size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len, Status &error) { if (m_stdio_communication.IsConnected()) { ConnectionStatus status; - m_stdio_communication.Write(src, src_len, status, NULL); + m_stdio_communication.Write(src, src_len, status, nullptr); } else if (m_stdin_forward) { m_gdb_comm.SendStdinNotification(src, src_len); } @@ -3136,7 +3163,7 @@ size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len, Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { Status error; - assert(bp_site != NULL); + assert(bp_site != nullptr); // Get logging info Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); @@ -3262,7 +3289,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { Status error; - assert(bp_site != NULL); + assert(bp_site != nullptr); addr_t addr = bp_site->GetLoadAddress(); user_id_t site_id = bp_site->GetID(); Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); @@ -3432,16 +3459,10 @@ 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()); + FileSpec history_file = loader->GetFile<ProcessGDBRemoteProvider::Info>(); + if (!history_file) + return Status("No provider for gdb-remote."); // Enable replay mode. m_replay_mode = true; @@ -3679,9 +3700,15 @@ bool ProcessGDBRemote::StartAsyncThread() { // 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.process.gdb-remote.async>", - ProcessGDBRemote::AsyncThread, this, NULL); + llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread( + "<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this); + if (!async_thread) { + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + "failed to launch host thread: {}", + llvm::toString(async_thread.takeError())); + return false; + } + m_async_thread = *async_thread; } else if (log) log->Printf("ProcessGDBRemote::%s () - Called when Async thread was " "already running.", @@ -3775,7 +3802,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr); - if (::strstr(continue_cstr, "vAttach") == NULL) + if (::strstr(continue_cstr, "vAttach") == nullptr) process->SetPrivateState(eStateRunning); StringExtractorGDBRemote response; @@ -3841,11 +3868,11 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { // the "E87" error code from debugserver -- this indicates that // the process is not debuggable. Return a slightly more // helpful error message about why the attach failed. - if (::strstr(continue_cstr, "vAttach") != NULL && + if (::strstr(continue_cstr, "vAttach") != nullptr && response.GetError() == 0x87) { process->SetExitStatus(-1, "cannot attach to process due to " "System Integrity Protection"); - } else if (::strstr(continue_cstr, "vAttach") != NULL && + } else if (::strstr(continue_cstr, "vAttach") != nullptr && response.GetStatus().Fail()) { process->SetExitStatus(-1, response.GetStatus().AsCString()); } else { @@ -3920,7 +3947,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { ") thread exiting...", __FUNCTION__, arg, process->GetID()); - return NULL; + return {}; } // uint32_t @@ -4016,7 +4043,7 @@ bool ProcessGDBRemote::StartNoticingNewThreads() { } } } - return m_thread_create_bp_sp.get() != NULL; + return m_thread_create_bp_sp.get() != nullptr; } bool ProcessGDBRemote::StopNoticingNewThreads() { @@ -4031,9 +4058,9 @@ bool ProcessGDBRemote::StopNoticingNewThreads() { } DynamicLoader *ProcessGDBRemote::GetDynamicLoader() { - if (m_dyld_ap.get() == NULL) - m_dyld_ap.reset(DynamicLoader::FindPlugin(this, NULL)); - return m_dyld_ap.get(); + if (m_dyld_up.get() == nullptr) + m_dyld_up.reset(DynamicLoader::FindPlugin(this, nullptr)); + return m_dyld_up.get(); } Status ProcessGDBRemote::SendEventData(const char *data) { @@ -4053,17 +4080,17 @@ Status ProcessGDBRemote::SendEventData(const char *data) { return error; } -const DataBufferSP ProcessGDBRemote::GetAuxvData() { +DataExtractor ProcessGDBRemote::GetAuxvData() { DataBufferSP buf; if (m_gdb_comm.GetQXferAuxvReadSupported()) { std::string response_string; if (m_gdb_comm.SendPacketsAndConcatenateResponses("qXfer:auxv:read::", response_string) == GDBRemoteCommunication::PacketResult::Success) - buf.reset(new DataBufferHeap(response_string.c_str(), - response_string.length())); + buf = std::make_shared<DataBufferHeap>(response_string.c_str(), + response_string.length()); } - return buf; + return DataExtractor(buf, GetByteOrder(), GetAddressByteSize()); } StructuredData::ObjectSP @@ -4212,7 +4239,7 @@ StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() { } Status ProcessGDBRemote::ConfigureStructuredData( - const ConstString &type_name, const StructuredData::ObjectSP &config_sp) { + ConstString type_name, const StructuredData::ObjectSP &config_sp) { return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp); } @@ -4373,8 +4400,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, bool encoding_set = false; bool format_set = false; RegisterInfo reg_info = { - NULL, // Name - NULL, // Alt name + nullptr, // Name + nullptr, // Alt name 0, // byte size reg_offset, // offset eEncodingUint, // encoding @@ -4386,10 +4413,10 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, cur_reg_num, // process plugin reg num cur_reg_num // native register number }, - NULL, - NULL, - NULL, // Dwarf Expression opcode bytes pointer - 0 // Dwarf Expression opcode bytes length + nullptr, + nullptr, + nullptr, // Dwarf Expression opcode bytes pointer + 0 // Dwarf Expression opcode bytes length }; reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, @@ -4423,7 +4450,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, } else if (name == "format") { format_set = true; Format format = eFormatInvalid; - if (OptionArgParser::ToFormat(value.data(), format, NULL).Success()) + if (OptionArgParser::ToFormat(value.data(), format, nullptr) + .Success()) reg_info.format = format; else if (value == "vector-sint8") reg_info.format = eFormatVectorOfSInt8; @@ -4499,8 +4527,15 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, // Only update the register set name if we didn't get a "reg_set" // attribute. "set_name" will be empty if we didn't have a "reg_set" // attribute. - if (!set_name && !gdb_group.empty()) - set_name.SetCString(gdb_group.c_str()); + if (!set_name) { + if (!gdb_group.empty()) { + set_name.SetCString(gdb_group.c_str()); + } else { + // If no register group name provided anywhere, + // we'll create a 'general' register set + set_name.SetCString("general"); + } + } reg_info.byte_offset = reg_offset; assert(reg_info.byte_size != 0); @@ -4525,38 +4560,33 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, } // namespace -// query the target of gdb-remote for extended target information return: -// 'true' on success -// 'false' on failure -bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { - // Make sure LLDB has an XML parser it can use first - if (!XMLDocument::XMLEnabled()) - return false; - - // redirect libxml2's error handler since the default prints to stdout - - GDBRemoteCommunicationClient &comm = m_gdb_comm; - - // check that we have extended feature read support - if (!comm.GetQXferFeaturesReadSupported()) - return false; - +// This method fetches a register description feature xml file from +// the remote stub and adds registers/register groupsets/architecture +// information to the current process. It will call itself recursively +// for nested register definition files. It returns true if it was able +// to fetch and parse an xml file. +bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess(ArchSpec &arch_to_use, + std::string xml_filename, + uint32_t &cur_reg_num, + uint32_t ®_offset) { // request the target xml file std::string raw; lldb_private::Status lldberr; - if (!comm.ReadExtFeature(ConstString("features"), ConstString("target.xml"), + if (!m_gdb_comm.ReadExtFeature(ConstString("features"), + ConstString(xml_filename.c_str()), raw, lldberr)) { return false; } XMLDocument xml_document; - if (xml_document.ParseMemory(raw.c_str(), raw.size(), "target.xml")) { + if (xml_document.ParseMemory(raw.c_str(), raw.size(), xml_filename.c_str())) { GdbServerTargetInfo target_info; + std::vector<XMLNode> feature_nodes; + // The top level feature XML file will start with a <target> tag. XMLNode target_node = xml_document.GetRootElement("target"); if (target_node) { - std::vector<XMLNode> feature_nodes; target_node.ForEachChildElement([&target_info, &feature_nodes]( const XMLNode &node) -> bool { llvm::StringRef name = node.GetName(); @@ -4594,32 +4624,48 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { } return true; // Keep iterating through all children of the target_node }); + } else { + // In an included XML feature file, we're already "inside" the <target> + // tag of the initial XML file; this included file will likely only have + // a <feature> tag. Need to check for any more included files in this + // <feature> element. + XMLNode feature_node = xml_document.GetRootElement("feature"); + if (feature_node) { + feature_nodes.push_back(feature_node); + feature_node.ForEachChildElement([&target_info]( + const XMLNode &node) -> bool { + llvm::StringRef name = node.GetName(); + if (name == "xi:include" || name == "include") { + llvm::StringRef href = node.GetAttributeValue("href"); + if (!href.empty()) + target_info.includes.push_back(href.str()); + } + return true; + }); + } + } - // If the target.xml includes an architecture entry like - // <architecture>i386:x86-64</architecture> (seen from VMWare ESXi) - // <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") { - // 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); - } + // If the target.xml includes an architecture entry like + // <architecture>i386:x86-64</architecture> (seen from VMWare ESXi) + // <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") { + // We don't have any information about vendor or OS. + arch_to_use.SetTriple("x86_64--"); + GetTarget().MergeArchitecture(arch_to_use); } - // Initialize these outside of ParseRegisters, since they should not be - // reset inside each include feature - uint32_t cur_reg_num = 0; - uint32_t reg_offset = 0; + // 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); + } + } + if (arch_to_use.IsValid()) { // Don't use Process::GetABI, this code gets called from DidAttach, and // in that context we haven't set the Target's architecture yet, so the // ABI is also potentially incorrect. @@ -4630,26 +4676,31 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { } for (const auto &include : target_info.includes) { - // request register file - std::string xml_data; - if (!comm.ReadExtFeature(ConstString("features"), ConstString(include), - xml_data, lldberr)) - continue; - - XMLDocument include_xml_document; - include_xml_document.ParseMemory(xml_data.data(), xml_data.size(), - include.c_str()); - XMLNode include_feature_node = - include_xml_document.GetRootElement("feature"); - if (include_feature_node) { - ParseRegisters(include_feature_node, target_info, - this->m_register_info, abi_to_use_sp, cur_reg_num, - reg_offset); - } + GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, include, + cur_reg_num, reg_offset); } - this->m_register_info.Finalize(arch_to_use); } + } else { + return false; } + return true; +} + +// query the target of gdb-remote for extended target information returns +// true on success (got register definitions), false on failure (did not). +bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { + // Make sure LLDB has an XML parser it can use first + if (!XMLDocument::XMLEnabled()) + return false; + + // check that we have extended feature read support + if (!m_gdb_comm.GetQXferFeaturesReadSupported()) + return false; + + uint32_t cur_reg_num = 0; + uint32_t reg_offset = 0; + if (GetGDBServerRegisterInfoXMLAndProcess (arch_to_use, "target.xml", cur_reg_num, reg_offset)) + this->m_register_info.Finalize(arch_to_use); return m_register_info.GetNumRegisters() > 0; } @@ -4664,9 +4715,10 @@ Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { log->Printf("ProcessGDBRemote::%s", __FUNCTION__); GDBRemoteCommunicationClient &comm = m_gdb_comm; + bool can_use_svr4 = GetGlobalPluginProperties()->GetUseSVR4(); // check that we have extended feature read support - if (comm.GetQXferLibrariesSVR4ReadSupported()) { + if (can_use_svr4 && comm.GetQXferLibrariesSVR4ReadSupported()) { list.clear(); // request the loaded library list @@ -4929,7 +4981,7 @@ Status ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file, StreamString packet; packet.PutCString("qFileLoadAddress:"); - packet.PutCStringAsRawHex8(file_path.c_str()); + packet.PutStringAsRawHex8(file_path); StringExtractorGDBRemote response; if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, @@ -5140,7 +5192,7 @@ public: "Tests packet speeds of various sizes to determine " "the performance characteristics of the GDB remote " "connection. ", - NULL), + nullptr), m_option_group(), m_num_packets(LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount, "The number of packets to send of each varying size " @@ -5165,7 +5217,7 @@ public: m_option_group.Finalize(); } - ~CommandObjectProcessGDBRemoteSpeedTest() {} + ~CommandObjectProcessGDBRemoteSpeedTest() override {} Options *GetOptions() override { return &m_option_group; } @@ -5214,9 +5266,9 @@ private: public: CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "process plugin packet history", - "Dumps the packet history buffer. ", NULL) {} + "Dumps the packet history buffer. ", nullptr) {} - ~CommandObjectProcessGDBRemotePacketHistory() {} + ~CommandObjectProcessGDBRemotePacketHistory() override {} bool DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); @@ -5245,9 +5297,9 @@ public: : CommandObjectParsed( interpreter, "process plugin packet xfer-size", "Maximum size that lldb will try to read/write one one chunk.", - NULL) {} + nullptr) {} - ~CommandObjectProcessGDBRemotePacketXferSize() {} + ~CommandObjectProcessGDBRemotePacketXferSize() override {} bool DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); @@ -5265,7 +5317,7 @@ public: if (process) { const char *packet_size = command.GetArgumentAtIndex(0); errno = 0; - uint64_t user_specified_max = strtoul(packet_size, NULL, 10); + uint64_t user_specified_max = strtoul(packet_size, nullptr, 10); if (errno == 0 && user_specified_max != 0) { process->SetUserSpecifiedMaxMemoryTransferSize(user_specified_max); result.SetStatus(eReturnStatusSuccessFinishResult); @@ -5287,9 +5339,9 @@ public: "The packet header and footer will automatically " "be added to the packet prior to sending and " "stripped from the result.", - NULL) {} + nullptr) {} - ~CommandObjectProcessGDBRemotePacketSend() {} + ~CommandObjectProcessGDBRemotePacketSend() override {} bool DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); @@ -5315,7 +5367,7 @@ public: output_strm.Printf(" packet: %s\n", packet_cstr); std::string &response_str = response.GetStringRef(); - if (strstr(packet_cstr, "qGetProfileData") != NULL) { + if (strstr(packet_cstr, "qGetProfileData") != nullptr) { response_str = process->HarmonizeThreadIdsForProfileData(response); } @@ -5340,7 +5392,7 @@ public: "encoded into a valid 'qRcmd' packet, sent and the " "response will be printed.") {} - ~CommandObjectProcessGDBRemotePacketMonitor() {} + ~CommandObjectProcessGDBRemotePacketMonitor() override {} bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override { @@ -5383,7 +5435,7 @@ public: CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter) : CommandObjectMultiword(interpreter, "process plugin packet", "Commands that deal with GDB remote packets.", - NULL) { + nullptr) { LoadSubCommand( "history", CommandObjectSP( @@ -5404,7 +5456,7 @@ public: interpreter))); } - ~CommandObjectProcessGDBRemotePacket() {} + ~CommandObjectProcessGDBRemotePacket() override {} }; class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword { @@ -5419,12 +5471,12 @@ public: CommandObjectSP(new CommandObjectProcessGDBRemotePacket(interpreter))); } - ~CommandObjectMultiwordProcessGDBRemote() {} + ~CommandObjectMultiwordProcessGDBRemote() override {} }; CommandObject *ProcessGDBRemote::GetPluginCommandObject() { if (!m_command_sp) - m_command_sp.reset(new CommandObjectMultiwordProcessGDBRemote( - GetTarget().GetDebugger().GetCommandInterpreter())); + m_command_sp = std::make_shared<CommandObjectMultiwordProcessGDBRemote>( + GetTarget().GetDebugger().GetCommandInterpreter()); return m_command_sp.get(); } diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 14a5237e4345..9c41fc2e5e98 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -1,9 +1,8 @@ //===-- ProcessGDBRemote.h --------------------------------------*- 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 // //===----------------------------------------------------------------------===// @@ -68,17 +67,13 @@ public: static const char *GetPluginDescriptionStatic(); - //------------------------------------------------------------------ // Check if a given Process - //------------------------------------------------------------------ bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override; CommandObject *GetPluginCommandObject() override; - //------------------------------------------------------------------ // Creating a new process, or attaching to an existing one - //------------------------------------------------------------------ Status WillLaunch(Module *module) override; Status DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override; @@ -103,16 +98,12 @@ public: void DidAttach(ArchSpec &process_arch) override; - //------------------------------------------------------------------ // PluginInterface protocol - //------------------------------------------------------------------ ConstString GetPluginName() override; uint32_t GetPluginVersion() override; - //------------------------------------------------------------------ // Process Control - //------------------------------------------------------------------ Status WillResume() override; Status DoResume() override; @@ -131,18 +122,14 @@ public: void SetUnixSignals(const lldb::UnixSignalsSP &signals_sp); - //------------------------------------------------------------------ // Process Queries - //------------------------------------------------------------------ bool IsAlive() override; lldb::addr_t GetImageInfoAddress() override; void WillPublicStop() override; - //------------------------------------------------------------------ // Process Memory - //------------------------------------------------------------------ size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Status &error) override; @@ -160,21 +147,15 @@ public: Status DoDeallocateMemory(lldb::addr_t ptr) override; - //------------------------------------------------------------------ // Process STDIO - //------------------------------------------------------------------ size_t PutSTDIN(const char *buf, size_t buf_size, Status &error) override; - //---------------------------------------------------------------------- // Process Breakpoints - //---------------------------------------------------------------------- Status EnableBreakpointSite(BreakpointSite *bp_site) override; Status DisableBreakpointSite(BreakpointSite *bp_site) override; - //---------------------------------------------------------------------- // Process Watchpoints - //---------------------------------------------------------------------- Status EnableWatchpoint(Watchpoint *wp, bool notify = true) override; Status DisableWatchpoint(Watchpoint *wp, bool notify = true) override; @@ -206,9 +187,7 @@ public: Status SendEventData(const char *data) override; - //---------------------------------------------------------------------- // Override DidExit so we can disconnect from the remote GDB server - //---------------------------------------------------------------------- void DidExit() override; void SetUserSpecifiedMaxMemoryTransferSize(uint64_t user_specified_max); @@ -235,7 +214,7 @@ public: lldb::addr_t image_count) override; Status - ConfigureStructuredData(const ConstString &type_name, + ConfigureStructuredData(ConstString type_name, const StructuredData::ObjectSP &config_sp) override; StructuredData::ObjectSP GetLoadedDynamicLibrariesInfos() override; @@ -256,9 +235,7 @@ protected: friend class GDBRemoteCommunicationClient; friend class GDBRemoteRegisterContext; - //------------------------------------------------------------------ /// Broadcaster event bits definitions. - //------------------------------------------------------------------ enum { eBroadcastBitAsyncContinue = (1 << 0), eBroadcastBitAsyncThreadShouldExit = (1 << 1), @@ -313,9 +290,7 @@ protected: using FlashRange = FlashRangeVector::Entry; FlashRangeVector m_erased_flash_ranges; - //---------------------------------------------------------------------- // Accessors - //---------------------------------------------------------------------- bool IsRunning(lldb::StateType state) { return state == lldb::eStateRunning || IsStepping(state); } @@ -349,7 +324,7 @@ protected: bool ParsePythonTargetDefinition(const FileSpec &target_definition_fspec); - const lldb::DataBufferSP GetAuxvData() override; + DataExtractor GetAuxvData() override; StructuredData::ObjectSP GetExtendedInfoForThread(lldb::tid_t tid); @@ -408,6 +383,11 @@ protected: DynamicLoader *GetDynamicLoader() override; + bool GetGDBServerRegisterInfoXMLAndProcess(ArchSpec &arch_to_use, + std::string xml_filename, + uint32_t &cur_reg_num, + uint32_t ®_offset); + // Query remote GDBServer for register information bool GetGDBServerRegisterInfo(ArchSpec &arch); @@ -428,9 +408,7 @@ protected: bool HasErased(FlashRange range); private: - //------------------------------------------------------------------ // For ProcessGDBRemote only - //------------------------------------------------------------------ std::string m_partial_profile_data; std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map; uint64_t m_last_signals_version = 0; @@ -440,9 +418,7 @@ private: lldb::user_id_t break_id, lldb::user_id_t break_loc_id); - //------------------------------------------------------------------ // ContinueDelegate interface - //------------------------------------------------------------------ void HandleAsyncStdout(llvm::StringRef out) override; void HandleAsyncMisc(llvm::StringRef data) override; void HandleStopReply() override; diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp index 8f16b83907cf..8cadc45824b3 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp @@ -1,9 +1,8 @@ //===-- ProcessGDBRemoteLog.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 // //===----------------------------------------------------------------------===// diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h index d4981df88d8d..d9b8d4536afe 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h @@ -1,9 +1,8 @@ //===-- ProcessGDBRemoteLog.h -----------------------------------*- 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 // //===----------------------------------------------------------------------===// diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index db7dc3eae0ba..6607bce4488b 100644 --- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -1,9 +1,8 @@ //===-- ThreadGDBRemote.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 // //===----------------------------------------------------------------------===// @@ -21,18 +20,18 @@ #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/State.h" #include "lldb/Utility/StreamString.h" +#include "lldb/Utility/StringExtractorGDBRemote.h" #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" -#include "lldb/Utility/StringExtractorGDBRemote.h" + +#include <memory> using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; -//---------------------------------------------------------------------- // Thread Registers -//---------------------------------------------------------------------- ThreadGDBRemote::ThreadGDBRemote(Process &process, lldb::tid_t tid) : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(), @@ -308,9 +307,9 @@ ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) { // supported. bool read_all_registers_at_once = !gdb_process->GetGDBRemote().GetpPacketSupported(GetID()); - reg_ctx_sp.reset(new GDBRemoteRegisterContext( + reg_ctx_sp = std::make_shared<GDBRemoteRegisterContext>( *this, concrete_frame_idx, gdb_process->m_register_info, - read_all_registers_at_once)); + read_all_registers_at_once); } } else { Unwind *unwinder = GetUnwinder(); diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index 4485a9cdc4c3..c74be169abaf 100644 --- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -1,9 +1,8 @@ //===-- ThreadGDBRemote.h ---------------------------------------*- 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 // //===----------------------------------------------------------------------===// @@ -12,13 +11,14 @@ #include <string> -#include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/StructuredData.h" class StringExtractor; namespace lldb_private { +class Process; + namespace process_gdb_remote { class ProcessGDBRemote; |