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/Interpreter/Args.h"
28 #include "lldb/lldb-public.h"
29 
30 #include "Utility/StringExtractorGDBRemote.h"
31 
32 namespace lldb_private {
33 namespace process_gdb_remote {
34 
35 typedef enum {
36   eStoppointInvalid = -1,
37   eBreakpointSoftware = 0,
38   eBreakpointHardware,
39   eWatchpointWrite,
40   eWatchpointRead,
41   eWatchpointReadWrite
42 } GDBStoppointType;
43 
44 enum class CompressionType {
45   None = 0,    // no compression
46   ZlibDeflate, // zlib's deflate compression scheme, requires zlib or Apple's
47                // libcompression
48   LZFSE,       // an Apple compression scheme, requires Apple's libcompression
49   LZ4, // lz compression - called "lz4 raw" in libcompression terms, compat with
50        // https://code.google.com/p/lz4/
51   LZMA, // Lempel–Ziv–Markov chain algorithm
52 };
53 
54 class ProcessGDBRemote;
55 
56 class GDBRemoteCommunication : public Communication {
57 public:
58   enum {
59     eBroadcastBitRunPacketSent = kLoUserBroadcastBit,
60     eBroadcastBitGdbReadThreadGotNotify =
61         kLoUserBroadcastBit << 1 // Sent when we received a notify packet.
62   };
63 
64   enum class PacketType { Invalid = 0, Standard, Notify };
65 
66   enum class PacketResult {
67     Success = 0,        // Success
68     ErrorSendFailed,    // Error sending the packet
69     ErrorSendAck,       // Didn't get an ack back after sending a packet
70     ErrorReplyFailed,   // Error getting the reply
71     ErrorReplyTimeout,  // Timed out waiting for reply
72     ErrorReplyInvalid,  // Got a reply but it wasn't valid for the packet that
73                         // was sent
74     ErrorReplyAck,      // Sending reply ack failed
75     ErrorDisconnected,  // We were disconnected
76     ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet
77                         // request
78   };
79 
80   // Class to change the timeout for a given scope and restore it to the
81   // original value when the
82   // created ScopedTimeout object got out of scope
83   class ScopedTimeout {
84   public:
85     ScopedTimeout(GDBRemoteCommunication &gdb_comm,
86                   std::chrono::seconds timeout);
87     ~ScopedTimeout();
88 
89   private:
90     GDBRemoteCommunication &m_gdb_comm;
91     std::chrono::seconds 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 is used when waiting
116   // for ACKs.
117   //------------------------------------------------------------------
118   std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) {
119     const auto old_packet_timeout = m_packet_timeout;
120     m_packet_timeout = packet_timeout;
121     return old_packet_timeout;
122   }
123 
124   std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; }
125 
126   //------------------------------------------------------------------
127   // Start a debugserver instance on the current host using the
128   // supplied connection URL.
129   //------------------------------------------------------------------
130   Error StartDebugserverProcess(
131       const char *url,
132       Platform *platform, // If non nullptr, then check with the platform for
133                           // the GDB server binary if it can't be located
134       ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args,
135       int pass_comm_fd); // Communication file descriptor to pass during
136                          // fork/exec to avoid having to connect/accept
137 
138   void DumpHistory(Stream &strm);
139 
140 protected:
141   class History {
142   public:
143     enum PacketType {
144       ePacketTypeInvalid = 0,
145       ePacketTypeSend,
146       ePacketTypeRecv
147     };
148 
149     struct Entry {
150       Entry()
151           : packet(), type(ePacketTypeInvalid), bytes_transmitted(0),
152             packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {}
153 
154       void Clear() {
155         packet.clear();
156         type = ePacketTypeInvalid;
157         bytes_transmitted = 0;
158         packet_idx = 0;
159         tid = LLDB_INVALID_THREAD_ID;
160       }
161       std::string packet;
162       PacketType type;
163       uint32_t bytes_transmitted;
164       uint32_t packet_idx;
165       lldb::tid_t tid;
166     };
167 
168     History(uint32_t size);
169 
170     ~History();
171 
172     // For single char packets for ack, nack and /x03
173     void AddPacket(char packet_char, PacketType type,
174                    uint32_t bytes_transmitted);
175 
176     void AddPacket(const std::string &src, uint32_t src_len, PacketType type,
177                    uint32_t bytes_transmitted);
178 
179     void Dump(Stream &strm) const;
180 
181     void Dump(Log *log) const;
182 
183     bool DidDumpToLog() const { return m_dumped_to_log; }
184 
185   protected:
186     uint32_t GetFirstSavedPacketIndex() const {
187       if (m_total_packet_count < m_packets.size())
188         return 0;
189       else
190         return m_curr_idx + 1;
191     }
192 
193     uint32_t GetNumPacketsInHistory() const {
194       if (m_total_packet_count < m_packets.size())
195         return m_total_packet_count;
196       else
197         return (uint32_t)m_packets.size();
198     }
199 
200     uint32_t GetNextIndex() {
201       ++m_total_packet_count;
202       const uint32_t idx = m_curr_idx;
203       m_curr_idx = NormalizeIndex(idx + 1);
204       return idx;
205     }
206 
207     uint32_t NormalizeIndex(uint32_t i) const { return i % m_packets.size(); }
208 
209     std::vector<Entry> m_packets;
210     uint32_t m_curr_idx;
211     uint32_t m_total_packet_count;
212     mutable bool m_dumped_to_log;
213   };
214 
215   std::chrono::seconds m_packet_timeout;
216   uint32_t m_echo_number;
217   LazyBool m_supports_qEcho;
218   History m_history;
219   bool m_send_acks;
220   bool m_is_platform; // Set to true if this class represents a platform,
221                       // false if this class represents a debug session for
222                       // a single process
223 
224   CompressionType m_compression_type;
225 
226   PacketResult SendPacketNoLock(llvm::StringRef payload);
227 
228   PacketResult ReadPacket(StringExtractorGDBRemote &response,
229                           Timeout<std::micro> timeout, bool sync_on_timeout);
230 
231   // Pop a packet from the queue in a thread safe manner
232   PacketResult PopPacketFromQueue(StringExtractorGDBRemote &response,
233                                   Timeout<std::micro> timeout);
234 
235   PacketResult WaitForPacketNoLock(StringExtractorGDBRemote &response,
236                                    Timeout<std::micro> timeout,
237                                    bool sync_on_timeout);
238 
239   bool CompressionIsEnabled() {
240     return m_compression_type != CompressionType::None;
241   }
242 
243   // If compression is enabled, decompress the packet in m_bytes and update
244   // m_bytes with the uncompressed version.
245   // Returns 'true' packet was decompressed and m_bytes is the now-decompressed
246   // text.
247   // Returns 'false' if unable to decompress or if the checksum was invalid.
248   //
249   // NB: Once the packet has been decompressed, checksum cannot be computed
250   // based
251   // on m_bytes.  The checksum was for the compressed packet.
252   bool DecompressPacket();
253 
254   Error StartListenThread(const char *hostname = "127.0.0.1",
255                           uint16_t port = 0);
256 
257   bool JoinListenThread();
258 
259   static lldb::thread_result_t ListenThread(lldb::thread_arg_t arg);
260 
261   // GDB-Remote read thread
262   //  . this thread constantly tries to read from the communication
263   //    class and stores all packets received in a queue.  The usual
264   //    threads read requests simply pop packets off the queue in the
265   //    usual order.
266   //    This setup allows us to intercept and handle async packets, such
267   //    as the notify packet.
268 
269   // This method is defined as part of communication.h
270   // when the read thread gets any bytes it will pass them on to this function
271   void AppendBytesToCache(const uint8_t *bytes, size_t len, bool broadcast,
272                           lldb::ConnectionStatus status) override;
273 
274 private:
275   std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue
276   std::mutex m_packet_queue_mutex; // Mutex for accessing queue
277   std::condition_variable
278       m_condition_queue_not_empty; // Condition variable to wait for packets
279 
280   HostThread m_listen_thread;
281   std::string m_listen_url;
282 
283   DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunication);
284 };
285 
286 } // namespace process_gdb_remote
287 } // namespace lldb_private
288 
289 #endif // liblldb_GDBRemoteCommunication_h_
290