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