blob: 854fa76ef0ac96f7f044d5087658db33b656744a [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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
Saleem Abdulrasool2d6a9ec2016-07-28 17:32:20 +000015#include <condition_variable>
16#include <mutex>
Ewan Crawfordfab40d32015-06-16 15:50:18 +000017#include <queue>
Kate Stoneb9c1b512016-09-06 20:57:50 +000018#include <string>
Eugene Zelenkoedb35d92015-10-24 01:08:35 +000019#include <vector>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020
21// Other libraries and framework includes
22// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000023#include "lldb/Core/Communication.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000024#include "lldb/Core/Listener.h"
Zachary Turner39de3112014-09-09 20:54:56 +000025#include "lldb/Host/HostThread.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026#include "lldb/Host/Predicate.h"
Peter Collingbourneba23ca02011-06-18 23:52:14 +000027#include "lldb/Host/TimeValue.h"
Tamas Berghammerccd6cff2015-12-08 14:08:19 +000028#include "lldb/Interpreter/Args.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000029#include "lldb/lldb-public.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030
Greg Claytonc982c762010-07-09 20:39:50 +000031#include "Utility/StringExtractorGDBRemote.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000032
Tamas Berghammerdb264a62015-03-31 09:52:22 +000033namespace lldb_private {
34namespace process_gdb_remote {
35
Kate Stoneb9c1b512016-09-06 20:57:50 +000036typedef enum {
37 eStoppointInvalid = -1,
38 eBreakpointSoftware = 0,
39 eBreakpointHardware,
40 eWatchpointWrite,
41 eWatchpointRead,
42 eWatchpointReadWrite
Chaoren Lin18fe6402015-02-03 01:51:47 +000043} GDBStoppointType;
44
Kate Stoneb9c1b512016-09-06 20:57:50 +000045enum 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
Jason Molenda91ffe0a2015-06-18 21:46:06 +000053};
54
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055class ProcessGDBRemote;
56
Kate Stoneb9c1b512016-09-06 20:57:50 +000057class GDBRemoteCommunication : public Communication {
Chris Lattner30fdc8d2010-06-08 16:52:24 +000058public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000059 enum {
60 eBroadcastBitRunPacketSent = kLoUserBroadcastBit,
61 eBroadcastBitGdbReadThreadGotNotify =
62 kLoUserBroadcastBit << 1 // Sent when we received a notify packet.
63 };
Ewan Crawford9aa2da002015-05-27 14:12:34 +000064
Kate Stoneb9c1b512016-09-06 20:57:50 +000065 enum class PacketType { Invalid = 0, Standard, Notify };
Ewan Crawford9aa2da002015-05-27 14:12:34 +000066
Kate Stoneb9c1b512016-09-06 20:57:50 +000067 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 };
Tamas Berghammer912800c2015-02-24 10:23:39 +000080
Kate Stoneb9c1b512016-09-06 20:57:50 +000081 // 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();
Tamas Berghammer912800c2015-02-24 10:23:39 +000088
Kate Stoneb9c1b512016-09-06 20:57:50 +000089 private:
90 GDBRemoteCommunication &m_gdb_comm;
91 uint32_t m_saved_timeout;
92 };
Tamas Berghammer912800c2015-02-24 10:23:39 +000093
Kate Stoneb9c1b512016-09-06 20:57:50 +000094 GDBRemoteCommunication(const char *comm_name, const char *listener_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000095
Kate Stoneb9c1b512016-09-06 20:57:50 +000096 ~GDBRemoteCommunication() override;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000097
Kate Stoneb9c1b512016-09-06 20:57:50 +000098 PacketResult GetAck();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000099
Kate Stoneb9c1b512016-09-06 20:57:50 +0000100 size_t SendAck();
Greg Clayton6ed95942011-01-22 07:12:45 +0000101
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102 size_t SendNack();
Greg Clayton6ed95942011-01-22 07:12:45 +0000103
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 char CalculcateChecksum(llvm::StringRef payload);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000105
Kate Stoneb9c1b512016-09-06 20:57:50 +0000106 PacketType CheckForPacket(const uint8_t *src, size_t src_len,
107 StringExtractorGDBRemote &packet);
Eugene Zelenkoedb35d92015-10-24 01:08:35 +0000108
Kate Stoneb9c1b512016-09-06 20:57:50 +0000109 bool GetSendAcks() { return m_send_acks; }
Greg Clayton1cb64962011-03-24 04:28:38 +0000110
Kate Stoneb9c1b512016-09-06 20:57:50 +0000111 //------------------------------------------------------------------
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 }
Greg Clayton71fc2a32011-02-12 06:28:37 +0000124
Kate Stoneb9c1b512016-09-06 20:57:50 +0000125 uint32_t GetPacketTimeoutInMicroSeconds() const {
126 return m_packet_timeout * TimeValue::MicroSecPerSec;
127 }
Eugene Zelenkoedb35d92015-10-24 01:08:35 +0000128
Kate Stoneb9c1b512016-09-06 20:57:50 +0000129 //------------------------------------------------------------------
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
Greg Clayton8b82f082011-04-12 05:54:46 +0000140
Kate Stoneb9c1b512016-09-06 20:57:50 +0000141 void DumpHistory(Stream &strm);
142
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000143protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000144 class History {
145 public:
146 enum PacketType {
147 ePacketTypeInvalid = 0,
148 ePacketTypeSend,
149 ePacketTypeRecv
Greg Claytonc1422c12012-04-09 22:46:21 +0000150 };
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151
Kate Stoneb9c1b512016-09-06 20:57:50 +0000152 struct Entry {
153 Entry()
154 : packet(), type(ePacketTypeInvalid), bytes_transmitted(0),
155 packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {}
Eugene Zelenkoedb35d92015-10-24 01:08:35 +0000156
Kate Stoneb9c1b512016-09-06 20:57:50 +0000157 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 };
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170
Kate Stoneb9c1b512016-09-06 20:57:50 +0000171 History(uint32_t size);
Ewan Crawfordfab40d32015-06-16 15:50:18 +0000172
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173 ~History();
Ewan Crawfordfab40d32015-06-16 15:50:18 +0000174
Kate Stoneb9c1b512016-09-06 20:57:50 +0000175 // For single char packets for ack, nack and /x03
176 void AddPacket(char packet_char, PacketType type,
177 uint32_t bytes_transmitted);
Greg Clayton6779606a2011-01-22 23:43:18 +0000178
Kate Stoneb9c1b512016-09-06 20:57:50 +0000179 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;
Jason Molenda91ffe0a2015-06-18 21:46:06 +0000194 }
195
Kate Stoneb9c1b512016-09-06 20:57:50 +0000196 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 }
Jason Molenda91ffe0a2015-06-18 21:46:06 +0000202
Kate Stoneb9c1b512016-09-06 20:57:50 +0000203 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 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000209
Kate Stoneb9c1b512016-09-06 20:57:50 +0000210 uint32_t NormalizeIndex(uint32_t i) const { return i % m_packets.size(); }
Greg Clayton00fe87b2013-12-05 22:58:22 +0000211
Kate Stoneb9c1b512016-09-06 20:57:50 +0000212 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 };
Greg Clayton8b82f082011-04-12 05:54:46 +0000217
Kate Stoneb9c1b512016-09-06 20:57:50 +0000218 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
Ewan Crawfordfab40d32015-06-16 15:50:18 +0000226
Kate Stoneb9c1b512016-09-06 20:57:50 +0000227 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;
Ewan Crawfordfab40d32015-06-16 15:50:18 +0000277
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000278private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000279 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
Ewan Crawfordfab40d32015-06-16 15:50:18 +0000283
Kate Stoneb9c1b512016-09-06 20:57:50 +0000284 HostThread m_listen_thread;
285 std::string m_listen_url;
Greg Clayton00fe87b2013-12-05 22:58:22 +0000286
Kate Stoneb9c1b512016-09-06 20:57:50 +0000287 DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunication);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000288};
289
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000290} // namespace process_gdb_remote
291} // namespace lldb_private
292
Eugene Zelenkoedb35d92015-10-24 01:08:35 +0000293#endif // liblldb_GDBRemoteCommunication_h_