blob: 38b823f77aa92b5a1cf3e6d84dff377846f47c15 [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
Jim Ingham84cdc152010-06-15 19:49:27 +000016#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000017#include "lldb/Core/ConnectionFileDescriptor.h"
18#include "lldb/Core/Log.h"
19#include "lldb/Core/State.h"
20#include "lldb/Core/StreamString.h"
21#include "lldb/Host/TimeValue.h"
22
23// Project includes
Greg Clayton54e7afa2010-07-09 20:39:50 +000024#include "Utility/StringExtractorGDBRemote.h"
Chris Lattner24943d22010-06-08 16:52:24 +000025#include "ProcessGDBRemote.h"
26#include "ProcessGDBRemoteLog.h"
27
28using namespace lldb;
29using namespace lldb_private;
30
31//----------------------------------------------------------------------
32// GDBRemoteCommunication constructor
33//----------------------------------------------------------------------
34GDBRemoteCommunication::GDBRemoteCommunication() :
Greg Claytoneecb0f32010-12-04 02:39:47 +000035 Communication("gdb-remote.packets"),
Chris Lattner24943d22010-06-08 16:52:24 +000036 m_send_acks (true),
Greg Claytonc71899e2011-01-18 19:36:39 +000037 m_thread_suffix_supported (false),
Chris Lattner24943d22010-06-08 16:52:24 +000038 m_rx_packet_listener ("gdbremote.rx_packet"),
39 m_sequence_mutex (Mutex::eMutexTypeRecursive),
Greg Claytoncecf3482011-01-20 07:53:45 +000040 m_public_is_running (false),
41 m_private_is_running (false),
Chris Lattner24943d22010-06-08 16:52:24 +000042 m_async_mutex (Mutex::eMutexTypeRecursive),
43 m_async_packet_predicate (false),
44 m_async_packet (),
45 m_async_response (),
46 m_async_timeout (UINT32_MAX),
47 m_async_signal (-1),
48 m_arch(),
49 m_os(),
50 m_vendor(),
51 m_byte_order(eByteOrderHost),
52 m_pointer_byte_size(0)
53{
54 m_rx_packet_listener.StartListeningForEvents(this,
55 Communication::eBroadcastBitPacketAvailable |
56 Communication::eBroadcastBitReadThreadDidExit);
57}
58
59//----------------------------------------------------------------------
60// Destructor
61//----------------------------------------------------------------------
62GDBRemoteCommunication::~GDBRemoteCommunication()
63{
64 m_rx_packet_listener.StopListeningForEvents(this,
65 Communication::eBroadcastBitPacketAvailable |
66 Communication::eBroadcastBitReadThreadDidExit);
67 if (IsConnected())
68 {
69 StopReadThread();
70 Disconnect();
71 }
72}
73
74
75char
76GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
77{
78 int checksum = 0;
79
80 // We only need to compute the checksum if we are sending acks
81 if (m_send_acks)
82 {
Greg Clayton54e7afa2010-07-09 20:39:50 +000083 for (size_t i = 0; i < payload_length; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +000084 checksum += payload[i];
85 }
86 return checksum & 255;
87}
88
89size_t
Greg Claytona4881d02011-01-22 07:12:45 +000090GDBRemoteCommunication::SendAck ()
Chris Lattner24943d22010-06-08 16:52:24 +000091{
Greg Claytona4881d02011-01-22 07:12:45 +000092 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: +");
Chris Lattner24943d22010-06-08 16:52:24 +000093 ConnectionStatus status = eConnectionStatusSuccess;
Greg Claytona4881d02011-01-22 07:12:45 +000094 char ack_char = '+';
Chris Lattner24943d22010-06-08 16:52:24 +000095 return Write (&ack_char, 1, status, NULL) == 1;
96}
97
98size_t
Greg Claytona4881d02011-01-22 07:12:45 +000099GDBRemoteCommunication::SendNack ()
100{
101 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: -");
102 ConnectionStatus status = eConnectionStatusSuccess;
103 char nack_char = '-';
104 return Write (&nack_char, 1, status, NULL) == 1;
105}
106
107size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000108GDBRemoteCommunication::SendPacketAndWaitForResponse
109(
110 const char *payload,
111 StringExtractorGDBRemote &response,
112 uint32_t timeout_seconds,
113 bool send_async
114)
115{
116 return SendPacketAndWaitForResponse (payload,
117 ::strlen (payload),
118 response,
119 timeout_seconds,
120 send_async);
121}
122
123size_t
124GDBRemoteCommunication::SendPacketAndWaitForResponse
125(
126 const char *payload,
127 size_t payload_length,
128 StringExtractorGDBRemote &response,
129 uint32_t timeout_seconds,
130 bool send_async
131)
132{
133 Mutex::Locker locker;
134 TimeValue timeout_time;
135 timeout_time = TimeValue::Now();
136 timeout_time.OffsetWithSeconds (timeout_seconds);
137
Greg Clayton1a679462010-09-03 19:15:43 +0000138 if (GetSequenceMutex (locker))
Chris Lattner24943d22010-06-08 16:52:24 +0000139 {
140 if (SendPacketNoLock (payload, strlen(payload)))
141 return WaitForPacketNoLock (response, &timeout_time);
142 }
143 else
144 {
145 if (send_async)
146 {
147 Mutex::Locker async_locker (m_async_mutex);
148 m_async_packet.assign(payload, payload_length);
149 m_async_timeout = timeout_seconds;
150 m_async_packet_predicate.SetValue (true, eBroadcastNever);
151
152 bool timed_out = false;
Greg Claytona4881d02011-01-22 07:12:45 +0000153 bool sent_interrupt = false;
154 if (SendInterrupt(locker, 1, sent_interrupt, timed_out))
Chris Lattner24943d22010-06-08 16:52:24 +0000155 {
156 if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out))
157 {
158 response = m_async_response;
159 return response.GetStringRef().size();
160 }
161 }
162// if (timed_out)
163// m_error.SetErrorString("Timeout.");
164// else
165// m_error.SetErrorString("Unknown error.");
166 }
167 else
168 {
169// m_error.SetErrorString("Sequence mutex is locked.");
170 }
171 }
172 return 0;
173}
174
175//template<typename _Tp>
176//class ScopedValueChanger
177//{
178//public:
Greg Clayton5d187e52011-01-08 20:28:42 +0000179// // Take a value reference and the value to assign it to when this class
Chris Lattner24943d22010-06-08 16:52:24 +0000180// // instance goes out of scope.
181// ScopedValueChanger (_Tp &value_ref, _Tp value) :
182// m_value_ref (value_ref),
183// m_value (value)
184// {
185// }
186//
187// // This object is going out of scope, change the value pointed to by
188// // m_value_ref to the value we got during construction which was stored in
189// // m_value;
190// ~ScopedValueChanger ()
191// {
192// m_value_ref = m_value;
193// }
194//protected:
Greg Clayton5d187e52011-01-08 20:28:42 +0000195// _Tp &m_value_ref; // A reference to the value we will change when this object destructs
Chris Lattner24943d22010-06-08 16:52:24 +0000196// _Tp m_value; // The value to assign to m_value_ref when this goes out of scope.
197//};
198
199StateType
200GDBRemoteCommunication::SendContinuePacketAndWaitForResponse
201(
202 ProcessGDBRemote *process,
203 const char *payload,
204 size_t packet_length,
205 StringExtractorGDBRemote &response
206)
207{
Greg Claytone005f2c2010-11-06 01:53:30 +0000208 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
209 LogSP async_log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_ASYNC));
Chris Lattner24943d22010-06-08 16:52:24 +0000210 if (log)
211 log->Printf ("GDBRemoteCommunication::%s ()", __FUNCTION__);
212
213 Mutex::Locker locker(m_sequence_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000214 StateType state = eStateRunning;
215
216 if (SendPacket(payload, packet_length) == 0)
217 state = eStateInvalid;
218
Greg Claytonb749a262010-12-03 06:02:24 +0000219 BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
Greg Claytoncecf3482011-01-20 07:53:45 +0000220 m_public_is_running.SetValue (true, eBroadcastNever);
221 m_private_is_running.SetValue (true, eBroadcastNever);
Jim Ingham3ae449a2010-11-17 02:32:00 +0000222
Chris Lattner24943d22010-06-08 16:52:24 +0000223 while (state == eStateRunning)
224 {
Caroline Tice926060e2010-10-29 21:48:37 +0000225 log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
Chris Lattner24943d22010-06-08 16:52:24 +0000226 if (log)
227 log->Printf ("GDBRemoteCommunication::%s () WaitForPacket(...)", __FUNCTION__);
228
229 if (WaitForPacket (response, (TimeValue*)NULL))
230 {
Caroline Tice926060e2010-10-29 21:48:37 +0000231 log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
232 async_log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000233 if (response.Empty())
234 state = eStateInvalid;
235 else
236 {
237 const char stop_type = response.GetChar();
238 if (log)
239 log->Printf ("GDBRemoteCommunication::%s () got '%c' packet", __FUNCTION__, stop_type);
240 switch (stop_type)
241 {
242 case 'T':
243 case 'S':
Greg Claytoncecf3482011-01-20 07:53:45 +0000244 // Privately notify any internal threads that we have stopped
245 // in case we wanted to interrupt our process, yet we might
246 // send a packet and continue without returning control to the
247 // user.
248 m_private_is_running.SetValue (false, eBroadcastAlways);
Chris Lattner24943d22010-06-08 16:52:24 +0000249 if (m_async_signal != -1)
250 {
Greg Claytonb4d1d332010-09-03 21:14:27 +0000251 if (async_log)
252 async_log->Printf ("async: send signo = %s", Host::GetSignalAsCString (m_async_signal));
253
Chris Lattner24943d22010-06-08 16:52:24 +0000254 // Save off the async signal we are supposed to send
255 const int async_signal = m_async_signal;
256 // Clear the async signal member so we don't end up
257 // sending the signal multiple times...
258 m_async_signal = -1;
259 // Check which signal we stopped with
260 uint8_t signo = response.GetHexU8(255);
261 if (signo == async_signal)
262 {
Greg Claytonb4d1d332010-09-03 21:14:27 +0000263 if (async_log)
264 async_log->Printf ("async: stopped with signal %s, we are done running", Host::GetSignalAsCString (signo));
265
Chris Lattner24943d22010-06-08 16:52:24 +0000266 // We already stopped with a signal that we wanted
267 // to stop with, so we are done
268 response.SetFilePos (0);
269 }
270 else
271 {
272 // We stopped with a different signal that the one
273 // we wanted to stop with, so now we must resume
274 // with the signal we want
275 char signal_packet[32];
276 int signal_packet_len = 0;
277 signal_packet_len = ::snprintf (signal_packet,
278 sizeof (signal_packet),
279 "C%2.2x",
280 async_signal);
281
Greg Claytonb4d1d332010-09-03 21:14:27 +0000282 if (async_log)
283 async_log->Printf ("async: stopped with signal %s, resume with %s",
284 Host::GetSignalAsCString (signo),
285 Host::GetSignalAsCString (async_signal));
286
Chris Lattner24943d22010-06-08 16:52:24 +0000287 if (SendPacket(signal_packet, signal_packet_len) == 0)
288 {
Greg Claytonb4d1d332010-09-03 21:14:27 +0000289 if (async_log)
290 async_log->Printf ("async: error: failed to resume with %s",
291 Host::GetSignalAsCString (async_signal));
Greg Claytoncecf3482011-01-20 07:53:45 +0000292 state = eStateExited;
Chris Lattner24943d22010-06-08 16:52:24 +0000293 break;
294 }
295 else
Greg Claytoncecf3482011-01-20 07:53:45 +0000296 {
297 m_private_is_running.SetValue (true, eBroadcastNever);
Chris Lattner24943d22010-06-08 16:52:24 +0000298 continue;
Greg Claytoncecf3482011-01-20 07:53:45 +0000299 }
Chris Lattner24943d22010-06-08 16:52:24 +0000300 }
301 }
302 else if (m_async_packet_predicate.GetValue())
303 {
Greg Claytonb4d1d332010-09-03 21:14:27 +0000304 if (async_log)
305 async_log->Printf ("async: send async packet: %s",
306 m_async_packet.c_str());
307
Chris Lattner24943d22010-06-08 16:52:24 +0000308 // We are supposed to send an asynchronous packet while
309 // we are running.
310 m_async_response.Clear();
311 if (!m_async_packet.empty())
312 {
Greg Clayton53d68e72010-07-20 22:52:08 +0000313 SendPacketAndWaitForResponse (&m_async_packet[0],
Chris Lattner24943d22010-06-08 16:52:24 +0000314 m_async_packet.size(),
315 m_async_response,
316 m_async_timeout,
317 false);
318 }
319 // Let the other thread that was trying to send the async
320 // packet know that the packet has been sent.
321 m_async_packet_predicate.SetValue(false, eBroadcastAlways);
322
Greg Claytonb4d1d332010-09-03 21:14:27 +0000323 if (async_log)
324 async_log->Printf ("async: resume after async response received: %s",
325 m_async_response.GetStringRef().c_str());
326
Chris Lattner24943d22010-06-08 16:52:24 +0000327 // Continue again
328 if (SendPacket("c", 1) == 0)
329 {
Greg Claytoncecf3482011-01-20 07:53:45 +0000330 // Failed to send the continue packet
331 state = eStateExited;
Chris Lattner24943d22010-06-08 16:52:24 +0000332 break;
333 }
334 else
Greg Claytoncecf3482011-01-20 07:53:45 +0000335 {
336 m_private_is_running.SetValue (true, eBroadcastNever);
Chris Lattner24943d22010-06-08 16:52:24 +0000337 continue;
Greg Claytoncecf3482011-01-20 07:53:45 +0000338 }
Chris Lattner24943d22010-06-08 16:52:24 +0000339 }
340 // Stop with signal and thread info
341 state = eStateStopped;
342 break;
343
344 case 'W':
345 // process exited
346 state = eStateExited;
347 break;
348
349 case 'O':
350 // STDOUT
351 {
352 std::string inferior_stdout;
353 inferior_stdout.reserve(response.GetBytesLeft () / 2);
354 char ch;
355 while ((ch = response.GetHexU8()) != '\0')
356 inferior_stdout.append(1, ch);
357 process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());
358 }
359 break;
360
361 case 'E':
362 // ERROR
363 state = eStateInvalid;
364 break;
365
366 default:
367 if (log)
368 log->Printf ("GDBRemoteCommunication::%s () got unrecognized async packet: '%s'", __FUNCTION__, stop_type);
369 break;
370 }
371 }
372 }
373 else
374 {
Caroline Tice926060e2010-10-29 21:48:37 +0000375 log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
Chris Lattner24943d22010-06-08 16:52:24 +0000376 if (log)
377 log->Printf ("GDBRemoteCommunication::%s () WaitForPacket(...) => false", __FUNCTION__);
378 state = eStateInvalid;
379 }
380 }
Caroline Tice926060e2010-10-29 21:48:37 +0000381 log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
Chris Lattner24943d22010-06-08 16:52:24 +0000382 if (log)
383 log->Printf ("GDBRemoteCommunication::%s () => %s", __FUNCTION__, StateAsCString(state));
384 response.SetFilePos(0);
Greg Claytoncecf3482011-01-20 07:53:45 +0000385 m_private_is_running.SetValue (false, eBroadcastAlways);
386 m_public_is_running.SetValue (false, eBroadcastAlways);
Chris Lattner24943d22010-06-08 16:52:24 +0000387 return state;
388}
389
390size_t
391GDBRemoteCommunication::SendPacket (const char *payload)
392{
393 Mutex::Locker locker(m_sequence_mutex);
394 return SendPacketNoLock (payload, ::strlen (payload));
395}
396
397size_t
398GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
399{
400 Mutex::Locker locker(m_sequence_mutex);
401 return SendPacketNoLock (payload, payload_length);
402}
403
404size_t
405GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
406{
407 if (IsConnected())
408 {
409 StreamString packet(0, 4, eByteOrderBig);
410
411 packet.PutChar('$');
412 packet.Write (payload, payload_length);
413 packet.PutChar('#');
414 packet.PutHex8(CalculcateChecksum (payload, payload_length));
415
416 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: %s", packet.GetData());
417 ConnectionStatus status = eConnectionStatusSuccess;
418 size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
419 if (bytes_written == packet.GetSize())
420 {
421 if (m_send_acks)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000422 {
423 if (GetAck (1) != '+')
424 return 0;
425 }
Chris Lattner24943d22010-06-08 16:52:24 +0000426 }
Johnny Chen515ea542010-09-14 22:10:43 +0000427 else
428 {
429 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "error: failed to send packet: %s", packet.GetData());
430 }
Chris Lattner24943d22010-06-08 16:52:24 +0000431 return bytes_written;
Greg Claytoneea26402010-09-14 23:36:40 +0000432 }
Chris Lattner24943d22010-06-08 16:52:24 +0000433 return 0;
434}
435
436char
437GDBRemoteCommunication::GetAck (uint32_t timeout_seconds)
438{
439 StringExtractorGDBRemote response;
440 if (WaitForPacket (response, timeout_seconds) == 1)
441 return response.GetChar();
442 return 0;
443}
444
445bool
446GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
447{
448 return locker.TryLock (m_sequence_mutex.GetMutex());
449}
450
451bool
452GDBRemoteCommunication::SendAsyncSignal (int signo)
453{
454 m_async_signal = signo;
455 bool timed_out = false;
Greg Claytona4881d02011-01-22 07:12:45 +0000456 bool sent_interrupt = false;
Greg Clayton1a679462010-09-03 19:15:43 +0000457 Mutex::Locker locker;
Greg Claytona4881d02011-01-22 07:12:45 +0000458 if (SendInterrupt (locker, 1, sent_interrupt, timed_out))
Chris Lattner24943d22010-06-08 16:52:24 +0000459 return true;
460 m_async_signal = -1;
461 return false;
462}
463
Greg Clayton1a679462010-09-03 19:15:43 +0000464// This function takes a mutex locker as a parameter in case the GetSequenceMutex
465// actually succeeds. If it doesn't succeed in acquiring the sequence mutex
466// (the expected result), then it will send the halt packet. If it does succeed
467// then the caller that requested the interrupt will want to keep the sequence
468// locked down so that no one else can send packets while the caller has control.
469// This function usually gets called when we are running and need to stop the
470// target. It can also be used when we are running and and we need to do something
471// else (like read/write memory), so we need to interrupt the running process
472// (gdb remote protocol requires this), and do what we need to do, then resume.
473
Chris Lattner24943d22010-06-08 16:52:24 +0000474bool
Greg Claytona4881d02011-01-22 07:12:45 +0000475GDBRemoteCommunication::SendInterrupt
476(
477 Mutex::Locker& locker,
478 uint32_t seconds_to_wait_for_stop,
479 bool &sent_interrupt,
480 bool &timed_out
481)
Chris Lattner24943d22010-06-08 16:52:24 +0000482{
Greg Claytona4881d02011-01-22 07:12:45 +0000483 sent_interrupt = false;
484 timed_out = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000485
486 if (IsConnected() && IsRunning())
487 {
488 // Only send an interrupt if our debugserver is running...
Greg Clayton1a679462010-09-03 19:15:43 +0000489 if (GetSequenceMutex (locker) == false)
Chris Lattner24943d22010-06-08 16:52:24 +0000490 {
491 // Someone has the mutex locked waiting for a response or for the
492 // inferior to stop, so send the interrupt on the down low...
493 char ctrl_c = '\x03';
494 ConnectionStatus status = eConnectionStatusSuccess;
495 TimeValue timeout;
496 if (seconds_to_wait_for_stop)
497 {
498 timeout = TimeValue::Now();
499 timeout.OffsetWithSeconds (seconds_to_wait_for_stop);
500 }
501 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: \\x03");
502 if (Write (&ctrl_c, 1, status, NULL) > 0)
503 {
Greg Claytona4881d02011-01-22 07:12:45 +0000504 sent_interrupt = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000505 if (seconds_to_wait_for_stop)
Greg Claytona4881d02011-01-22 07:12:45 +0000506 m_private_is_running.WaitForValueEqualTo (false, &timeout, &timed_out);
Chris Lattner24943d22010-06-08 16:52:24 +0000507 return true;
508 }
509 }
510 }
511 return false;
512}
513
514size_t
515GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, uint32_t timeout_seconds)
516{
Greg Claytoncecf3482011-01-20 07:53:45 +0000517 Mutex::Locker locker(m_sequence_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000518 TimeValue timeout_time;
519 timeout_time = TimeValue::Now();
520 timeout_time.OffsetWithSeconds (timeout_seconds);
521 return WaitForPacketNoLock (response, &timeout_time);
522}
523
524size_t
525GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, TimeValue* timeout_time_ptr)
526{
527 Mutex::Locker locker(m_sequence_mutex);
528 return WaitForPacketNoLock (response, timeout_time_ptr);
529}
530
531size_t
532GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &response, TimeValue* timeout_time_ptr)
533{
534 bool checksum_error = false;
535 response.Clear ();
536
537 EventSP event_sp;
538
539 if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
540 {
541 const uint32_t event_type = event_sp->GetType();
542 if (event_type | Communication::eBroadcastBitPacketAvailable)
543 {
544 const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
545 if (event_bytes)
546 {
547 const char * packet_data = (const char *)event_bytes->GetBytes();
548 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "read packet: %s", packet_data);
549 const size_t packet_size = event_bytes->GetByteSize();
550 if (packet_data && packet_size > 0)
551 {
552 std::string &response_str = response.GetStringRef();
553 if (packet_data[0] == '$')
554 {
Greg Clayton4862fa22011-01-08 03:17:57 +0000555 bool success = false;
556 if (packet_size < 4)
557 ::fprintf (stderr, "Packet that starts with $ is too short: '%s'\n", packet_data);
558 else if (packet_data[packet_size-3] != '#' ||
559 !::isxdigit (packet_data[packet_size-2]) ||
560 !::isxdigit (packet_data[packet_size-1]))
561 ::fprintf (stderr, "Invalid checksum footer for packet: '%s'\n", packet_data);
562 else
563 success = true;
564
565 if (success)
566 response_str.assign (packet_data + 1, packet_size - 4);
Chris Lattner24943d22010-06-08 16:52:24 +0000567 if (m_send_acks)
568 {
569 char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
Greg Clayton53d68e72010-07-20 22:52:08 +0000570 char actual_checksum = CalculcateChecksum (&response_str[0], response_str.size());
Chris Lattner24943d22010-06-08 16:52:24 +0000571 checksum_error = packet_checksum != actual_checksum;
572 // Send the ack or nack if needed
Greg Clayton4862fa22011-01-08 03:17:57 +0000573 if (checksum_error || !success)
Greg Claytona4881d02011-01-22 07:12:45 +0000574 SendNack();
Chris Lattner24943d22010-06-08 16:52:24 +0000575 else
Greg Claytona4881d02011-01-22 07:12:45 +0000576 SendAck();
Chris Lattner24943d22010-06-08 16:52:24 +0000577 }
578 }
579 else
580 {
581 response_str.assign (packet_data, packet_size);
582 }
583 return response_str.size();
584 }
585 }
586 }
587 else if (Communication::eBroadcastBitReadThreadDidExit)
588 {
589 // Our read thread exited on us so just fall through and return zero...
590 }
591 }
592 return 0;
593}
594
595void
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000596GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast,
597 ConnectionStatus status)
Chris Lattner24943d22010-06-08 16:52:24 +0000598{
599 // Put the packet data into the buffer in a thread safe fashion
600 Mutex::Locker locker(m_bytes_mutex);
601 m_bytes.append ((const char *)src, src_len);
602
603 // Parse up the packets into gdb remote packets
604 while (!m_bytes.empty())
605 {
606 // end_idx must be one past the last valid packet byte. Start
607 // it off with an invalid value that is the same as the current
608 // index.
609 size_t end_idx = 0;
610
611 switch (m_bytes[0])
612 {
613 case '+': // Look for ack
614 case '-': // Look for cancel
615 case '\x03': // ^C to halt target
616 end_idx = 1; // The command is one byte long...
617 break;
618
619 case '$':
620 // Look for a standard gdb packet?
621 end_idx = m_bytes.find('#');
622 if (end_idx != std::string::npos)
623 {
624 if (end_idx + 2 < m_bytes.size())
625 {
626 end_idx += 3;
627 }
628 else
629 {
630 // Checksum bytes aren't all here yet
631 end_idx = std::string::npos;
632 }
633 }
634 break;
635
636 default:
637 break;
638 }
639
640 if (end_idx == std::string::npos)
641 {
642 //ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
643 return;
644 }
645 else if (end_idx > 0)
646 {
647 // We have a valid packet...
648 assert (end_idx <= m_bytes.size());
649 std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
650 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
651 BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
652 m_bytes.erase(0, end_idx);
653 }
654 else
655 {
656 assert (1 <= m_bytes.size());
657 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
658 m_bytes.erase(0, 1);
659 }
660 }
661}
662
663lldb::pid_t
664GDBRemoteCommunication::GetCurrentProcessID (uint32_t timeout_seconds)
665{
666 StringExtractorGDBRemote response;
667 if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, timeout_seconds, false))
668 {
669 if (response.GetChar() == 'Q')
670 if (response.GetChar() == 'C')
671 return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
672 }
673 return LLDB_INVALID_PROCESS_ID;
674}
675
676bool
677GDBRemoteCommunication::GetLaunchSuccess (uint32_t timeout_seconds, std::string &error_str)
678{
679 error_str.clear();
680 StringExtractorGDBRemote response;
681 if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, timeout_seconds, false))
682 {
683 if (response.IsOKPacket())
684 return true;
685 if (response.GetChar() == 'E')
686 {
687 // A string the describes what failed when launching...
688 error_str = response.GetStringRef().substr(1);
689 }
690 else
691 {
692 error_str.assign ("unknown error occurred launching process");
693 }
694 }
695 else
696 {
697 error_str.assign ("failed to send the qLaunchSuccess packet");
698 }
699 return false;
700}
701
702int
703GDBRemoteCommunication::SendArgumentsPacket (char const *argv[], uint32_t timeout_seconds)
704{
705 if (argv && argv[0])
706 {
707 StreamString packet;
708 packet.PutChar('A');
709 const char *arg;
710 for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i)
711 {
712 const int arg_len = strlen(arg);
713 if (i > 0)
714 packet.PutChar(',');
715 packet.Printf("%i,%i,", arg_len * 2, i);
716 packet.PutBytesAsRawHex8(arg, arg_len, eByteOrderHost, eByteOrderHost);
717 }
718
719 StringExtractorGDBRemote response;
720 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
721 {
722 if (response.IsOKPacket())
723 return 0;
724 uint8_t error = response.GetError();
725 if (error)
726 return error;
727 }
728 }
729 return -1;
730}
731
732int
733GDBRemoteCommunication::SendEnvironmentPacket (char const *name_equal_value, uint32_t timeout_seconds)
734{
735 if (name_equal_value && name_equal_value[0])
736 {
737 StreamString packet;
738 packet.Printf("QEnvironment:%s", name_equal_value);
739 StringExtractorGDBRemote response;
740 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
741 {
742 if (response.IsOKPacket())
743 return 0;
744 uint8_t error = response.GetError();
745 if (error)
746 return error;
747 }
748 }
749 return -1;
750}
751
752bool
753GDBRemoteCommunication::GetHostInfo (uint32_t timeout_seconds)
754{
755 m_arch.Clear();
756 m_os.Clear();
757 m_vendor.Clear();
758 m_byte_order = eByteOrderHost;
759 m_pointer_byte_size = 0;
760
761 StringExtractorGDBRemote response;
762 if (SendPacketAndWaitForResponse ("qHostInfo", response, timeout_seconds, false))
763 {
764 if (response.IsUnsupportedPacket())
765 return false;
766
767
768 std::string name;
769 std::string value;
770 while (response.GetNameColonValue(name, value))
771 {
772 if (name.compare("cputype") == 0)
773 {
774 // exception type in big endian hex
775 m_arch.SetCPUType(Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0));
776 }
777 else if (name.compare("cpusubtype") == 0)
778 {
779 // exception count in big endian hex
780 m_arch.SetCPUSubtype(Args::StringToUInt32 (value.c_str(), 0, 0));
781 }
782 else if (name.compare("ostype") == 0)
783 {
784 // exception data in big endian hex
785 m_os.SetCString(value.c_str());
786 }
787 else if (name.compare("vendor") == 0)
788 {
789 m_vendor.SetCString(value.c_str());
790 }
791 else if (name.compare("endian") == 0)
792 {
793 if (value.compare("little") == 0)
794 m_byte_order = eByteOrderLittle;
795 else if (value.compare("big") == 0)
796 m_byte_order = eByteOrderBig;
797 else if (value.compare("pdp") == 0)
798 m_byte_order = eByteOrderPDP;
799 }
800 else if (name.compare("ptrsize") == 0)
801 {
802 m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
803 }
804 }
805 }
806 return HostInfoIsValid();
807}
808
809int
810GDBRemoteCommunication::SendAttach
811(
812 lldb::pid_t pid,
813 uint32_t timeout_seconds,
814 StringExtractorGDBRemote& response
815)
816{
817 if (pid != LLDB_INVALID_PROCESS_ID)
818 {
819 StreamString packet;
820 packet.Printf("vAttach;%x", pid);
821
822 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
823 {
824 if (response.IsErrorPacket())
825 return response.GetError();
826 return 0;
827 }
828 }
829 return -1;
830}
831
832const lldb_private::ArchSpec &
833GDBRemoteCommunication::GetHostArchitecture ()
834{
835 if (!HostInfoIsValid ())
836 GetHostInfo (1);
837 return m_arch;
838}
839
840const lldb_private::ConstString &
841GDBRemoteCommunication::GetOSString ()
842{
843 if (!HostInfoIsValid ())
844 GetHostInfo (1);
845 return m_os;
846}
847
848const lldb_private::ConstString &
849GDBRemoteCommunication::GetVendorString()
850{
851 if (!HostInfoIsValid ())
852 GetHostInfo (1);
853 return m_vendor;
854}
855
856lldb::ByteOrder
857GDBRemoteCommunication::GetByteOrder ()
858{
859 if (!HostInfoIsValid ())
860 GetHostInfo (1);
861 return m_byte_order;
862}
863
864uint32_t
865GDBRemoteCommunication::GetAddressByteSize ()
866{
867 if (!HostInfoIsValid ())
868 GetHostInfo (1);
869 return m_pointer_byte_size;
870}
871
872addr_t
873GDBRemoteCommunication::AllocateMemory (size_t size, uint32_t permissions, uint32_t timeout_seconds)
874{
875 char packet[64];
876 ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
877 permissions & lldb::ePermissionsReadable ? "r" : "",
878 permissions & lldb::ePermissionsWritable ? "w" : "",
879 permissions & lldb::ePermissionsExecutable ? "x" : "");
880 StringExtractorGDBRemote response;
881 if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
882 {
883 if (!response.IsErrorPacket())
884 return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
885 }
886 return LLDB_INVALID_ADDRESS;
887}
888
889bool
890GDBRemoteCommunication::DeallocateMemory (addr_t addr, uint32_t timeout_seconds)
891{
892 char packet[64];
893 snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
894 StringExtractorGDBRemote response;
895 if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
896 {
Sean Callanan6a925532011-01-13 08:53:35 +0000897 if (response.IsOKPacket())
Chris Lattner24943d22010-06-08 16:52:24 +0000898 return true;
899 }
900 return false;
901}
Jim Ingham3ae449a2010-11-17 02:32:00 +0000902