blob: 92e33b25771537d0f87b82f2effe51cd20f703cd [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
90GDBRemoteCommunication::SendAck (char ack_char)
91{
92 Mutex::Locker locker(m_sequence_mutex);
93 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: %c", ack_char);
94 ConnectionStatus status = eConnectionStatusSuccess;
95 return Write (&ack_char, 1, status, NULL) == 1;
96}
97
98size_t
99GDBRemoteCommunication::SendPacketAndWaitForResponse
100(
101 const char *payload,
102 StringExtractorGDBRemote &response,
103 uint32_t timeout_seconds,
104 bool send_async
105)
106{
107 return SendPacketAndWaitForResponse (payload,
108 ::strlen (payload),
109 response,
110 timeout_seconds,
111 send_async);
112}
113
114size_t
115GDBRemoteCommunication::SendPacketAndWaitForResponse
116(
117 const char *payload,
118 size_t payload_length,
119 StringExtractorGDBRemote &response,
120 uint32_t timeout_seconds,
121 bool send_async
122)
123{
124 Mutex::Locker locker;
125 TimeValue timeout_time;
126 timeout_time = TimeValue::Now();
127 timeout_time.OffsetWithSeconds (timeout_seconds);
128
Greg Clayton1a679462010-09-03 19:15:43 +0000129 if (GetSequenceMutex (locker))
Chris Lattner24943d22010-06-08 16:52:24 +0000130 {
131 if (SendPacketNoLock (payload, strlen(payload)))
132 return WaitForPacketNoLock (response, &timeout_time);
133 }
134 else
135 {
136 if (send_async)
137 {
138 Mutex::Locker async_locker (m_async_mutex);
139 m_async_packet.assign(payload, payload_length);
140 m_async_timeout = timeout_seconds;
141 m_async_packet_predicate.SetValue (true, eBroadcastNever);
142
143 bool timed_out = false;
Greg Clayton1a679462010-09-03 19:15:43 +0000144 if (SendInterrupt(locker, 1, &timed_out))
Chris Lattner24943d22010-06-08 16:52:24 +0000145 {
146 if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out))
147 {
148 response = m_async_response;
149 return response.GetStringRef().size();
150 }
151 }
152// if (timed_out)
153// m_error.SetErrorString("Timeout.");
154// else
155// m_error.SetErrorString("Unknown error.");
156 }
157 else
158 {
159// m_error.SetErrorString("Sequence mutex is locked.");
160 }
161 }
162 return 0;
163}
164
165//template<typename _Tp>
166//class ScopedValueChanger
167//{
168//public:
Greg Clayton5d187e52011-01-08 20:28:42 +0000169// // Take a value reference and the value to assign it to when this class
Chris Lattner24943d22010-06-08 16:52:24 +0000170// // instance goes out of scope.
171// ScopedValueChanger (_Tp &value_ref, _Tp value) :
172// m_value_ref (value_ref),
173// m_value (value)
174// {
175// }
176//
177// // This object is going out of scope, change the value pointed to by
178// // m_value_ref to the value we got during construction which was stored in
179// // m_value;
180// ~ScopedValueChanger ()
181// {
182// m_value_ref = m_value;
183// }
184//protected:
Greg Clayton5d187e52011-01-08 20:28:42 +0000185// _Tp &m_value_ref; // A reference to the value we will change when this object destructs
Chris Lattner24943d22010-06-08 16:52:24 +0000186// _Tp m_value; // The value to assign to m_value_ref when this goes out of scope.
187//};
188
189StateType
190GDBRemoteCommunication::SendContinuePacketAndWaitForResponse
191(
192 ProcessGDBRemote *process,
193 const char *payload,
194 size_t packet_length,
195 StringExtractorGDBRemote &response
196)
197{
Greg Claytone005f2c2010-11-06 01:53:30 +0000198 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
199 LogSP async_log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_ASYNC));
Chris Lattner24943d22010-06-08 16:52:24 +0000200 if (log)
201 log->Printf ("GDBRemoteCommunication::%s ()", __FUNCTION__);
202
203 Mutex::Locker locker(m_sequence_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000204 StateType state = eStateRunning;
205
206 if (SendPacket(payload, packet_length) == 0)
207 state = eStateInvalid;
208
Greg Claytonb749a262010-12-03 06:02:24 +0000209 BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
Greg Claytoncecf3482011-01-20 07:53:45 +0000210 m_public_is_running.SetValue (true, eBroadcastNever);
211 m_private_is_running.SetValue (true, eBroadcastNever);
Jim Ingham3ae449a2010-11-17 02:32:00 +0000212
Chris Lattner24943d22010-06-08 16:52:24 +0000213 while (state == eStateRunning)
214 {
Caroline Tice926060e2010-10-29 21:48:37 +0000215 log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
Chris Lattner24943d22010-06-08 16:52:24 +0000216 if (log)
217 log->Printf ("GDBRemoteCommunication::%s () WaitForPacket(...)", __FUNCTION__);
218
219 if (WaitForPacket (response, (TimeValue*)NULL))
220 {
Caroline Tice926060e2010-10-29 21:48:37 +0000221 log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
222 async_log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000223 if (response.Empty())
224 state = eStateInvalid;
225 else
226 {
227 const char stop_type = response.GetChar();
228 if (log)
229 log->Printf ("GDBRemoteCommunication::%s () got '%c' packet", __FUNCTION__, stop_type);
230 switch (stop_type)
231 {
232 case 'T':
233 case 'S':
Greg Claytoncecf3482011-01-20 07:53:45 +0000234 // Privately notify any internal threads that we have stopped
235 // in case we wanted to interrupt our process, yet we might
236 // send a packet and continue without returning control to the
237 // user.
238 m_private_is_running.SetValue (false, eBroadcastAlways);
Chris Lattner24943d22010-06-08 16:52:24 +0000239 if (m_async_signal != -1)
240 {
Greg Claytonb4d1d332010-09-03 21:14:27 +0000241 if (async_log)
242 async_log->Printf ("async: send signo = %s", Host::GetSignalAsCString (m_async_signal));
243
Chris Lattner24943d22010-06-08 16:52:24 +0000244 // Save off the async signal we are supposed to send
245 const int async_signal = m_async_signal;
246 // Clear the async signal member so we don't end up
247 // sending the signal multiple times...
248 m_async_signal = -1;
249 // Check which signal we stopped with
250 uint8_t signo = response.GetHexU8(255);
251 if (signo == async_signal)
252 {
Greg Claytonb4d1d332010-09-03 21:14:27 +0000253 if (async_log)
254 async_log->Printf ("async: stopped with signal %s, we are done running", Host::GetSignalAsCString (signo));
255
Chris Lattner24943d22010-06-08 16:52:24 +0000256 // We already stopped with a signal that we wanted
257 // to stop with, so we are done
258 response.SetFilePos (0);
259 }
260 else
261 {
262 // We stopped with a different signal that the one
263 // we wanted to stop with, so now we must resume
264 // with the signal we want
265 char signal_packet[32];
266 int signal_packet_len = 0;
267 signal_packet_len = ::snprintf (signal_packet,
268 sizeof (signal_packet),
269 "C%2.2x",
270 async_signal);
271
Greg Claytonb4d1d332010-09-03 21:14:27 +0000272 if (async_log)
273 async_log->Printf ("async: stopped with signal %s, resume with %s",
274 Host::GetSignalAsCString (signo),
275 Host::GetSignalAsCString (async_signal));
276
Chris Lattner24943d22010-06-08 16:52:24 +0000277 if (SendPacket(signal_packet, signal_packet_len) == 0)
278 {
Greg Claytonb4d1d332010-09-03 21:14:27 +0000279 if (async_log)
280 async_log->Printf ("async: error: failed to resume with %s",
281 Host::GetSignalAsCString (async_signal));
Greg Claytoncecf3482011-01-20 07:53:45 +0000282 state = eStateExited;
Chris Lattner24943d22010-06-08 16:52:24 +0000283 break;
284 }
285 else
Greg Claytoncecf3482011-01-20 07:53:45 +0000286 {
287 m_private_is_running.SetValue (true, eBroadcastNever);
Chris Lattner24943d22010-06-08 16:52:24 +0000288 continue;
Greg Claytoncecf3482011-01-20 07:53:45 +0000289 }
Chris Lattner24943d22010-06-08 16:52:24 +0000290 }
291 }
292 else if (m_async_packet_predicate.GetValue())
293 {
Greg Claytonb4d1d332010-09-03 21:14:27 +0000294 if (async_log)
295 async_log->Printf ("async: send async packet: %s",
296 m_async_packet.c_str());
297
Chris Lattner24943d22010-06-08 16:52:24 +0000298 // We are supposed to send an asynchronous packet while
299 // we are running.
300 m_async_response.Clear();
301 if (!m_async_packet.empty())
302 {
Greg Clayton53d68e72010-07-20 22:52:08 +0000303 SendPacketAndWaitForResponse (&m_async_packet[0],
Chris Lattner24943d22010-06-08 16:52:24 +0000304 m_async_packet.size(),
305 m_async_response,
306 m_async_timeout,
307 false);
308 }
309 // Let the other thread that was trying to send the async
310 // packet know that the packet has been sent.
311 m_async_packet_predicate.SetValue(false, eBroadcastAlways);
312
Greg Claytonb4d1d332010-09-03 21:14:27 +0000313 if (async_log)
314 async_log->Printf ("async: resume after async response received: %s",
315 m_async_response.GetStringRef().c_str());
316
Chris Lattner24943d22010-06-08 16:52:24 +0000317 // Continue again
318 if (SendPacket("c", 1) == 0)
319 {
Greg Claytoncecf3482011-01-20 07:53:45 +0000320 // Failed to send the continue packet
321 state = eStateExited;
Chris Lattner24943d22010-06-08 16:52:24 +0000322 break;
323 }
324 else
Greg Claytoncecf3482011-01-20 07:53:45 +0000325 {
326 m_private_is_running.SetValue (true, eBroadcastNever);
Chris Lattner24943d22010-06-08 16:52:24 +0000327 continue;
Greg Claytoncecf3482011-01-20 07:53:45 +0000328 }
Chris Lattner24943d22010-06-08 16:52:24 +0000329 }
330 // Stop with signal and thread info
331 state = eStateStopped;
332 break;
333
334 case 'W':
335 // process exited
336 state = eStateExited;
337 break;
338
339 case 'O':
340 // STDOUT
341 {
342 std::string inferior_stdout;
343 inferior_stdout.reserve(response.GetBytesLeft () / 2);
344 char ch;
345 while ((ch = response.GetHexU8()) != '\0')
346 inferior_stdout.append(1, ch);
347 process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());
348 }
349 break;
350
351 case 'E':
352 // ERROR
353 state = eStateInvalid;
354 break;
355
356 default:
357 if (log)
358 log->Printf ("GDBRemoteCommunication::%s () got unrecognized async packet: '%s'", __FUNCTION__, stop_type);
359 break;
360 }
361 }
362 }
363 else
364 {
Caroline Tice926060e2010-10-29 21:48:37 +0000365 log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
Chris Lattner24943d22010-06-08 16:52:24 +0000366 if (log)
367 log->Printf ("GDBRemoteCommunication::%s () WaitForPacket(...) => false", __FUNCTION__);
368 state = eStateInvalid;
369 }
370 }
Caroline Tice926060e2010-10-29 21:48:37 +0000371 log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
Chris Lattner24943d22010-06-08 16:52:24 +0000372 if (log)
373 log->Printf ("GDBRemoteCommunication::%s () => %s", __FUNCTION__, StateAsCString(state));
374 response.SetFilePos(0);
Greg Claytoncecf3482011-01-20 07:53:45 +0000375 m_private_is_running.SetValue (false, eBroadcastAlways);
376 m_public_is_running.SetValue (false, eBroadcastAlways);
Chris Lattner24943d22010-06-08 16:52:24 +0000377 return state;
378}
379
380size_t
381GDBRemoteCommunication::SendPacket (const char *payload)
382{
383 Mutex::Locker locker(m_sequence_mutex);
384 return SendPacketNoLock (payload, ::strlen (payload));
385}
386
387size_t
388GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
389{
390 Mutex::Locker locker(m_sequence_mutex);
391 return SendPacketNoLock (payload, payload_length);
392}
393
394size_t
395GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
396{
397 if (IsConnected())
398 {
399 StreamString packet(0, 4, eByteOrderBig);
400
401 packet.PutChar('$');
402 packet.Write (payload, payload_length);
403 packet.PutChar('#');
404 packet.PutHex8(CalculcateChecksum (payload, payload_length));
405
406 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: %s", packet.GetData());
407 ConnectionStatus status = eConnectionStatusSuccess;
408 size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
409 if (bytes_written == packet.GetSize())
410 {
411 if (m_send_acks)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000412 {
413 if (GetAck (1) != '+')
414 return 0;
415 }
Chris Lattner24943d22010-06-08 16:52:24 +0000416 }
Johnny Chen515ea542010-09-14 22:10:43 +0000417 else
418 {
419 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "error: failed to send packet: %s", packet.GetData());
420 }
Chris Lattner24943d22010-06-08 16:52:24 +0000421 return bytes_written;
Greg Claytoneea26402010-09-14 23:36:40 +0000422 }
Chris Lattner24943d22010-06-08 16:52:24 +0000423 return 0;
424}
425
426char
427GDBRemoteCommunication::GetAck (uint32_t timeout_seconds)
428{
429 StringExtractorGDBRemote response;
430 if (WaitForPacket (response, timeout_seconds) == 1)
431 return response.GetChar();
432 return 0;
433}
434
435bool
436GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
437{
438 return locker.TryLock (m_sequence_mutex.GetMutex());
439}
440
441bool
442GDBRemoteCommunication::SendAsyncSignal (int signo)
443{
444 m_async_signal = signo;
445 bool timed_out = false;
Greg Clayton1a679462010-09-03 19:15:43 +0000446 Mutex::Locker locker;
447 if (SendInterrupt (locker, 1, &timed_out))
Chris Lattner24943d22010-06-08 16:52:24 +0000448 return true;
449 m_async_signal = -1;
450 return false;
451}
452
Greg Clayton1a679462010-09-03 19:15:43 +0000453// This function takes a mutex locker as a parameter in case the GetSequenceMutex
454// actually succeeds. If it doesn't succeed in acquiring the sequence mutex
455// (the expected result), then it will send the halt packet. If it does succeed
456// then the caller that requested the interrupt will want to keep the sequence
457// locked down so that no one else can send packets while the caller has control.
458// This function usually gets called when we are running and need to stop the
459// target. It can also be used when we are running and and we need to do something
460// else (like read/write memory), so we need to interrupt the running process
461// (gdb remote protocol requires this), and do what we need to do, then resume.
462
Chris Lattner24943d22010-06-08 16:52:24 +0000463bool
Greg Clayton1a679462010-09-03 19:15:43 +0000464GDBRemoteCommunication::SendInterrupt (Mutex::Locker& locker, uint32_t seconds_to_wait_for_stop, bool *timed_out)
Chris Lattner24943d22010-06-08 16:52:24 +0000465{
466 if (timed_out)
467 *timed_out = false;
468
469 if (IsConnected() && IsRunning())
470 {
471 // Only send an interrupt if our debugserver is running...
Greg Clayton1a679462010-09-03 19:15:43 +0000472 if (GetSequenceMutex (locker) == false)
Chris Lattner24943d22010-06-08 16:52:24 +0000473 {
474 // Someone has the mutex locked waiting for a response or for the
475 // inferior to stop, so send the interrupt on the down low...
476 char ctrl_c = '\x03';
477 ConnectionStatus status = eConnectionStatusSuccess;
478 TimeValue timeout;
479 if (seconds_to_wait_for_stop)
480 {
481 timeout = TimeValue::Now();
482 timeout.OffsetWithSeconds (seconds_to_wait_for_stop);
483 }
484 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: \\x03");
485 if (Write (&ctrl_c, 1, status, NULL) > 0)
486 {
487 if (seconds_to_wait_for_stop)
Greg Claytoncecf3482011-01-20 07:53:45 +0000488 m_private_is_running.WaitForValueEqualTo (false, &timeout, timed_out);
Chris Lattner24943d22010-06-08 16:52:24 +0000489 return true;
490 }
491 }
492 }
493 return false;
494}
495
496size_t
497GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, uint32_t timeout_seconds)
498{
Greg Claytoncecf3482011-01-20 07:53:45 +0000499 Mutex::Locker locker(m_sequence_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000500 TimeValue timeout_time;
501 timeout_time = TimeValue::Now();
502 timeout_time.OffsetWithSeconds (timeout_seconds);
503 return WaitForPacketNoLock (response, &timeout_time);
504}
505
506size_t
507GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, TimeValue* timeout_time_ptr)
508{
509 Mutex::Locker locker(m_sequence_mutex);
510 return WaitForPacketNoLock (response, timeout_time_ptr);
511}
512
513size_t
514GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &response, TimeValue* timeout_time_ptr)
515{
516 bool checksum_error = false;
517 response.Clear ();
518
519 EventSP event_sp;
520
521 if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
522 {
523 const uint32_t event_type = event_sp->GetType();
524 if (event_type | Communication::eBroadcastBitPacketAvailable)
525 {
526 const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
527 if (event_bytes)
528 {
529 const char * packet_data = (const char *)event_bytes->GetBytes();
530 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "read packet: %s", packet_data);
531 const size_t packet_size = event_bytes->GetByteSize();
532 if (packet_data && packet_size > 0)
533 {
534 std::string &response_str = response.GetStringRef();
535 if (packet_data[0] == '$')
536 {
Greg Clayton4862fa22011-01-08 03:17:57 +0000537 bool success = false;
538 if (packet_size < 4)
539 ::fprintf (stderr, "Packet that starts with $ is too short: '%s'\n", packet_data);
540 else if (packet_data[packet_size-3] != '#' ||
541 !::isxdigit (packet_data[packet_size-2]) ||
542 !::isxdigit (packet_data[packet_size-1]))
543 ::fprintf (stderr, "Invalid checksum footer for packet: '%s'\n", packet_data);
544 else
545 success = true;
546
547 if (success)
548 response_str.assign (packet_data + 1, packet_size - 4);
Chris Lattner24943d22010-06-08 16:52:24 +0000549 if (m_send_acks)
550 {
551 char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
Greg Clayton53d68e72010-07-20 22:52:08 +0000552 char actual_checksum = CalculcateChecksum (&response_str[0], response_str.size());
Chris Lattner24943d22010-06-08 16:52:24 +0000553 checksum_error = packet_checksum != actual_checksum;
554 // Send the ack or nack if needed
Greg Clayton4862fa22011-01-08 03:17:57 +0000555 if (checksum_error || !success)
Chris Lattner24943d22010-06-08 16:52:24 +0000556 SendAck('-');
557 else
558 SendAck('+');
559 }
560 }
561 else
562 {
563 response_str.assign (packet_data, packet_size);
564 }
565 return response_str.size();
566 }
567 }
568 }
569 else if (Communication::eBroadcastBitReadThreadDidExit)
570 {
571 // Our read thread exited on us so just fall through and return zero...
572 }
573 }
574 return 0;
575}
576
577void
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000578GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast,
579 ConnectionStatus status)
Chris Lattner24943d22010-06-08 16:52:24 +0000580{
581 // Put the packet data into the buffer in a thread safe fashion
582 Mutex::Locker locker(m_bytes_mutex);
583 m_bytes.append ((const char *)src, src_len);
584
585 // Parse up the packets into gdb remote packets
586 while (!m_bytes.empty())
587 {
588 // end_idx must be one past the last valid packet byte. Start
589 // it off with an invalid value that is the same as the current
590 // index.
591 size_t end_idx = 0;
592
593 switch (m_bytes[0])
594 {
595 case '+': // Look for ack
596 case '-': // Look for cancel
597 case '\x03': // ^C to halt target
598 end_idx = 1; // The command is one byte long...
599 break;
600
601 case '$':
602 // Look for a standard gdb packet?
603 end_idx = m_bytes.find('#');
604 if (end_idx != std::string::npos)
605 {
606 if (end_idx + 2 < m_bytes.size())
607 {
608 end_idx += 3;
609 }
610 else
611 {
612 // Checksum bytes aren't all here yet
613 end_idx = std::string::npos;
614 }
615 }
616 break;
617
618 default:
619 break;
620 }
621
622 if (end_idx == std::string::npos)
623 {
624 //ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
625 return;
626 }
627 else if (end_idx > 0)
628 {
629 // We have a valid packet...
630 assert (end_idx <= m_bytes.size());
631 std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
632 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
633 BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
634 m_bytes.erase(0, end_idx);
635 }
636 else
637 {
638 assert (1 <= m_bytes.size());
639 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
640 m_bytes.erase(0, 1);
641 }
642 }
643}
644
645lldb::pid_t
646GDBRemoteCommunication::GetCurrentProcessID (uint32_t timeout_seconds)
647{
648 StringExtractorGDBRemote response;
649 if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, timeout_seconds, false))
650 {
651 if (response.GetChar() == 'Q')
652 if (response.GetChar() == 'C')
653 return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
654 }
655 return LLDB_INVALID_PROCESS_ID;
656}
657
658bool
659GDBRemoteCommunication::GetLaunchSuccess (uint32_t timeout_seconds, std::string &error_str)
660{
661 error_str.clear();
662 StringExtractorGDBRemote response;
663 if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, timeout_seconds, false))
664 {
665 if (response.IsOKPacket())
666 return true;
667 if (response.GetChar() == 'E')
668 {
669 // A string the describes what failed when launching...
670 error_str = response.GetStringRef().substr(1);
671 }
672 else
673 {
674 error_str.assign ("unknown error occurred launching process");
675 }
676 }
677 else
678 {
679 error_str.assign ("failed to send the qLaunchSuccess packet");
680 }
681 return false;
682}
683
684int
685GDBRemoteCommunication::SendArgumentsPacket (char const *argv[], uint32_t timeout_seconds)
686{
687 if (argv && argv[0])
688 {
689 StreamString packet;
690 packet.PutChar('A');
691 const char *arg;
692 for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i)
693 {
694 const int arg_len = strlen(arg);
695 if (i > 0)
696 packet.PutChar(',');
697 packet.Printf("%i,%i,", arg_len * 2, i);
698 packet.PutBytesAsRawHex8(arg, arg_len, eByteOrderHost, eByteOrderHost);
699 }
700
701 StringExtractorGDBRemote response;
702 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
703 {
704 if (response.IsOKPacket())
705 return 0;
706 uint8_t error = response.GetError();
707 if (error)
708 return error;
709 }
710 }
711 return -1;
712}
713
714int
715GDBRemoteCommunication::SendEnvironmentPacket (char const *name_equal_value, uint32_t timeout_seconds)
716{
717 if (name_equal_value && name_equal_value[0])
718 {
719 StreamString packet;
720 packet.Printf("QEnvironment:%s", name_equal_value);
721 StringExtractorGDBRemote response;
722 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
723 {
724 if (response.IsOKPacket())
725 return 0;
726 uint8_t error = response.GetError();
727 if (error)
728 return error;
729 }
730 }
731 return -1;
732}
733
734bool
735GDBRemoteCommunication::GetHostInfo (uint32_t timeout_seconds)
736{
737 m_arch.Clear();
738 m_os.Clear();
739 m_vendor.Clear();
740 m_byte_order = eByteOrderHost;
741 m_pointer_byte_size = 0;
742
743 StringExtractorGDBRemote response;
744 if (SendPacketAndWaitForResponse ("qHostInfo", response, timeout_seconds, false))
745 {
746 if (response.IsUnsupportedPacket())
747 return false;
748
749
750 std::string name;
751 std::string value;
752 while (response.GetNameColonValue(name, value))
753 {
754 if (name.compare("cputype") == 0)
755 {
756 // exception type in big endian hex
757 m_arch.SetCPUType(Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0));
758 }
759 else if (name.compare("cpusubtype") == 0)
760 {
761 // exception count in big endian hex
762 m_arch.SetCPUSubtype(Args::StringToUInt32 (value.c_str(), 0, 0));
763 }
764 else if (name.compare("ostype") == 0)
765 {
766 // exception data in big endian hex
767 m_os.SetCString(value.c_str());
768 }
769 else if (name.compare("vendor") == 0)
770 {
771 m_vendor.SetCString(value.c_str());
772 }
773 else if (name.compare("endian") == 0)
774 {
775 if (value.compare("little") == 0)
776 m_byte_order = eByteOrderLittle;
777 else if (value.compare("big") == 0)
778 m_byte_order = eByteOrderBig;
779 else if (value.compare("pdp") == 0)
780 m_byte_order = eByteOrderPDP;
781 }
782 else if (name.compare("ptrsize") == 0)
783 {
784 m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
785 }
786 }
787 }
788 return HostInfoIsValid();
789}
790
791int
792GDBRemoteCommunication::SendAttach
793(
794 lldb::pid_t pid,
795 uint32_t timeout_seconds,
796 StringExtractorGDBRemote& response
797)
798{
799 if (pid != LLDB_INVALID_PROCESS_ID)
800 {
801 StreamString packet;
802 packet.Printf("vAttach;%x", pid);
803
804 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
805 {
806 if (response.IsErrorPacket())
807 return response.GetError();
808 return 0;
809 }
810 }
811 return -1;
812}
813
814const lldb_private::ArchSpec &
815GDBRemoteCommunication::GetHostArchitecture ()
816{
817 if (!HostInfoIsValid ())
818 GetHostInfo (1);
819 return m_arch;
820}
821
822const lldb_private::ConstString &
823GDBRemoteCommunication::GetOSString ()
824{
825 if (!HostInfoIsValid ())
826 GetHostInfo (1);
827 return m_os;
828}
829
830const lldb_private::ConstString &
831GDBRemoteCommunication::GetVendorString()
832{
833 if (!HostInfoIsValid ())
834 GetHostInfo (1);
835 return m_vendor;
836}
837
838lldb::ByteOrder
839GDBRemoteCommunication::GetByteOrder ()
840{
841 if (!HostInfoIsValid ())
842 GetHostInfo (1);
843 return m_byte_order;
844}
845
846uint32_t
847GDBRemoteCommunication::GetAddressByteSize ()
848{
849 if (!HostInfoIsValid ())
850 GetHostInfo (1);
851 return m_pointer_byte_size;
852}
853
854addr_t
855GDBRemoteCommunication::AllocateMemory (size_t size, uint32_t permissions, uint32_t timeout_seconds)
856{
857 char packet[64];
858 ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
859 permissions & lldb::ePermissionsReadable ? "r" : "",
860 permissions & lldb::ePermissionsWritable ? "w" : "",
861 permissions & lldb::ePermissionsExecutable ? "x" : "");
862 StringExtractorGDBRemote response;
863 if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
864 {
865 if (!response.IsErrorPacket())
866 return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
867 }
868 return LLDB_INVALID_ADDRESS;
869}
870
871bool
872GDBRemoteCommunication::DeallocateMemory (addr_t addr, uint32_t timeout_seconds)
873{
874 char packet[64];
875 snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
876 StringExtractorGDBRemote response;
877 if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
878 {
Sean Callanan6a925532011-01-13 08:53:35 +0000879 if (response.IsOKPacket())
Chris Lattner24943d22010-06-08 16:52:24 +0000880 return true;
881 }
882 return false;
883}
Jim Ingham3ae449a2010-11-17 02:32:00 +0000884