1 //===-- GDBRemoteCommunication.h --------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATION_H 10 #define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATION_H 11 12 #include "GDBRemoteCommunicationHistory.h" 13 #include "lldb/Core/Communication.h" 14 #include "lldb/Host/Config.h" 15 #include "lldb/Host/Socket.h" 16 #include "lldb/Utility/Args.h" 17 #include "lldb/Utility/StringExtractorGDBRemote.h" 18 #include <mutex> 19 #include <string> 20 21 namespace lldb_private { 22 namespace process_gdb_remote { 23 24 enum GDBStoppointType { 25 eStoppointInvalid = -1, 26 eBreakpointSoftware = 0, 27 eBreakpointHardware, 28 eWatchpointWrite, 29 eWatchpointRead, 30 eWatchpointReadWrite 31 }; 32 33 enum class CompressionType { 34 None = 0, // no compression 35 ZlibDeflate, // zlib's deflate compression scheme, requires zlib or Apple's 36 // libcompression 37 LZFSE, // an Apple compression scheme, requires Apple's libcompression 38 LZ4, // lz compression - called "lz4 raw" in libcompression terms, compat with 39 // https://code.google.com/p/lz4/ 40 LZMA, // Lempel–Ziv–Markov chain algorithm 41 }; 42 43 // Data included in the vFile:fstat packet. 44 // https://sourceware.org/gdb/onlinedocs/gdb/struct-stat.html#struct-stat 45 struct GDBRemoteFStatData { 46 llvm::support::ubig32_t gdb_st_dev; 47 llvm::support::ubig32_t gdb_st_ino; 48 llvm::support::ubig32_t gdb_st_mode; 49 llvm::support::ubig32_t gdb_st_nlink; 50 llvm::support::ubig32_t gdb_st_uid; 51 llvm::support::ubig32_t gdb_st_gid; 52 llvm::support::ubig32_t gdb_st_rdev; 53 llvm::support::ubig64_t gdb_st_size; 54 llvm::support::ubig64_t gdb_st_blksize; 55 llvm::support::ubig64_t gdb_st_blocks; 56 llvm::support::ubig32_t gdb_st_atime; 57 llvm::support::ubig32_t gdb_st_mtime; 58 llvm::support::ubig32_t gdb_st_ctime; 59 }; 60 static_assert(sizeof(GDBRemoteFStatData) == 64, 61 "size of GDBRemoteFStatData is not 64"); 62 63 enum GDBErrno { 64 #define HANDLE_ERRNO(name, value) GDB_##name = value, 65 #include "Plugins/Process/gdb-remote/GDBRemoteErrno.def" 66 GDB_EUNKNOWN = 9999 67 }; 68 69 class ProcessGDBRemote; 70 71 class GDBRemoteCommunication : public Communication { 72 public: 73 enum class PacketType { Invalid = 0, Standard, Notify }; 74 75 enum class PacketResult { 76 Success = 0, // Success 77 ErrorSendFailed, // Status sending the packet 78 ErrorSendAck, // Didn't get an ack back after sending a packet 79 ErrorReplyFailed, // Status getting the reply 80 ErrorReplyTimeout, // Timed out waiting for reply 81 ErrorReplyInvalid, // Got a reply but it wasn't valid for the packet that 82 // was sent 83 ErrorReplyAck, // Sending reply ack failed 84 ErrorDisconnected, // We were disconnected 85 ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet 86 // request 87 }; 88 89 // Class to change the timeout for a given scope and restore it to the 90 // original value when the 91 // created ScopedTimeout object got out of scope 92 class ScopedTimeout { 93 public: 94 ScopedTimeout(GDBRemoteCommunication &gdb_comm, 95 std::chrono::seconds timeout); 96 ~ScopedTimeout(); 97 98 private: 99 GDBRemoteCommunication &m_gdb_comm; 100 std::chrono::seconds m_saved_timeout; 101 // Don't ever reduce the timeout for a packet, only increase it. If the 102 // requested timeout if less than the current timeout, we don't set it 103 // and won't need to restore it. 104 bool m_timeout_modified; 105 }; 106 107 GDBRemoteCommunication(); 108 109 ~GDBRemoteCommunication() override; 110 111 PacketResult GetAck(); 112 113 size_t SendAck(); 114 115 size_t SendNack(); 116 117 char CalculcateChecksum(llvm::StringRef payload); 118 119 PacketType CheckForPacket(const uint8_t *src, size_t src_len, 120 StringExtractorGDBRemote &packet); 121 GetSendAcks()122 bool GetSendAcks() { return m_send_acks; } 123 124 // Set the global packet timeout. 125 // 126 // For clients, this is the timeout that gets used when sending 127 // packets and waiting for responses. For servers, this is used when waiting 128 // for ACKs. SetPacketTimeout(std::chrono::seconds packet_timeout)129 std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) { 130 const auto old_packet_timeout = m_packet_timeout; 131 m_packet_timeout = packet_timeout; 132 return old_packet_timeout; 133 } 134 GetPacketTimeout()135 std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; } 136 137 // Start a debugserver instance on the current host using the 138 // supplied connection URL. 139 static Status 140 StartDebugserverProcess(std::variant<llvm::StringRef, shared_fd_t> comm, 141 ProcessLaunchInfo &launch_info, 142 const Args *inferior_args); 143 144 void DumpHistory(Stream &strm); 145 146 /// Expand GDB run-length encoding. 147 static std::optional<std::string> ExpandRLE(std::string); 148 149 protected: 150 std::chrono::seconds m_packet_timeout; 151 uint32_t m_echo_number; 152 LazyBool m_supports_qEcho; 153 GDBRemoteCommunicationHistory m_history; 154 bool m_send_acks; 155 bool m_is_platform; // Set to true if this class represents a platform, 156 // false if this class represents a debug session for 157 // a single process 158 159 std::string m_bytes; 160 std::recursive_mutex m_bytes_mutex; 161 CompressionType m_compression_type; 162 163 PacketResult SendPacketNoLock(llvm::StringRef payload); 164 PacketResult SendNotificationPacketNoLock(llvm::StringRef notify_type, 165 std::deque<std::string>& queue, 166 llvm::StringRef payload); 167 PacketResult SendRawPacketNoLock(llvm::StringRef payload, 168 bool skip_ack = false); 169 170 PacketResult ReadPacket(StringExtractorGDBRemote &response, 171 Timeout<std::micro> timeout, bool sync_on_timeout); 172 173 PacketResult WaitForPacketNoLock(StringExtractorGDBRemote &response, 174 Timeout<std::micro> timeout, 175 bool sync_on_timeout); 176 CompressionIsEnabled()177 bool CompressionIsEnabled() { 178 return m_compression_type != CompressionType::None; 179 } 180 181 // If compression is enabled, decompress the packet in m_bytes and update 182 // m_bytes with the uncompressed version. 183 // Returns 'true' packet was decompressed and m_bytes is the now-decompressed 184 // text. 185 // Returns 'false' if unable to decompress or if the checksum was invalid. 186 // 187 // NB: Once the packet has been decompressed, checksum cannot be computed 188 // based 189 // on m_bytes. The checksum was for the compressed packet. 190 bool DecompressPacket(); 191 192 private: 193 #if HAVE_LIBCOMPRESSION 194 CompressionType m_decompression_scratch_type = CompressionType::None; 195 void *m_decompression_scratch = nullptr; 196 #endif 197 198 GDBRemoteCommunication(const GDBRemoteCommunication &) = delete; 199 const GDBRemoteCommunication & 200 operator=(const GDBRemoteCommunication &) = delete; 201 }; 202 203 } // namespace process_gdb_remote 204 } // namespace lldb_private 205 206 namespace llvm { 207 template <> 208 struct format_provider< 209 lldb_private::process_gdb_remote::GDBRemoteCommunication::PacketResult> { 210 static void format(const lldb_private::process_gdb_remote:: 211 GDBRemoteCommunication::PacketResult &state, 212 raw_ostream &Stream, StringRef Style); 213 }; 214 } // namespace llvm 215 216 #endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATION_H 217