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 <string>
16 #include <queue>
17 #include <vector>
18 
19 // Other libraries and framework includes
20 // Project includes
21 #include "lldb/lldb-public.h"
22 #include "lldb/Core/Communication.h"
23 #include "lldb/Core/Listener.h"
24 #include "lldb/Host/HostThread.h"
25 #include "lldb/Host/Mutex.h"
26 #include "lldb/Host/Predicate.h"
27 #include "lldb/Host/TimeValue.h"
28 #include "lldb/Interpreter/Args.h"
29 
30 #include "Utility/StringExtractorGDBRemote.h"
31 
32 namespace lldb_private {
33 namespace process_gdb_remote {
34 
35 typedef enum
36 {
37     eStoppointInvalid = -1,
38     eBreakpointSoftware = 0,
39     eBreakpointHardware,
40     eWatchpointWrite,
41     eWatchpointRead,
42     eWatchpointReadWrite
43 } GDBStoppointType;
44 
45 enum class CompressionType
46 {
47     None = 0,       // no compression
48     ZlibDeflate,    // zlib's deflate compression scheme, requires zlib or Apple's libcompression
49     LZFSE,          // an Apple compression scheme, requires Apple's libcompression
50     LZ4,            // lz compression - called "lz4 raw" in libcompression terms, compat with 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 {
58 public:
59     enum
60     {
61         eBroadcastBitRunPacketSent = kLoUserBroadcastBit,
62         eBroadcastBitGdbReadThreadGotNotify = kLoUserBroadcastBit << 1 // Sent when we received a notify packet.
63     };
64 
65     enum class PacketType
66     {
67         Invalid = 0,
68         Standard,
69         Notify
70     };
71 
72     enum class PacketResult
73     {
74         Success = 0,        // Success
75         ErrorSendFailed,    // Error sending the packet
76         ErrorSendAck,       // Didn't get an ack back after sending a packet
77         ErrorReplyFailed,   // Error getting the reply
78         ErrorReplyTimeout,  // Timed out waiting for reply
79         ErrorReplyInvalid,  // Got a reply but it wasn't valid for the packet that was sent
80         ErrorReplyAck,      // Sending reply ack failed
81         ErrorDisconnected,  // We were disconnected
82         ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet request
83     };
84 
85     // Class to change the timeout for a given scope and restore it to the original value when the
86     // created ScopedTimeout object got out of scope
87     class ScopedTimeout
88     {
89     public:
90         ScopedTimeout (GDBRemoteCommunication& gdb_comm, uint32_t timeout);
91         ~ScopedTimeout ();
92 
93     private:
94         GDBRemoteCommunication& m_gdb_comm;
95         uint32_t m_saved_timeout;
96     };
97 
98     GDBRemoteCommunication(const char *comm_name,
99                            const char *listener_name);
100 
101     ~GDBRemoteCommunication() override;
102 
103     PacketResult
104     GetAck ();
105 
106     size_t
107     SendAck ();
108 
109     size_t
110     SendNack ();
111 
112     char
113     CalculcateChecksum (const char *payload,
114                         size_t payload_length);
115 
116     bool
117     GetSequenceMutex(Mutex::Locker& locker, const char *failure_message = nullptr);
118 
119     PacketType
120     CheckForPacket (const uint8_t *src,
121                     size_t src_len,
122                     StringExtractorGDBRemote &packet);
123 
124     bool
125     IsRunning() const
126     {
127         return m_public_is_running.GetValue();
128     }
129 
130     bool
131     GetSendAcks ()
132     {
133         return m_send_acks;
134     }
135 
136     //------------------------------------------------------------------
137     // Client and server must implement these pure virtual functions
138     //------------------------------------------------------------------
139     virtual bool
140     GetThreadSuffixSupported () = 0;
141 
142     //------------------------------------------------------------------
143     // Set the global packet timeout.
144     //
145     // For clients, this is the timeout that gets used when sending
146     // packets and waiting for responses. For servers, this might not
147     // get used, and if it doesn't this should be moved to the
148     // GDBRemoteCommunicationClient.
149     //------------------------------------------------------------------
150     uint32_t
151     SetPacketTimeout (uint32_t packet_timeout)
152     {
153         const uint32_t old_packet_timeout = m_packet_timeout;
154         m_packet_timeout = packet_timeout;
155         return old_packet_timeout;
156     }
157 
158     uint32_t
159     GetPacketTimeoutInMicroSeconds () const
160     {
161         return m_packet_timeout * TimeValue::MicroSecPerSec;
162     }
163 
164     //------------------------------------------------------------------
165     // Start a debugserver instance on the current host using the
166     // supplied connection URL.
167     //------------------------------------------------------------------
168     Error
169     StartDebugserverProcess(const char *url,
170                             Platform *platform, // If non nullptr, then check with the platform for the GDB server binary if it can't be located
171                             ProcessLaunchInfo &launch_info,
172                             uint16_t *port,
173                             const Args& inferior_args = Args());
174 
175     void
176     DumpHistory(Stream &strm);
177 
178 protected:
179     class History
180     {
181     public:
182         enum PacketType
183         {
184             ePacketTypeInvalid = 0,
185             ePacketTypeSend,
186             ePacketTypeRecv
187         };
188 
189         struct Entry
190         {
191             Entry() :
192                 packet(),
193                 type (ePacketTypeInvalid),
194                 bytes_transmitted (0),
195                 packet_idx (0),
196                 tid (LLDB_INVALID_THREAD_ID)
197             {
198             }
199 
200             void
201             Clear ()
202             {
203                 packet.clear();
204                 type = ePacketTypeInvalid;
205                 bytes_transmitted = 0;
206                 packet_idx = 0;
207                 tid = LLDB_INVALID_THREAD_ID;
208             }
209             std::string packet;
210             PacketType type;
211             uint32_t bytes_transmitted;
212             uint32_t packet_idx;
213             lldb::tid_t tid;
214         };
215 
216         History (uint32_t size);
217 
218         ~History ();
219 
220         // For single char packets for ack, nack and /x03
221         void
222         AddPacket (char packet_char,
223                    PacketType type,
224                    uint32_t bytes_transmitted);
225 
226         void
227         AddPacket (const std::string &src,
228                    uint32_t src_len,
229                    PacketType type,
230                    uint32_t bytes_transmitted);
231 
232         void
233         Dump (Stream &strm) const;
234 
235         void
236         Dump (Log *log) const;
237 
238         bool
239         DidDumpToLog () const
240         {
241             return m_dumped_to_log;
242         }
243 
244     protected:
245         uint32_t
246         GetFirstSavedPacketIndex () const
247         {
248             if (m_total_packet_count < m_packets.size())
249                 return 0;
250             else
251                 return m_curr_idx + 1;
252         }
253 
254         uint32_t
255         GetNumPacketsInHistory () const
256         {
257             if (m_total_packet_count < m_packets.size())
258                 return m_total_packet_count;
259             else
260                 return (uint32_t)m_packets.size();
261         }
262 
263         uint32_t
264         GetNextIndex()
265         {
266             ++m_total_packet_count;
267             const uint32_t idx = m_curr_idx;
268             m_curr_idx = NormalizeIndex(idx + 1);
269             return idx;
270         }
271 
272         uint32_t
273         NormalizeIndex (uint32_t i) const
274         {
275             return i % m_packets.size();
276         }
277 
278         std::vector<Entry> m_packets;
279         uint32_t m_curr_idx;
280         uint32_t m_total_packet_count;
281         mutable bool m_dumped_to_log;
282     };
283 
284     uint32_t m_packet_timeout;
285     uint32_t m_echo_number;
286     LazyBool m_supports_qEcho;
287 #ifdef ENABLE_MUTEX_ERROR_CHECKING
288     TrackingMutex m_sequence_mutex;
289 #else
290     Mutex m_sequence_mutex;    // Restrict access to sending/receiving packets to a single thread at a time
291 #endif
292     Predicate<bool> m_public_is_running;
293     Predicate<bool> m_private_is_running;
294     History m_history;
295     bool m_send_acks;
296     bool m_is_platform; // Set to true if this class represents a platform,
297                         // false if this class represents a debug session for
298                         // a single process
299 
300     CompressionType m_compression_type;
301 
302     PacketResult
303     SendPacket (const char *payload,
304                 size_t payload_length);
305 
306     PacketResult
307     SendPacketNoLock (const char *payload,
308                       size_t payload_length);
309 
310     PacketResult
311     ReadPacket (StringExtractorGDBRemote &response, uint32_t timeout_usec, bool sync_on_timeout);
312 
313     // Pop a packet from the queue in a thread safe manner
314     PacketResult
315     PopPacketFromQueue (StringExtractorGDBRemote &response, uint32_t timeout_usec);
316 
317     PacketResult
318     WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &response,
319                                                 uint32_t timeout_usec,
320                                                 bool sync_on_timeout);
321 
322     bool
323     WaitForNotRunningPrivate (const TimeValue *timeout_ptr);
324 
325     bool
326     CompressionIsEnabled ()
327     {
328         return m_compression_type != CompressionType::None;
329     }
330 
331     // If compression is enabled, decompress the packet in m_bytes and update
332     // m_bytes with the uncompressed version.
333     // Returns 'true' packet was decompressed and m_bytes is the now-decompressed text.
334     // Returns 'false' if unable to decompress or if the checksum was invalid.
335     //
336     // NB: Once the packet has been decompressed, checksum cannot be computed based
337     // on m_bytes.  The checksum was for the compressed packet.
338     bool
339     DecompressPacket ();
340 
341     Error
342     StartListenThread (const char *hostname = "127.0.0.1", uint16_t port = 0);
343 
344     bool
345     JoinListenThread ();
346 
347     static lldb::thread_result_t
348     ListenThread (lldb::thread_arg_t arg);
349 
350     // GDB-Remote read thread
351     //  . this thread constantly tries to read from the communication
352     //    class and stores all packets received in a queue.  The usual
353     //    threads read requests simply pop packets off the queue in the
354     //    usual order.
355     //    This setup allows us to intercept and handle async packets, such
356     //    as the notify packet.
357 
358     // This method is defined as part of communication.h
359     // when the read thread gets any bytes it will pass them on to this function
360     void AppendBytesToCache(const uint8_t * bytes,
361                             size_t len,
362                             bool broadcast,
363                             lldb::ConnectionStatus status) override;
364 
365 private:
366     std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue
367     lldb_private::Mutex m_packet_queue_mutex;            // Mutex for accessing queue
368     Condition m_condition_queue_not_empty;               // Condition variable to wait for packets
369 
370     HostThread m_listen_thread;
371     std::string m_listen_url;
372 
373     DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunication);
374 };
375 
376 } // namespace process_gdb_remote
377 } // namespace lldb_private
378 
379 #endif // liblldb_GDBRemoteCommunication_h_
380