blob: 15ab58975ccd99b9a4236005b031ddba1276e206 [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
14// C++ Includes
15// Other libraries and framework includes
Chris Lattner24943d22010-06-08 16:52:24 +000016#include "lldb/Core/Log.h"
Chris Lattner24943d22010-06-08 16:52:24 +000017#include "lldb/Core/StreamString.h"
18#include "lldb/Host/TimeValue.h"
19
20// Project includes
Chris Lattner24943d22010-06-08 16:52:24 +000021#include "ProcessGDBRemoteLog.h"
22
23using namespace lldb;
24using namespace lldb_private;
25
26//----------------------------------------------------------------------
27// GDBRemoteCommunication constructor
28//----------------------------------------------------------------------
Greg Clayton61d043b2011-03-22 04:00:09 +000029GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, const char *listener_name) :
30 Communication(comm_name),
Greg Claytonc97bfdb2011-03-10 02:26:48 +000031 m_packet_timeout (1),
Greg Clayton61d043b2011-03-22 04:00:09 +000032 m_rx_packet_listener (listener_name),
Chris Lattner24943d22010-06-08 16:52:24 +000033 m_sequence_mutex (Mutex::eMutexTypeRecursive),
Greg Claytoncecf3482011-01-20 07:53:45 +000034 m_public_is_running (false),
Greg Clayton58e26e02011-03-24 04:28:38 +000035 m_private_is_running (false),
36 m_send_acks (true)
Chris Lattner24943d22010-06-08 16:52:24 +000037{
38 m_rx_packet_listener.StartListeningForEvents(this,
39 Communication::eBroadcastBitPacketAvailable |
40 Communication::eBroadcastBitReadThreadDidExit);
41}
42
43//----------------------------------------------------------------------
44// Destructor
45//----------------------------------------------------------------------
46GDBRemoteCommunication::~GDBRemoteCommunication()
47{
48 m_rx_packet_listener.StopListeningForEvents(this,
49 Communication::eBroadcastBitPacketAvailable |
50 Communication::eBroadcastBitReadThreadDidExit);
51 if (IsConnected())
52 {
53 StopReadThread();
54 Disconnect();
55 }
56}
57
58
59char
60GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
61{
62 int checksum = 0;
63
64 // We only need to compute the checksum if we are sending acks
Greg Claytonc1f45872011-02-12 06:28:37 +000065 if (GetSendAcks ())
Chris Lattner24943d22010-06-08 16:52:24 +000066 {
Greg Clayton54e7afa2010-07-09 20:39:50 +000067 for (size_t i = 0; i < payload_length; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +000068 checksum += payload[i];
69 }
70 return checksum & 255;
71}
72
73size_t
Greg Claytona4881d02011-01-22 07:12:45 +000074GDBRemoteCommunication::SendAck ()
Chris Lattner24943d22010-06-08 16:52:24 +000075{
Greg Clayton0bfda0b2011-02-05 02:25:06 +000076 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
77 if (log)
78 log->Printf ("send packet: +");
Chris Lattner24943d22010-06-08 16:52:24 +000079 ConnectionStatus status = eConnectionStatusSuccess;
Greg Claytona4881d02011-01-22 07:12:45 +000080 char ack_char = '+';
Chris Lattner24943d22010-06-08 16:52:24 +000081 return Write (&ack_char, 1, status, NULL) == 1;
82}
83
84size_t
Greg Claytona4881d02011-01-22 07:12:45 +000085GDBRemoteCommunication::SendNack ()
86{
Greg Clayton0bfda0b2011-02-05 02:25:06 +000087 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
88 if (log)
89 log->Printf ("send packet: -");
Greg Claytona4881d02011-01-22 07:12:45 +000090 ConnectionStatus status = eConnectionStatusSuccess;
91 char nack_char = '-';
92 return Write (&nack_char, 1, status, NULL) == 1;
93}
94
Chris Lattner24943d22010-06-08 16:52:24 +000095size_t
96GDBRemoteCommunication::SendPacket (const char *payload)
97{
98 Mutex::Locker locker(m_sequence_mutex);
99 return SendPacketNoLock (payload, ::strlen (payload));
100}
101
102size_t
103GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
104{
105 Mutex::Locker locker(m_sequence_mutex);
106 return SendPacketNoLock (payload, payload_length);
107}
108
109size_t
110GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
111{
112 if (IsConnected())
113 {
114 StreamString packet(0, 4, eByteOrderBig);
115
116 packet.PutChar('$');
117 packet.Write (payload, payload_length);
118 packet.PutChar('#');
119 packet.PutHex8(CalculcateChecksum (payload, payload_length));
120
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000121 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
122 if (log)
123 log->Printf ("send packet: %s", packet.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000124 ConnectionStatus status = eConnectionStatusSuccess;
125 size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
126 if (bytes_written == packet.GetSize())
127 {
Greg Claytonc1f45872011-02-12 06:28:37 +0000128 if (GetSendAcks ())
Greg Clayton54e7afa2010-07-09 20:39:50 +0000129 {
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000130 if (GetAck () != '+')
Greg Clayton58e26e02011-03-24 04:28:38 +0000131 {
132 printf("get ack failed...");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000133 return 0;
Greg Clayton58e26e02011-03-24 04:28:38 +0000134 }
Greg Clayton54e7afa2010-07-09 20:39:50 +0000135 }
Chris Lattner24943d22010-06-08 16:52:24 +0000136 }
Johnny Chen515ea542010-09-14 22:10:43 +0000137 else
138 {
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000139 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
140 if (log)
141 log->Printf ("error: failed to send packet: %s", packet.GetData());
Johnny Chen515ea542010-09-14 22:10:43 +0000142 }
Chris Lattner24943d22010-06-08 16:52:24 +0000143 return bytes_written;
Greg Claytoneea26402010-09-14 23:36:40 +0000144 }
Chris Lattner24943d22010-06-08 16:52:24 +0000145 return 0;
146}
147
148char
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000149GDBRemoteCommunication::GetAck ()
Chris Lattner24943d22010-06-08 16:52:24 +0000150{
Greg Clayton61d043b2011-03-22 04:00:09 +0000151 StringExtractorGDBRemote packet;
152 if (WaitForPacket (packet, m_packet_timeout) == 1)
153 return packet.GetChar();
Chris Lattner24943d22010-06-08 16:52:24 +0000154 return 0;
155}
156
157bool
158GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
159{
160 return locker.TryLock (m_sequence_mutex.GetMutex());
161}
162
Chris Lattner24943d22010-06-08 16:52:24 +0000163
Greg Clayton72e1c782011-01-22 23:43:18 +0000164bool
Greg Clayton72e1c782011-01-22 23:43:18 +0000165GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
166{
167 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
168}
169
Chris Lattner24943d22010-06-08 16:52:24 +0000170size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000171GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, uint32_t timeout_seconds)
Chris Lattner24943d22010-06-08 16:52:24 +0000172{
Greg Claytoncecf3482011-01-20 07:53:45 +0000173 Mutex::Locker locker(m_sequence_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000174 TimeValue timeout_time;
175 timeout_time = TimeValue::Now();
176 timeout_time.OffsetWithSeconds (timeout_seconds);
Greg Clayton61d043b2011-03-22 04:00:09 +0000177 return WaitForPacketNoLock (packet, &timeout_time);
Chris Lattner24943d22010-06-08 16:52:24 +0000178}
179
180size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000181GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000182{
183 Mutex::Locker locker(m_sequence_mutex);
Greg Clayton61d043b2011-03-22 04:00:09 +0000184 return WaitForPacketNoLock (packet, timeout_time_ptr);
Chris Lattner24943d22010-06-08 16:52:24 +0000185}
186
187size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000188GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000189{
190 bool checksum_error = false;
Greg Clayton61d043b2011-03-22 04:00:09 +0000191 packet.Clear ();
Chris Lattner24943d22010-06-08 16:52:24 +0000192
193 EventSP event_sp;
194
195 if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
196 {
197 const uint32_t event_type = event_sp->GetType();
198 if (event_type | Communication::eBroadcastBitPacketAvailable)
199 {
200 const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
201 if (event_bytes)
202 {
203 const char * packet_data = (const char *)event_bytes->GetBytes();
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000204 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
205 if (log)
206 log->Printf ("read packet: %s", packet_data);
Chris Lattner24943d22010-06-08 16:52:24 +0000207 const size_t packet_size = event_bytes->GetByteSize();
208 if (packet_data && packet_size > 0)
209 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000210 std::string &packet_str = packet.GetStringRef();
Chris Lattner24943d22010-06-08 16:52:24 +0000211 if (packet_data[0] == '$')
212 {
Greg Clayton4862fa22011-01-08 03:17:57 +0000213 bool success = false;
214 if (packet_size < 4)
215 ::fprintf (stderr, "Packet that starts with $ is too short: '%s'\n", packet_data);
216 else if (packet_data[packet_size-3] != '#' ||
217 !::isxdigit (packet_data[packet_size-2]) ||
218 !::isxdigit (packet_data[packet_size-1]))
219 ::fprintf (stderr, "Invalid checksum footer for packet: '%s'\n", packet_data);
220 else
221 success = true;
222
223 if (success)
Greg Clayton61d043b2011-03-22 04:00:09 +0000224 packet_str.assign (packet_data + 1, packet_size - 4);
Greg Claytonc1f45872011-02-12 06:28:37 +0000225 if (GetSendAcks ())
Chris Lattner24943d22010-06-08 16:52:24 +0000226 {
227 char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
Greg Clayton61d043b2011-03-22 04:00:09 +0000228 char actual_checksum = CalculcateChecksum (&packet_str[0], packet_str.size());
Chris Lattner24943d22010-06-08 16:52:24 +0000229 checksum_error = packet_checksum != actual_checksum;
230 // Send the ack or nack if needed
Greg Clayton4862fa22011-01-08 03:17:57 +0000231 if (checksum_error || !success)
Greg Claytona4881d02011-01-22 07:12:45 +0000232 SendNack();
Chris Lattner24943d22010-06-08 16:52:24 +0000233 else
Greg Claytona4881d02011-01-22 07:12:45 +0000234 SendAck();
Chris Lattner24943d22010-06-08 16:52:24 +0000235 }
236 }
237 else
238 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000239 packet_str.assign (packet_data, packet_size);
Chris Lattner24943d22010-06-08 16:52:24 +0000240 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000241 return packet_str.size();
Chris Lattner24943d22010-06-08 16:52:24 +0000242 }
243 }
244 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000245 else if (event_type | Communication::eBroadcastBitReadThreadDidExit)
Chris Lattner24943d22010-06-08 16:52:24 +0000246 {
247 // Our read thread exited on us so just fall through and return zero...
Greg Clayton58e26e02011-03-24 04:28:38 +0000248 Disconnect();
Chris Lattner24943d22010-06-08 16:52:24 +0000249 }
250 }
251 return 0;
252}
253
254void
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000255GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast,
256 ConnectionStatus status)
Chris Lattner24943d22010-06-08 16:52:24 +0000257{
258 // Put the packet data into the buffer in a thread safe fashion
259 Mutex::Locker locker(m_bytes_mutex);
260 m_bytes.append ((const char *)src, src_len);
261
262 // Parse up the packets into gdb remote packets
263 while (!m_bytes.empty())
264 {
265 // end_idx must be one past the last valid packet byte. Start
266 // it off with an invalid value that is the same as the current
267 // index.
268 size_t end_idx = 0;
269
270 switch (m_bytes[0])
271 {
272 case '+': // Look for ack
273 case '-': // Look for cancel
274 case '\x03': // ^C to halt target
275 end_idx = 1; // The command is one byte long...
276 break;
277
278 case '$':
279 // Look for a standard gdb packet?
280 end_idx = m_bytes.find('#');
281 if (end_idx != std::string::npos)
282 {
283 if (end_idx + 2 < m_bytes.size())
284 {
285 end_idx += 3;
286 }
287 else
288 {
289 // Checksum bytes aren't all here yet
290 end_idx = std::string::npos;
291 }
292 }
293 break;
294
295 default:
296 break;
297 }
298
299 if (end_idx == std::string::npos)
300 {
301 //ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
302 return;
303 }
304 else if (end_idx > 0)
305 {
306 // We have a valid packet...
307 assert (end_idx <= m_bytes.size());
308 std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
309 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
310 BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
311 m_bytes.erase(0, end_idx);
312 }
313 else
314 {
315 assert (1 <= m_bytes.size());
316 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
317 m_bytes.erase(0, 1);
318 }
319 }
320}
321