xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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