blob: a779db2575620c38cbaeb57c8759f61e6aa20305 [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
Greg Clayton72e1c782011-01-22 23:43:18 +0000514bool
515GDBRemoteCommunication::WaitForNotRunning (const TimeValue *timeout_ptr)
516{
517 return m_public_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
518}
519
520bool
521GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
522{
523 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
524}
525
Chris Lattner24943d22010-06-08 16:52:24 +0000526size_t
527GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, uint32_t timeout_seconds)
528{
Greg Claytoncecf3482011-01-20 07:53:45 +0000529 Mutex::Locker locker(m_sequence_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000530 TimeValue timeout_time;
531 timeout_time = TimeValue::Now();
532 timeout_time.OffsetWithSeconds (timeout_seconds);
533 return WaitForPacketNoLock (response, &timeout_time);
534}
535
536size_t
Greg Clayton72e1c782011-01-22 23:43:18 +0000537GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000538{
539 Mutex::Locker locker(m_sequence_mutex);
540 return WaitForPacketNoLock (response, timeout_time_ptr);
541}
542
543size_t
Greg Clayton72e1c782011-01-22 23:43:18 +0000544GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &response, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000545{
546 bool checksum_error = false;
547 response.Clear ();
548
549 EventSP event_sp;
550
551 if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
552 {
553 const uint32_t event_type = event_sp->GetType();
554 if (event_type | Communication::eBroadcastBitPacketAvailable)
555 {
556 const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
557 if (event_bytes)
558 {
559 const char * packet_data = (const char *)event_bytes->GetBytes();
560 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "read packet: %s", packet_data);
561 const size_t packet_size = event_bytes->GetByteSize();
562 if (packet_data && packet_size > 0)
563 {
564 std::string &response_str = response.GetStringRef();
565 if (packet_data[0] == '$')
566 {
Greg Clayton4862fa22011-01-08 03:17:57 +0000567 bool success = false;
568 if (packet_size < 4)
569 ::fprintf (stderr, "Packet that starts with $ is too short: '%s'\n", packet_data);
570 else if (packet_data[packet_size-3] != '#' ||
571 !::isxdigit (packet_data[packet_size-2]) ||
572 !::isxdigit (packet_data[packet_size-1]))
573 ::fprintf (stderr, "Invalid checksum footer for packet: '%s'\n", packet_data);
574 else
575 success = true;
576
577 if (success)
578 response_str.assign (packet_data + 1, packet_size - 4);
Chris Lattner24943d22010-06-08 16:52:24 +0000579 if (m_send_acks)
580 {
581 char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
Greg Clayton53d68e72010-07-20 22:52:08 +0000582 char actual_checksum = CalculcateChecksum (&response_str[0], response_str.size());
Chris Lattner24943d22010-06-08 16:52:24 +0000583 checksum_error = packet_checksum != actual_checksum;
584 // Send the ack or nack if needed
Greg Clayton4862fa22011-01-08 03:17:57 +0000585 if (checksum_error || !success)
Greg Claytona4881d02011-01-22 07:12:45 +0000586 SendNack();
Chris Lattner24943d22010-06-08 16:52:24 +0000587 else
Greg Claytona4881d02011-01-22 07:12:45 +0000588 SendAck();
Chris Lattner24943d22010-06-08 16:52:24 +0000589 }
590 }
591 else
592 {
593 response_str.assign (packet_data, packet_size);
594 }
595 return response_str.size();
596 }
597 }
598 }
599 else if (Communication::eBroadcastBitReadThreadDidExit)
600 {
601 // Our read thread exited on us so just fall through and return zero...
602 }
603 }
604 return 0;
605}
606
607void
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000608GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast,
609 ConnectionStatus status)
Chris Lattner24943d22010-06-08 16:52:24 +0000610{
611 // Put the packet data into the buffer in a thread safe fashion
612 Mutex::Locker locker(m_bytes_mutex);
613 m_bytes.append ((const char *)src, src_len);
614
615 // Parse up the packets into gdb remote packets
616 while (!m_bytes.empty())
617 {
618 // end_idx must be one past the last valid packet byte. Start
619 // it off with an invalid value that is the same as the current
620 // index.
621 size_t end_idx = 0;
622
623 switch (m_bytes[0])
624 {
625 case '+': // Look for ack
626 case '-': // Look for cancel
627 case '\x03': // ^C to halt target
628 end_idx = 1; // The command is one byte long...
629 break;
630
631 case '$':
632 // Look for a standard gdb packet?
633 end_idx = m_bytes.find('#');
634 if (end_idx != std::string::npos)
635 {
636 if (end_idx + 2 < m_bytes.size())
637 {
638 end_idx += 3;
639 }
640 else
641 {
642 // Checksum bytes aren't all here yet
643 end_idx = std::string::npos;
644 }
645 }
646 break;
647
648 default:
649 break;
650 }
651
652 if (end_idx == std::string::npos)
653 {
654 //ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
655 return;
656 }
657 else if (end_idx > 0)
658 {
659 // We have a valid packet...
660 assert (end_idx <= m_bytes.size());
661 std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
662 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
663 BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
664 m_bytes.erase(0, end_idx);
665 }
666 else
667 {
668 assert (1 <= m_bytes.size());
669 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
670 m_bytes.erase(0, 1);
671 }
672 }
673}
674
675lldb::pid_t
676GDBRemoteCommunication::GetCurrentProcessID (uint32_t timeout_seconds)
677{
678 StringExtractorGDBRemote response;
679 if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, timeout_seconds, false))
680 {
681 if (response.GetChar() == 'Q')
682 if (response.GetChar() == 'C')
683 return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
684 }
685 return LLDB_INVALID_PROCESS_ID;
686}
687
688bool
689GDBRemoteCommunication::GetLaunchSuccess (uint32_t timeout_seconds, std::string &error_str)
690{
691 error_str.clear();
692 StringExtractorGDBRemote response;
693 if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, timeout_seconds, false))
694 {
695 if (response.IsOKPacket())
696 return true;
697 if (response.GetChar() == 'E')
698 {
699 // A string the describes what failed when launching...
700 error_str = response.GetStringRef().substr(1);
701 }
702 else
703 {
704 error_str.assign ("unknown error occurred launching process");
705 }
706 }
707 else
708 {
709 error_str.assign ("failed to send the qLaunchSuccess packet");
710 }
711 return false;
712}
713
714int
715GDBRemoteCommunication::SendArgumentsPacket (char const *argv[], uint32_t timeout_seconds)
716{
717 if (argv && argv[0])
718 {
719 StreamString packet;
720 packet.PutChar('A');
721 const char *arg;
722 for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i)
723 {
724 const int arg_len = strlen(arg);
725 if (i > 0)
726 packet.PutChar(',');
727 packet.Printf("%i,%i,", arg_len * 2, i);
728 packet.PutBytesAsRawHex8(arg, arg_len, eByteOrderHost, eByteOrderHost);
729 }
730
731 StringExtractorGDBRemote response;
732 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
733 {
734 if (response.IsOKPacket())
735 return 0;
736 uint8_t error = response.GetError();
737 if (error)
738 return error;
739 }
740 }
741 return -1;
742}
743
744int
745GDBRemoteCommunication::SendEnvironmentPacket (char const *name_equal_value, uint32_t timeout_seconds)
746{
747 if (name_equal_value && name_equal_value[0])
748 {
749 StreamString packet;
750 packet.Printf("QEnvironment:%s", name_equal_value);
751 StringExtractorGDBRemote response;
752 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
753 {
754 if (response.IsOKPacket())
755 return 0;
756 uint8_t error = response.GetError();
757 if (error)
758 return error;
759 }
760 }
761 return -1;
762}
763
764bool
765GDBRemoteCommunication::GetHostInfo (uint32_t timeout_seconds)
766{
767 m_arch.Clear();
768 m_os.Clear();
769 m_vendor.Clear();
770 m_byte_order = eByteOrderHost;
771 m_pointer_byte_size = 0;
772
773 StringExtractorGDBRemote response;
774 if (SendPacketAndWaitForResponse ("qHostInfo", response, timeout_seconds, false))
775 {
776 if (response.IsUnsupportedPacket())
777 return false;
778
779
780 std::string name;
781 std::string value;
782 while (response.GetNameColonValue(name, value))
783 {
784 if (name.compare("cputype") == 0)
785 {
786 // exception type in big endian hex
787 m_arch.SetCPUType(Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0));
788 }
789 else if (name.compare("cpusubtype") == 0)
790 {
791 // exception count in big endian hex
792 m_arch.SetCPUSubtype(Args::StringToUInt32 (value.c_str(), 0, 0));
793 }
794 else if (name.compare("ostype") == 0)
795 {
796 // exception data in big endian hex
797 m_os.SetCString(value.c_str());
798 }
799 else if (name.compare("vendor") == 0)
800 {
801 m_vendor.SetCString(value.c_str());
802 }
803 else if (name.compare("endian") == 0)
804 {
805 if (value.compare("little") == 0)
806 m_byte_order = eByteOrderLittle;
807 else if (value.compare("big") == 0)
808 m_byte_order = eByteOrderBig;
809 else if (value.compare("pdp") == 0)
810 m_byte_order = eByteOrderPDP;
811 }
812 else if (name.compare("ptrsize") == 0)
813 {
814 m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
815 }
816 }
817 }
818 return HostInfoIsValid();
819}
820
821int
822GDBRemoteCommunication::SendAttach
823(
824 lldb::pid_t pid,
825 uint32_t timeout_seconds,
826 StringExtractorGDBRemote& response
827)
828{
829 if (pid != LLDB_INVALID_PROCESS_ID)
830 {
831 StreamString packet;
832 packet.Printf("vAttach;%x", pid);
833
834 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
835 {
836 if (response.IsErrorPacket())
837 return response.GetError();
838 return 0;
839 }
840 }
841 return -1;
842}
843
844const lldb_private::ArchSpec &
845GDBRemoteCommunication::GetHostArchitecture ()
846{
847 if (!HostInfoIsValid ())
848 GetHostInfo (1);
849 return m_arch;
850}
851
852const lldb_private::ConstString &
853GDBRemoteCommunication::GetOSString ()
854{
855 if (!HostInfoIsValid ())
856 GetHostInfo (1);
857 return m_os;
858}
859
860const lldb_private::ConstString &
861GDBRemoteCommunication::GetVendorString()
862{
863 if (!HostInfoIsValid ())
864 GetHostInfo (1);
865 return m_vendor;
866}
867
868lldb::ByteOrder
869GDBRemoteCommunication::GetByteOrder ()
870{
871 if (!HostInfoIsValid ())
872 GetHostInfo (1);
873 return m_byte_order;
874}
875
876uint32_t
877GDBRemoteCommunication::GetAddressByteSize ()
878{
879 if (!HostInfoIsValid ())
880 GetHostInfo (1);
881 return m_pointer_byte_size;
882}
883
884addr_t
885GDBRemoteCommunication::AllocateMemory (size_t size, uint32_t permissions, uint32_t timeout_seconds)
886{
887 char packet[64];
888 ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
889 permissions & lldb::ePermissionsReadable ? "r" : "",
890 permissions & lldb::ePermissionsWritable ? "w" : "",
891 permissions & lldb::ePermissionsExecutable ? "x" : "");
892 StringExtractorGDBRemote response;
893 if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
894 {
895 if (!response.IsErrorPacket())
896 return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
897 }
898 return LLDB_INVALID_ADDRESS;
899}
900
901bool
902GDBRemoteCommunication::DeallocateMemory (addr_t addr, uint32_t timeout_seconds)
903{
904 char packet[64];
905 snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
906 StringExtractorGDBRemote response;
907 if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
908 {
Sean Callanan6a925532011-01-13 08:53:35 +0000909 if (response.IsOKPacket())
Chris Lattner24943d22010-06-08 16:52:24 +0000910 return true;
911 }
912 return false;
913}
Jim Ingham3ae449a2010-11-17 02:32:00 +0000914