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