1 //===-- GDBRemoteCommunication.h --------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef liblldb_GDBRemoteCommunication_h_
11 #define liblldb_GDBRemoteCommunication_h_
12 
13 // C Includes
14 // C++ Includes
15 #include <condition_variable>
16 #include <mutex>
17 #include <queue>
18 #include <string>
19 #include <vector>
20 
21 // Other libraries and framework includes
22 // Project includes
23 #include "lldb/Core/Communication.h"
24 #include "lldb/Core/Listener.h"
25 #include "lldb/Host/HostThread.h"
26 #include "lldb/Host/Predicate.h"
27 #include "lldb/Host/TimeValue.h"
28 #include "lldb/Interpreter/Args.h"
29 #include "lldb/lldb-public.h"
30 
31 #include "Utility/StringExtractorGDBRemote.h"
32 
33 namespace lldb_private {
34 namespace process_gdb_remote {
35 
36 typedef enum {
37   eStoppointInvalid = -1,
38   eBreakpointSoftware = 0,
39   eBreakpointHardware,
40   eWatchpointWrite,
41   eWatchpointRead,
42   eWatchpointReadWrite
43 } GDBStoppointType;
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 class ProcessGDBRemote;
56 
57 class GDBRemoteCommunication : public Communication {
58 public:
59   enum {
60     eBroadcastBitRunPacketSent = kLoUserBroadcastBit,
61     eBroadcastBitGdbReadThreadGotNotify =
62         kLoUserBroadcastBit << 1 // Sent when we received a notify packet.
63   };
64 
65   enum class PacketType { Invalid = 0, Standard, Notify };
66 
67   enum class PacketResult {
68     Success = 0,        // Success
69     ErrorSendFailed,    // Error sending the packet
70     ErrorSendAck,       // Didn't get an ack back after sending a packet
71     ErrorReplyFailed,   // Error getting the reply
72     ErrorReplyTimeout,  // Timed out waiting for reply
73     ErrorReplyInvalid,  // Got a reply but it wasn't valid for the packet that
74                         // was sent
75     ErrorReplyAck,      // Sending reply ack failed
76     ErrorDisconnected,  // We were disconnected
77     ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet
78                         // request
79   };
80 
81   // Class to change the timeout for a given scope and restore it to the
82   // original value when the
83   // created ScopedTimeout object got out of scope
84   class ScopedTimeout {
85   public:
86     ScopedTimeout(GDBRemoteCommunication &gdb_comm, uint32_t timeout);
87     ~ScopedTimeout();
88 
89   private:
90     GDBRemoteCommunication &m_gdb_comm;
91     uint32_t m_saved_timeout;
92   };
93 
94   GDBRemoteCommunication(const char *comm_name, const char *listener_name);
95 
96   ~GDBRemoteCommunication() override;
97 
98   PacketResult GetAck();
99 
100   size_t SendAck();
101 
102   size_t SendNack();
103 
104   char CalculcateChecksum(llvm::StringRef payload);
105 
106   PacketType CheckForPacket(const uint8_t *src, size_t src_len,
107                             StringExtractorGDBRemote &packet);
108 
109   bool GetSendAcks() { return m_send_acks; }
110 
111   //------------------------------------------------------------------
112   // Set the global packet timeout.
113   //
114   // For clients, this is the timeout that gets used when sending
115   // packets and waiting for responses. For servers, this might not
116   // get used, and if it doesn't this should be moved to the
117   // GDBRemoteCommunicationClient.
118   //------------------------------------------------------------------
119   uint32_t SetPacketTimeout(uint32_t packet_timeout) {
120     const uint32_t old_packet_timeout = m_packet_timeout;
121     m_packet_timeout = packet_timeout;
122     return old_packet_timeout;
123   }
124 
125   uint32_t GetPacketTimeoutInMicroSeconds() const {
126     return m_packet_timeout * TimeValue::MicroSecPerSec;
127   }
128 
129   //------------------------------------------------------------------
130   // Start a debugserver instance on the current host using the
131   // supplied connection URL.
132   //------------------------------------------------------------------
133   Error StartDebugserverProcess(
134       const char *url,
135       Platform *platform, // If non nullptr, then check with the platform for
136                           // the GDB server binary if it can't be located
137       ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args,
138       int pass_comm_fd); // Communication file descriptor to pass during
139                          // fork/exec to avoid having to connect/accept
140 
141   void DumpHistory(Stream &strm);
142 
143 protected:
144   class History {
145   public:
146     enum PacketType {
147       ePacketTypeInvalid = 0,
148       ePacketTypeSend,
149       ePacketTypeRecv
150     };
151 
152     struct Entry {
153       Entry()
154           : packet(), type(ePacketTypeInvalid), bytes_transmitted(0),
155             packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {}
156 
157       void Clear() {
158         packet.clear();
159         type = ePacketTypeInvalid;
160         bytes_transmitted = 0;
161         packet_idx = 0;
162         tid = LLDB_INVALID_THREAD_ID;
163       }
164       std::string packet;
165       PacketType type;
166       uint32_t bytes_transmitted;
167       uint32_t packet_idx;
168       lldb::tid_t tid;
169     };
170 
171     History(uint32_t size);
172 
173     ~History();
174 
175     // For single char packets for ack, nack and /x03
176     void AddPacket(char packet_char, PacketType type,
177                    uint32_t bytes_transmitted);
178 
179     void AddPacket(const std::string &src, uint32_t src_len, PacketType type,
180                    uint32_t bytes_transmitted);
181 
182     void Dump(Stream &strm) const;
183 
184     void Dump(Log *log) const;
185 
186     bool DidDumpToLog() const { return m_dumped_to_log; }
187 
188   protected:
189     uint32_t GetFirstSavedPacketIndex() const {
190       if (m_total_packet_count < m_packets.size())
191         return 0;
192       else
193         return m_curr_idx + 1;
194     }
195 
196     uint32_t GetNumPacketsInHistory() const {
197       if (m_total_packet_count < m_packets.size())
198         return m_total_packet_count;
199       else
200         return (uint32_t)m_packets.size();
201     }
202 
203     uint32_t GetNextIndex() {
204       ++m_total_packet_count;
205       const uint32_t idx = m_curr_idx;
206       m_curr_idx = NormalizeIndex(idx + 1);
207       return idx;
208     }
209 
210     uint32_t NormalizeIndex(uint32_t i) const { return i % m_packets.size(); }
211 
212     std::vector<Entry> m_packets;
213     uint32_t m_curr_idx;
214     uint32_t m_total_packet_count;
215     mutable bool m_dumped_to_log;
216   };
217 
218   uint32_t m_packet_timeout;
219   uint32_t m_echo_number;
220   LazyBool m_supports_qEcho;
221   History m_history;
222   bool m_send_acks;
223   bool m_is_platform; // Set to true if this class represents a platform,
224                       // false if this class represents a debug session for
225                       // a single process
226 
227   CompressionType m_compression_type;
228 
229   PacketResult SendPacketNoLock(llvm::StringRef payload);
230 
231   PacketResult ReadPacket(StringExtractorGDBRemote &response,
232                           uint32_t timeout_usec, bool sync_on_timeout);
233 
234   // Pop a packet from the queue in a thread safe manner
235   PacketResult PopPacketFromQueue(StringExtractorGDBRemote &response,
236                                   uint32_t timeout_usec);
237 
238   PacketResult
239   WaitForPacketWithTimeoutMicroSecondsNoLock(StringExtractorGDBRemote &response,
240                                              uint32_t timeout_usec,
241                                              bool sync_on_timeout);
242 
243   bool CompressionIsEnabled() {
244     return m_compression_type != CompressionType::None;
245   }
246 
247   // If compression is enabled, decompress the packet in m_bytes and update
248   // m_bytes with the uncompressed version.
249   // Returns 'true' packet was decompressed and m_bytes is the now-decompressed
250   // text.
251   // Returns 'false' if unable to decompress or if the checksum was invalid.
252   //
253   // NB: Once the packet has been decompressed, checksum cannot be computed
254   // based
255   // on m_bytes.  The checksum was for the compressed packet.
256   bool DecompressPacket();
257 
258   Error StartListenThread(const char *hostname = "127.0.0.1",
259                           uint16_t port = 0);
260 
261   bool JoinListenThread();
262 
263   static lldb::thread_result_t ListenThread(lldb::thread_arg_t arg);
264 
265   // GDB-Remote read thread
266   //  . this thread constantly tries to read from the communication
267   //    class and stores all packets received in a queue.  The usual
268   //    threads read requests simply pop packets off the queue in the
269   //    usual order.
270   //    This setup allows us to intercept and handle async packets, such
271   //    as the notify packet.
272 
273   // This method is defined as part of communication.h
274   // when the read thread gets any bytes it will pass them on to this function
275   void AppendBytesToCache(const uint8_t *bytes, size_t len, bool broadcast,
276                           lldb::ConnectionStatus status) override;
277 
278 private:
279   std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue
280   std::mutex m_packet_queue_mutex; // Mutex for accessing queue
281   std::condition_variable
282       m_condition_queue_not_empty; // Condition variable to wait for packets
283 
284   HostThread m_listen_thread;
285   std::string m_listen_url;
286 
287   DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunication);
288 };
289 
290 } // namespace process_gdb_remote
291 } // namespace lldb_private
292 
293 #endif // liblldb_GDBRemoteCommunication_h_
294