blob: 3b8d60560639330d1509efd54b1c0ef926ad78e5 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- GDBRemoteCommunication.cpp ------------------------------*- 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
11#include "GDBRemoteCommunication.h"
12
13// C Includes
Stephen Wilson50daf772011-03-25 18:16:28 +000014#include <string.h>
15
Chris Lattner24943d22010-06-08 16:52:24 +000016// C++ Includes
17// Other libraries and framework includes
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Core/Log.h"
Chris Lattner24943d22010-06-08 16:52:24 +000019#include "lldb/Core/StreamString.h"
20#include "lldb/Host/TimeValue.h"
21
22// Project includes
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "ProcessGDBRemoteLog.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28//----------------------------------------------------------------------
29// GDBRemoteCommunication constructor
30//----------------------------------------------------------------------
Greg Clayton61d043b2011-03-22 04:00:09 +000031GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, const char *listener_name) :
32 Communication(comm_name),
Greg Clayton24bc5d92011-03-30 18:16:51 +000033 m_packet_timeout (60),
Greg Clayton61d043b2011-03-22 04:00:09 +000034 m_rx_packet_listener (listener_name),
Chris Lattner24943d22010-06-08 16:52:24 +000035 m_sequence_mutex (Mutex::eMutexTypeRecursive),
Greg Claytoncecf3482011-01-20 07:53:45 +000036 m_public_is_running (false),
Greg Clayton58e26e02011-03-24 04:28:38 +000037 m_private_is_running (false),
38 m_send_acks (true)
Chris Lattner24943d22010-06-08 16:52:24 +000039{
40 m_rx_packet_listener.StartListeningForEvents(this,
41 Communication::eBroadcastBitPacketAvailable |
42 Communication::eBroadcastBitReadThreadDidExit);
43}
44
45//----------------------------------------------------------------------
46// Destructor
47//----------------------------------------------------------------------
48GDBRemoteCommunication::~GDBRemoteCommunication()
49{
50 m_rx_packet_listener.StopListeningForEvents(this,
51 Communication::eBroadcastBitPacketAvailable |
52 Communication::eBroadcastBitReadThreadDidExit);
53 if (IsConnected())
54 {
55 StopReadThread();
56 Disconnect();
57 }
58}
59
Chris Lattner24943d22010-06-08 16:52:24 +000060char
61GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
62{
63 int checksum = 0;
64
65 // We only need to compute the checksum if we are sending acks
Greg Claytonc1f45872011-02-12 06:28:37 +000066 if (GetSendAcks ())
Chris Lattner24943d22010-06-08 16:52:24 +000067 {
Greg Clayton54e7afa2010-07-09 20:39:50 +000068 for (size_t i = 0; i < payload_length; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +000069 checksum += payload[i];
70 }
71 return checksum & 255;
72}
73
74size_t
Greg Claytona4881d02011-01-22 07:12:45 +000075GDBRemoteCommunication::SendAck ()
Chris Lattner24943d22010-06-08 16:52:24 +000076{
Greg Clayton0bfda0b2011-02-05 02:25:06 +000077 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
78 if (log)
79 log->Printf ("send packet: +");
Chris Lattner24943d22010-06-08 16:52:24 +000080 ConnectionStatus status = eConnectionStatusSuccess;
Greg Claytona4881d02011-01-22 07:12:45 +000081 char ack_char = '+';
Greg Clayton24bc5d92011-03-30 18:16:51 +000082 return Write (&ack_char, 1, status, NULL);
Chris Lattner24943d22010-06-08 16:52:24 +000083}
84
85size_t
Greg Claytona4881d02011-01-22 07:12:45 +000086GDBRemoteCommunication::SendNack ()
87{
Greg Clayton0bfda0b2011-02-05 02:25:06 +000088 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
89 if (log)
90 log->Printf ("send packet: -");
Greg Claytona4881d02011-01-22 07:12:45 +000091 ConnectionStatus status = eConnectionStatusSuccess;
92 char nack_char = '-';
Greg Clayton24bc5d92011-03-30 18:16:51 +000093 return Write (&nack_char, 1, status, NULL);
94}
95
96size_t
97GDBRemoteCommunication::SendPacket (lldb_private::StreamString &payload)
98{
99 Mutex::Locker locker(m_sequence_mutex);
100 const std::string &p (payload.GetString());
101 return SendPacketNoLock (p.c_str(), p.size());
Greg Claytona4881d02011-01-22 07:12:45 +0000102}
103
Chris Lattner24943d22010-06-08 16:52:24 +0000104size_t
105GDBRemoteCommunication::SendPacket (const char *payload)
106{
107 Mutex::Locker locker(m_sequence_mutex);
108 return SendPacketNoLock (payload, ::strlen (payload));
109}
110
111size_t
112GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
113{
114 Mutex::Locker locker(m_sequence_mutex);
115 return SendPacketNoLock (payload, payload_length);
116}
117
118size_t
119GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
120{
121 if (IsConnected())
122 {
123 StreamString packet(0, 4, eByteOrderBig);
124
125 packet.PutChar('$');
126 packet.Write (payload, payload_length);
127 packet.PutChar('#');
128 packet.PutHex8(CalculcateChecksum (payload, payload_length));
129
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000130 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
131 if (log)
132 log->Printf ("send packet: %s", packet.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000133 ConnectionStatus status = eConnectionStatusSuccess;
134 size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
135 if (bytes_written == packet.GetSize())
136 {
Greg Claytonc1f45872011-02-12 06:28:37 +0000137 if (GetSendAcks ())
Greg Clayton54e7afa2010-07-09 20:39:50 +0000138 {
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000139 if (GetAck () != '+')
Greg Clayton58e26e02011-03-24 04:28:38 +0000140 {
141 printf("get ack failed...");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000142 return 0;
Greg Clayton58e26e02011-03-24 04:28:38 +0000143 }
Greg Clayton54e7afa2010-07-09 20:39:50 +0000144 }
Chris Lattner24943d22010-06-08 16:52:24 +0000145 }
Johnny Chen515ea542010-09-14 22:10:43 +0000146 else
147 {
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000148 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
149 if (log)
150 log->Printf ("error: failed to send packet: %s", packet.GetData());
Johnny Chen515ea542010-09-14 22:10:43 +0000151 }
Chris Lattner24943d22010-06-08 16:52:24 +0000152 return bytes_written;
Greg Claytoneea26402010-09-14 23:36:40 +0000153 }
Chris Lattner24943d22010-06-08 16:52:24 +0000154 return 0;
155}
156
157char
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000158GDBRemoteCommunication::GetAck ()
Chris Lattner24943d22010-06-08 16:52:24 +0000159{
Greg Clayton61d043b2011-03-22 04:00:09 +0000160 StringExtractorGDBRemote packet;
161 if (WaitForPacket (packet, m_packet_timeout) == 1)
162 return packet.GetChar();
Chris Lattner24943d22010-06-08 16:52:24 +0000163 return 0;
164}
165
166bool
167GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
168{
169 return locker.TryLock (m_sequence_mutex.GetMutex());
170}
171
Chris Lattner24943d22010-06-08 16:52:24 +0000172
Greg Clayton72e1c782011-01-22 23:43:18 +0000173bool
Greg Clayton72e1c782011-01-22 23:43:18 +0000174GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
175{
176 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
177}
178
Chris Lattner24943d22010-06-08 16:52:24 +0000179size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000180GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, uint32_t timeout_seconds)
Chris Lattner24943d22010-06-08 16:52:24 +0000181{
Greg Claytoncecf3482011-01-20 07:53:45 +0000182 Mutex::Locker locker(m_sequence_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000183 TimeValue timeout_time;
184 timeout_time = TimeValue::Now();
185 timeout_time.OffsetWithSeconds (timeout_seconds);
Greg Clayton61d043b2011-03-22 04:00:09 +0000186 return WaitForPacketNoLock (packet, &timeout_time);
Chris Lattner24943d22010-06-08 16:52:24 +0000187}
188
189size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000190GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000191{
192 Mutex::Locker locker(m_sequence_mutex);
Greg Clayton61d043b2011-03-22 04:00:09 +0000193 return WaitForPacketNoLock (packet, timeout_time_ptr);
Chris Lattner24943d22010-06-08 16:52:24 +0000194}
195
196size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000197GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000198{
199 bool checksum_error = false;
Greg Clayton61d043b2011-03-22 04:00:09 +0000200 packet.Clear ();
Chris Lattner24943d22010-06-08 16:52:24 +0000201
202 EventSP event_sp;
203
204 if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
205 {
206 const uint32_t event_type = event_sp->GetType();
207 if (event_type | Communication::eBroadcastBitPacketAvailable)
208 {
209 const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
210 if (event_bytes)
211 {
212 const char * packet_data = (const char *)event_bytes->GetBytes();
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000213 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
214 if (log)
215 log->Printf ("read packet: %s", packet_data);
Chris Lattner24943d22010-06-08 16:52:24 +0000216 const size_t packet_size = event_bytes->GetByteSize();
217 if (packet_data && packet_size > 0)
218 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000219 std::string &packet_str = packet.GetStringRef();
Chris Lattner24943d22010-06-08 16:52:24 +0000220 if (packet_data[0] == '$')
221 {
Greg Clayton4862fa22011-01-08 03:17:57 +0000222 bool success = false;
223 if (packet_size < 4)
224 ::fprintf (stderr, "Packet that starts with $ is too short: '%s'\n", packet_data);
225 else if (packet_data[packet_size-3] != '#' ||
226 !::isxdigit (packet_data[packet_size-2]) ||
227 !::isxdigit (packet_data[packet_size-1]))
228 ::fprintf (stderr, "Invalid checksum footer for packet: '%s'\n", packet_data);
229 else
230 success = true;
231
232 if (success)
Greg Clayton61d043b2011-03-22 04:00:09 +0000233 packet_str.assign (packet_data + 1, packet_size - 4);
Greg Claytonc1f45872011-02-12 06:28:37 +0000234 if (GetSendAcks ())
Chris Lattner24943d22010-06-08 16:52:24 +0000235 {
236 char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
Greg Clayton61d043b2011-03-22 04:00:09 +0000237 char actual_checksum = CalculcateChecksum (&packet_str[0], packet_str.size());
Chris Lattner24943d22010-06-08 16:52:24 +0000238 checksum_error = packet_checksum != actual_checksum;
239 // Send the ack or nack if needed
Greg Clayton4862fa22011-01-08 03:17:57 +0000240 if (checksum_error || !success)
Greg Claytona4881d02011-01-22 07:12:45 +0000241 SendNack();
Chris Lattner24943d22010-06-08 16:52:24 +0000242 else
Greg Claytona4881d02011-01-22 07:12:45 +0000243 SendAck();
Chris Lattner24943d22010-06-08 16:52:24 +0000244 }
245 }
246 else
247 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000248 packet_str.assign (packet_data, packet_size);
Chris Lattner24943d22010-06-08 16:52:24 +0000249 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000250 return packet_str.size();
Chris Lattner24943d22010-06-08 16:52:24 +0000251 }
252 }
253 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000254 else if (event_type | Communication::eBroadcastBitReadThreadDidExit)
Chris Lattner24943d22010-06-08 16:52:24 +0000255 {
256 // Our read thread exited on us so just fall through and return zero...
Greg Clayton58e26e02011-03-24 04:28:38 +0000257 Disconnect();
Chris Lattner24943d22010-06-08 16:52:24 +0000258 }
259 }
260 return 0;
261}
262
263void
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000264GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast,
265 ConnectionStatus status)
Chris Lattner24943d22010-06-08 16:52:24 +0000266{
267 // Put the packet data into the buffer in a thread safe fashion
268 Mutex::Locker locker(m_bytes_mutex);
269 m_bytes.append ((const char *)src, src_len);
270
271 // Parse up the packets into gdb remote packets
272 while (!m_bytes.empty())
273 {
274 // end_idx must be one past the last valid packet byte. Start
275 // it off with an invalid value that is the same as the current
276 // index.
277 size_t end_idx = 0;
278
279 switch (m_bytes[0])
280 {
281 case '+': // Look for ack
282 case '-': // Look for cancel
283 case '\x03': // ^C to halt target
284 end_idx = 1; // The command is one byte long...
285 break;
286
287 case '$':
288 // Look for a standard gdb packet?
289 end_idx = m_bytes.find('#');
290 if (end_idx != std::string::npos)
291 {
292 if (end_idx + 2 < m_bytes.size())
293 {
294 end_idx += 3;
295 }
296 else
297 {
298 // Checksum bytes aren't all here yet
299 end_idx = std::string::npos;
300 }
301 }
302 break;
303
304 default:
305 break;
306 }
307
308 if (end_idx == std::string::npos)
309 {
310 //ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
311 return;
312 }
313 else if (end_idx > 0)
314 {
315 // We have a valid packet...
316 assert (end_idx <= m_bytes.size());
317 std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
318 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
319 BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
320 m_bytes.erase(0, end_idx);
321 }
322 else
323 {
324 assert (1 <= m_bytes.size());
325 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
326 m_bytes.erase(0, 1);
327 }
328 }
329}
330