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