]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / Process / gdb-remote / GDBRemoteCommunication.h
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/Utility/Args.h"
28 #include "lldb/lldb-public.h"
29
30 #include "lldb/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,    // Status sending the packet
69     ErrorSendAck,       // Didn't get an ack back after sending a packet
70     ErrorReplyFailed,   // Status 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     // Don't ever reduce the timeout for a packet, only increase it. If the
93     // requested timeout if less than the current timeout, we don't set it
94     // and won't need to restore it.
95     bool m_timeout_modified;
96   };
97
98   GDBRemoteCommunication(const char *comm_name, const char *listener_name);
99
100   ~GDBRemoteCommunication() override;
101
102   PacketResult GetAck();
103
104   size_t SendAck();
105
106   size_t SendNack();
107
108   char CalculcateChecksum(llvm::StringRef payload);
109
110   PacketType CheckForPacket(const uint8_t *src, size_t src_len,
111                             StringExtractorGDBRemote &packet);
112
113   bool GetSendAcks() { return m_send_acks; }
114
115   //------------------------------------------------------------------
116   // Set the global packet timeout.
117   //
118   // For clients, this is the timeout that gets used when sending
119   // packets and waiting for responses. For servers, this is used when waiting
120   // for ACKs.
121   //------------------------------------------------------------------
122   std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) {
123     const auto old_packet_timeout = m_packet_timeout;
124     m_packet_timeout = packet_timeout;
125     return old_packet_timeout;
126   }
127
128   std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; }
129
130   //------------------------------------------------------------------
131   // Start a debugserver instance on the current host using the
132   // supplied connection URL.
133   //------------------------------------------------------------------
134   Status StartDebugserverProcess(
135       const char *url,
136       Platform *platform, // If non nullptr, then check with the platform for
137                           // the GDB server binary if it can't be located
138       ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args,
139       int pass_comm_fd); // Communication file descriptor to pass during
140                          // fork/exec to avoid having to connect/accept
141
142   void DumpHistory(Stream &strm);
143
144 protected:
145   class History {
146   public:
147     enum PacketType {
148       ePacketTypeInvalid = 0,
149       ePacketTypeSend,
150       ePacketTypeRecv
151     };
152
153     struct Entry {
154       Entry()
155           : packet(), type(ePacketTypeInvalid), bytes_transmitted(0),
156             packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {}
157
158       void Clear() {
159         packet.clear();
160         type = ePacketTypeInvalid;
161         bytes_transmitted = 0;
162         packet_idx = 0;
163         tid = LLDB_INVALID_THREAD_ID;
164       }
165       std::string packet;
166       PacketType type;
167       uint32_t bytes_transmitted;
168       uint32_t packet_idx;
169       lldb::tid_t tid;
170     };
171
172     History(uint32_t size);
173
174     ~History();
175
176     // For single char packets for ack, nack and /x03
177     void AddPacket(char packet_char, PacketType type,
178                    uint32_t bytes_transmitted);
179
180     void AddPacket(const std::string &src, uint32_t src_len, PacketType type,
181                    uint32_t bytes_transmitted);
182
183     void Dump(Stream &strm) const;
184
185     void Dump(Log *log) const;
186
187     bool DidDumpToLog() const { return m_dumped_to_log; }
188
189   protected:
190     uint32_t GetFirstSavedPacketIndex() const {
191       if (m_total_packet_count < m_packets.size())
192         return 0;
193       else
194         return m_curr_idx + 1;
195     }
196
197     uint32_t GetNumPacketsInHistory() const {
198       if (m_total_packet_count < m_packets.size())
199         return m_total_packet_count;
200       else
201         return (uint32_t)m_packets.size();
202     }
203
204     uint32_t GetNextIndex() {
205       ++m_total_packet_count;
206       const uint32_t idx = m_curr_idx;
207       m_curr_idx = NormalizeIndex(idx + 1);
208       return idx;
209     }
210
211     uint32_t NormalizeIndex(uint32_t i) const { return i % m_packets.size(); }
212
213     std::vector<Entry> m_packets;
214     uint32_t m_curr_idx;
215     uint32_t m_total_packet_count;
216     mutable bool m_dumped_to_log;
217   };
218
219   std::chrono::seconds m_packet_timeout;
220   uint32_t m_echo_number;
221   LazyBool m_supports_qEcho;
222   History m_history;
223   bool m_send_acks;
224   bool m_is_platform; // Set to true if this class represents a platform,
225                       // false if this class represents a debug session for
226                       // a single process
227
228   CompressionType m_compression_type;
229
230   PacketResult SendPacketNoLock(llvm::StringRef payload);
231
232   PacketResult ReadPacket(StringExtractorGDBRemote &response,
233                           Timeout<std::micro> timeout, bool sync_on_timeout);
234
235   PacketResult ReadPacketWithOutputSupport(
236       StringExtractorGDBRemote &response, Timeout<std::micro> timeout,
237       bool sync_on_timeout,
238       llvm::function_ref<void(llvm::StringRef)> output_callback);
239
240   // Pop a packet from the queue in a thread safe manner
241   PacketResult PopPacketFromQueue(StringExtractorGDBRemote &response,
242                                   Timeout<std::micro> timeout);
243
244   PacketResult WaitForPacketNoLock(StringExtractorGDBRemote &response,
245                                    Timeout<std::micro> timeout,
246                                    bool sync_on_timeout);
247
248   bool CompressionIsEnabled() {
249     return m_compression_type != CompressionType::None;
250   }
251
252   // If compression is enabled, decompress the packet in m_bytes and update
253   // m_bytes with the uncompressed version.
254   // Returns 'true' packet was decompressed and m_bytes is the now-decompressed
255   // text.
256   // Returns 'false' if unable to decompress or if the checksum was invalid.
257   //
258   // NB: Once the packet has been decompressed, checksum cannot be computed
259   // based
260   // on m_bytes.  The checksum was for the compressed packet.
261   bool DecompressPacket();
262
263   Status StartListenThread(const char *hostname = "127.0.0.1",
264                            uint16_t port = 0);
265
266   bool JoinListenThread();
267
268   static lldb::thread_result_t ListenThread(lldb::thread_arg_t arg);
269
270   // GDB-Remote read thread
271   //  . this thread constantly tries to read from the communication
272   //    class and stores all packets received in a queue.  The usual
273   //    threads read requests simply pop packets off the queue in the
274   //    usual order.
275   //    This setup allows us to intercept and handle async packets, such
276   //    as the notify packet.
277
278   // This method is defined as part of communication.h
279   // when the read thread gets any bytes it will pass them on to this function
280   void AppendBytesToCache(const uint8_t *bytes, size_t len, bool broadcast,
281                           lldb::ConnectionStatus status) override;
282
283 private:
284   std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue
285   std::mutex m_packet_queue_mutex; // Mutex for accessing queue
286   std::condition_variable
287       m_condition_queue_not_empty; // Condition variable to wait for packets
288
289   HostThread m_listen_thread;
290   std::string m_listen_url;
291
292   DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunication);
293 };
294
295 } // namespace process_gdb_remote
296 } // namespace lldb_private
297
298 namespace llvm {
299 template <>
300 struct format_provider<
301     lldb_private::process_gdb_remote::GDBRemoteCommunication::PacketResult> {
302   static void format(const lldb_private::process_gdb_remote::
303                          GDBRemoteCommunication::PacketResult &state,
304                      raw_ostream &Stream, StringRef Style);
305 };
306 } // namespace llvm
307
308 #endif // liblldb_GDBRemoteCommunication_h_