blob: 707fe46c26f328b60a2a3c7b5f0870568a024dea [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 Clayton61d043b2011-03-22 04:00:09 +000035 m_private_is_running (false)
Chris Lattner24943d22010-06-08 16:52:24 +000036{
37 m_rx_packet_listener.StartListeningForEvents(this,
38 Communication::eBroadcastBitPacketAvailable |
39 Communication::eBroadcastBitReadThreadDidExit);
40}
41
42//----------------------------------------------------------------------
43// Destructor
44//----------------------------------------------------------------------
45GDBRemoteCommunication::~GDBRemoteCommunication()
46{
47 m_rx_packet_listener.StopListeningForEvents(this,
48 Communication::eBroadcastBitPacketAvailable |
49 Communication::eBroadcastBitReadThreadDidExit);
50 if (IsConnected())
51 {
52 StopReadThread();
53 Disconnect();
54 }
55}
56
57
58char
59GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
60{
61 int checksum = 0;
62
63 // We only need to compute the checksum if we are sending acks
Greg Claytonc1f45872011-02-12 06:28:37 +000064 if (GetSendAcks ())
Chris Lattner24943d22010-06-08 16:52:24 +000065 {
Greg Clayton54e7afa2010-07-09 20:39:50 +000066 for (size_t i = 0; i < payload_length; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +000067 checksum += payload[i];
68 }
69 return checksum & 255;
70}
71
72size_t
Greg Claytona4881d02011-01-22 07:12:45 +000073GDBRemoteCommunication::SendAck ()
Chris Lattner24943d22010-06-08 16:52:24 +000074{
Greg Clayton0bfda0b2011-02-05 02:25:06 +000075 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
76 if (log)
77 log->Printf ("send packet: +");
Chris Lattner24943d22010-06-08 16:52:24 +000078 ConnectionStatus status = eConnectionStatusSuccess;
Greg Claytona4881d02011-01-22 07:12:45 +000079 char ack_char = '+';
Chris Lattner24943d22010-06-08 16:52:24 +000080 return Write (&ack_char, 1, status, NULL) == 1;
81}
82
83size_t
Greg Claytona4881d02011-01-22 07:12:45 +000084GDBRemoteCommunication::SendNack ()
85{
Greg Clayton0bfda0b2011-02-05 02:25:06 +000086 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
87 if (log)
88 log->Printf ("send packet: -");
Greg Claytona4881d02011-01-22 07:12:45 +000089 ConnectionStatus status = eConnectionStatusSuccess;
90 char nack_char = '-';
91 return Write (&nack_char, 1, status, NULL) == 1;
92}
93
Chris Lattner24943d22010-06-08 16:52:24 +000094size_t
95GDBRemoteCommunication::SendPacket (const char *payload)
96{
97 Mutex::Locker locker(m_sequence_mutex);
98 return SendPacketNoLock (payload, ::strlen (payload));
99}
100
101size_t
102GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
103{
104 Mutex::Locker locker(m_sequence_mutex);
105 return SendPacketNoLock (payload, payload_length);
106}
107
108size_t
109GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
110{
111 if (IsConnected())
112 {
113 StreamString packet(0, 4, eByteOrderBig);
114
115 packet.PutChar('$');
116 packet.Write (payload, payload_length);
117 packet.PutChar('#');
118 packet.PutHex8(CalculcateChecksum (payload, payload_length));
119
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000120 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
121 if (log)
122 log->Printf ("send packet: %s", packet.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000123 ConnectionStatus status = eConnectionStatusSuccess;
124 size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
125 if (bytes_written == packet.GetSize())
126 {
Greg Claytonc1f45872011-02-12 06:28:37 +0000127 if (GetSendAcks ())
Greg Clayton54e7afa2010-07-09 20:39:50 +0000128 {
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000129 if (GetAck () != '+')
Greg Clayton54e7afa2010-07-09 20:39:50 +0000130 return 0;
131 }
Chris Lattner24943d22010-06-08 16:52:24 +0000132 }
Johnny Chen515ea542010-09-14 22:10:43 +0000133 else
134 {
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000135 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
136 if (log)
137 log->Printf ("error: failed to send packet: %s", packet.GetData());
Johnny Chen515ea542010-09-14 22:10:43 +0000138 }
Chris Lattner24943d22010-06-08 16:52:24 +0000139 return bytes_written;
Greg Claytoneea26402010-09-14 23:36:40 +0000140 }
Chris Lattner24943d22010-06-08 16:52:24 +0000141 return 0;
142}
143
144char
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000145GDBRemoteCommunication::GetAck ()
Chris Lattner24943d22010-06-08 16:52:24 +0000146{
Greg Clayton61d043b2011-03-22 04:00:09 +0000147 StringExtractorGDBRemote packet;
148 if (WaitForPacket (packet, m_packet_timeout) == 1)
149 return packet.GetChar();
Chris Lattner24943d22010-06-08 16:52:24 +0000150 return 0;
151}
152
153bool
154GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
155{
156 return locker.TryLock (m_sequence_mutex.GetMutex());
157}
158
Chris Lattner24943d22010-06-08 16:52:24 +0000159
Greg Clayton72e1c782011-01-22 23:43:18 +0000160bool
Greg Clayton72e1c782011-01-22 23:43:18 +0000161GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
162{
163 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
164}
165
Chris Lattner24943d22010-06-08 16:52:24 +0000166size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000167GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, uint32_t timeout_seconds)
Chris Lattner24943d22010-06-08 16:52:24 +0000168{
Greg Claytoncecf3482011-01-20 07:53:45 +0000169 Mutex::Locker locker(m_sequence_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000170 TimeValue timeout_time;
171 timeout_time = TimeValue::Now();
172 timeout_time.OffsetWithSeconds (timeout_seconds);
Greg Clayton61d043b2011-03-22 04:00:09 +0000173 return WaitForPacketNoLock (packet, &timeout_time);
Chris Lattner24943d22010-06-08 16:52:24 +0000174}
175
176size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000177GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000178{
179 Mutex::Locker locker(m_sequence_mutex);
Greg Clayton61d043b2011-03-22 04:00:09 +0000180 return WaitForPacketNoLock (packet, timeout_time_ptr);
Chris Lattner24943d22010-06-08 16:52:24 +0000181}
182
183size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000184GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000185{
186 bool checksum_error = false;
Greg Clayton61d043b2011-03-22 04:00:09 +0000187 packet.Clear ();
Chris Lattner24943d22010-06-08 16:52:24 +0000188
189 EventSP event_sp;
190
191 if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
192 {
193 const uint32_t event_type = event_sp->GetType();
194 if (event_type | Communication::eBroadcastBitPacketAvailable)
195 {
196 const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
197 if (event_bytes)
198 {
199 const char * packet_data = (const char *)event_bytes->GetBytes();
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000200 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
201 if (log)
202 log->Printf ("read packet: %s", packet_data);
Chris Lattner24943d22010-06-08 16:52:24 +0000203 const size_t packet_size = event_bytes->GetByteSize();
204 if (packet_data && packet_size > 0)
205 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000206 std::string &packet_str = packet.GetStringRef();
Chris Lattner24943d22010-06-08 16:52:24 +0000207 if (packet_data[0] == '$')
208 {
Greg Clayton4862fa22011-01-08 03:17:57 +0000209 bool success = false;
210 if (packet_size < 4)
211 ::fprintf (stderr, "Packet that starts with $ is too short: '%s'\n", packet_data);
212 else if (packet_data[packet_size-3] != '#' ||
213 !::isxdigit (packet_data[packet_size-2]) ||
214 !::isxdigit (packet_data[packet_size-1]))
215 ::fprintf (stderr, "Invalid checksum footer for packet: '%s'\n", packet_data);
216 else
217 success = true;
218
219 if (success)
Greg Clayton61d043b2011-03-22 04:00:09 +0000220 packet_str.assign (packet_data + 1, packet_size - 4);
Greg Claytonc1f45872011-02-12 06:28:37 +0000221 if (GetSendAcks ())
Chris Lattner24943d22010-06-08 16:52:24 +0000222 {
223 char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
Greg Clayton61d043b2011-03-22 04:00:09 +0000224 char actual_checksum = CalculcateChecksum (&packet_str[0], packet_str.size());
Chris Lattner24943d22010-06-08 16:52:24 +0000225 checksum_error = packet_checksum != actual_checksum;
226 // Send the ack or nack if needed
Greg Clayton4862fa22011-01-08 03:17:57 +0000227 if (checksum_error || !success)
Greg Claytona4881d02011-01-22 07:12:45 +0000228 SendNack();
Chris Lattner24943d22010-06-08 16:52:24 +0000229 else
Greg Claytona4881d02011-01-22 07:12:45 +0000230 SendAck();
Chris Lattner24943d22010-06-08 16:52:24 +0000231 }
232 }
233 else
234 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000235 packet_str.assign (packet_data, packet_size);
Chris Lattner24943d22010-06-08 16:52:24 +0000236 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000237 return packet_str.size();
Chris Lattner24943d22010-06-08 16:52:24 +0000238 }
239 }
240 }
241 else if (Communication::eBroadcastBitReadThreadDidExit)
242 {
243 // Our read thread exited on us so just fall through and return zero...
244 }
245 }
246 return 0;
247}
248
249void
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000250GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast,
251 ConnectionStatus status)
Chris Lattner24943d22010-06-08 16:52:24 +0000252{
253 // Put the packet data into the buffer in a thread safe fashion
254 Mutex::Locker locker(m_bytes_mutex);
255 m_bytes.append ((const char *)src, src_len);
256
257 // Parse up the packets into gdb remote packets
258 while (!m_bytes.empty())
259 {
260 // end_idx must be one past the last valid packet byte. Start
261 // it off with an invalid value that is the same as the current
262 // index.
263 size_t end_idx = 0;
264
265 switch (m_bytes[0])
266 {
267 case '+': // Look for ack
268 case '-': // Look for cancel
269 case '\x03': // ^C to halt target
270 end_idx = 1; // The command is one byte long...
271 break;
272
273 case '$':
274 // Look for a standard gdb packet?
275 end_idx = m_bytes.find('#');
276 if (end_idx != std::string::npos)
277 {
278 if (end_idx + 2 < m_bytes.size())
279 {
280 end_idx += 3;
281 }
282 else
283 {
284 // Checksum bytes aren't all here yet
285 end_idx = std::string::npos;
286 }
287 }
288 break;
289
290 default:
291 break;
292 }
293
294 if (end_idx == std::string::npos)
295 {
296 //ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
297 return;
298 }
299 else if (end_idx > 0)
300 {
301 // We have a valid packet...
302 assert (end_idx <= m_bytes.size());
303 std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
304 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
305 BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
306 m_bytes.erase(0, end_idx);
307 }
308 else
309 {
310 assert (1 <= m_bytes.size());
311 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
312 m_bytes.erase(0, 1);
313 }
314 }
315}
316