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