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