blob: 0f7787bf2ce7ef93001e26a277018bdad95297bf [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() :
35 Communication("gdb-remote.packets"),
36 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:
167// // Take a value reference and the value to assing it to when this class
168// // 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:
183// _Tp &m_value_ref; // A reference to the value we wil change when this object destructs
184// _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{
196 Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
197 if (log)
198 log->Printf ("GDBRemoteCommunication::%s ()", __FUNCTION__);
199
200 Mutex::Locker locker(m_sequence_mutex);
201 m_is_running.SetValue (true, eBroadcastNever);
202
203// ScopedValueChanger<bool> restore_running_to_false (m_is_running, false);
204 StateType state = eStateRunning;
205
206 if (SendPacket(payload, packet_length) == 0)
207 state = eStateInvalid;
208
209 while (state == eStateRunning)
210 {
211 if (log)
212 log->Printf ("GDBRemoteCommunication::%s () WaitForPacket(...)", __FUNCTION__);
213
214 if (WaitForPacket (response, (TimeValue*)NULL))
215 {
216 if (response.Empty())
217 state = eStateInvalid;
218 else
219 {
220 const char stop_type = response.GetChar();
221 if (log)
222 log->Printf ("GDBRemoteCommunication::%s () got '%c' packet", __FUNCTION__, stop_type);
223 switch (stop_type)
224 {
225 case 'T':
226 case 'S':
227 if (m_async_signal != -1)
228 {
229 // Save off the async signal we are supposed to send
230 const int async_signal = m_async_signal;
231 // Clear the async signal member so we don't end up
232 // sending the signal multiple times...
233 m_async_signal = -1;
234 // Check which signal we stopped with
235 uint8_t signo = response.GetHexU8(255);
236 if (signo == async_signal)
237 {
238 // We already stopped with a signal that we wanted
239 // to stop with, so we are done
240 response.SetFilePos (0);
241 }
242 else
243 {
244 // We stopped with a different signal that the one
245 // we wanted to stop with, so now we must resume
246 // with the signal we want
247 char signal_packet[32];
248 int signal_packet_len = 0;
249 signal_packet_len = ::snprintf (signal_packet,
250 sizeof (signal_packet),
251 "C%2.2x",
252 async_signal);
253
254 if (SendPacket(signal_packet, signal_packet_len) == 0)
255 {
256 state = eStateInvalid;
257 break;
258 }
259 else
260 continue;
261 }
262 }
263 else if (m_async_packet_predicate.GetValue())
264 {
265 // We are supposed to send an asynchronous packet while
266 // we are running.
267 m_async_response.Clear();
268 if (!m_async_packet.empty())
269 {
Greg Clayton53d68e72010-07-20 22:52:08 +0000270 SendPacketAndWaitForResponse (&m_async_packet[0],
Chris Lattner24943d22010-06-08 16:52:24 +0000271 m_async_packet.size(),
272 m_async_response,
273 m_async_timeout,
274 false);
275 }
276 // Let the other thread that was trying to send the async
277 // packet know that the packet has been sent.
278 m_async_packet_predicate.SetValue(false, eBroadcastAlways);
279
280 // Continue again
281 if (SendPacket("c", 1) == 0)
282 {
283 state = eStateInvalid;
284 break;
285 }
286 else
287 continue;
288 }
289 // Stop with signal and thread info
290 state = eStateStopped;
291 break;
292
293 case 'W':
294 // process exited
295 state = eStateExited;
296 break;
297
298 case 'O':
299 // STDOUT
300 {
301 std::string inferior_stdout;
302 inferior_stdout.reserve(response.GetBytesLeft () / 2);
303 char ch;
304 while ((ch = response.GetHexU8()) != '\0')
305 inferior_stdout.append(1, ch);
306 process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());
307 }
308 break;
309
310 case 'E':
311 // ERROR
312 state = eStateInvalid;
313 break;
314
315 default:
316 if (log)
317 log->Printf ("GDBRemoteCommunication::%s () got unrecognized async packet: '%s'", __FUNCTION__, stop_type);
318 break;
319 }
320 }
321 }
322 else
323 {
324 if (log)
325 log->Printf ("GDBRemoteCommunication::%s () WaitForPacket(...) => false", __FUNCTION__);
326 state = eStateInvalid;
327 }
328 }
329 if (log)
330 log->Printf ("GDBRemoteCommunication::%s () => %s", __FUNCTION__, StateAsCString(state));
331 response.SetFilePos(0);
332 m_is_running.SetValue (false, eBroadcastOnChange);
333 return state;
334}
335
336size_t
337GDBRemoteCommunication::SendPacket (const char *payload)
338{
339 Mutex::Locker locker(m_sequence_mutex);
340 return SendPacketNoLock (payload, ::strlen (payload));
341}
342
343size_t
344GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
345{
346 Mutex::Locker locker(m_sequence_mutex);
347 return SendPacketNoLock (payload, payload_length);
348}
349
350size_t
351GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
352{
353 if (IsConnected())
354 {
355 StreamString packet(0, 4, eByteOrderBig);
356
357 packet.PutChar('$');
358 packet.Write (payload, payload_length);
359 packet.PutChar('#');
360 packet.PutHex8(CalculcateChecksum (payload, payload_length));
361
362 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: %s", packet.GetData());
363 ConnectionStatus status = eConnectionStatusSuccess;
364 size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
365 if (bytes_written == packet.GetSize())
366 {
367 if (m_send_acks)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000368 {
369 if (GetAck (1) != '+')
370 return 0;
371 }
Chris Lattner24943d22010-06-08 16:52:24 +0000372 }
373 return bytes_written;
374 }
375 //m_error.SetErrorString("Not connected.");
376 return 0;
377}
378
379char
380GDBRemoteCommunication::GetAck (uint32_t timeout_seconds)
381{
382 StringExtractorGDBRemote response;
383 if (WaitForPacket (response, timeout_seconds) == 1)
384 return response.GetChar();
385 return 0;
386}
387
388bool
389GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
390{
391 return locker.TryLock (m_sequence_mutex.GetMutex());
392}
393
394bool
395GDBRemoteCommunication::SendAsyncSignal (int signo)
396{
397 m_async_signal = signo;
398 bool timed_out = false;
Greg Clayton1a679462010-09-03 19:15:43 +0000399 Mutex::Locker locker;
400 if (SendInterrupt (locker, 1, &timed_out))
Chris Lattner24943d22010-06-08 16:52:24 +0000401 return true;
402 m_async_signal = -1;
403 return false;
404}
405
Greg Clayton1a679462010-09-03 19:15:43 +0000406// This function takes a mutex locker as a parameter in case the GetSequenceMutex
407// actually succeeds. If it doesn't succeed in acquiring the sequence mutex
408// (the expected result), then it will send the halt packet. If it does succeed
409// then the caller that requested the interrupt will want to keep the sequence
410// locked down so that no one else can send packets while the caller has control.
411// This function usually gets called when we are running and need to stop the
412// target. It can also be used when we are running and and we need to do something
413// else (like read/write memory), so we need to interrupt the running process
414// (gdb remote protocol requires this), and do what we need to do, then resume.
415
Chris Lattner24943d22010-06-08 16:52:24 +0000416bool
Greg Clayton1a679462010-09-03 19:15:43 +0000417GDBRemoteCommunication::SendInterrupt (Mutex::Locker& locker, uint32_t seconds_to_wait_for_stop, bool *timed_out)
Chris Lattner24943d22010-06-08 16:52:24 +0000418{
419 if (timed_out)
420 *timed_out = false;
421
422 if (IsConnected() && IsRunning())
423 {
424 // Only send an interrupt if our debugserver is running...
Greg Clayton1a679462010-09-03 19:15:43 +0000425 if (GetSequenceMutex (locker) == false)
Chris Lattner24943d22010-06-08 16:52:24 +0000426 {
427 // Someone has the mutex locked waiting for a response or for the
428 // inferior to stop, so send the interrupt on the down low...
429 char ctrl_c = '\x03';
430 ConnectionStatus status = eConnectionStatusSuccess;
431 TimeValue timeout;
432 if (seconds_to_wait_for_stop)
433 {
434 timeout = TimeValue::Now();
435 timeout.OffsetWithSeconds (seconds_to_wait_for_stop);
436 }
437 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: \\x03");
438 if (Write (&ctrl_c, 1, status, NULL) > 0)
439 {
440 if (seconds_to_wait_for_stop)
441 m_is_running.WaitForValueEqualTo (false, &timeout, timed_out);
442 return true;
443 }
444 }
445 }
446 return false;
447}
448
449size_t
450GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, uint32_t timeout_seconds)
451{
452 TimeValue timeout_time;
453 timeout_time = TimeValue::Now();
454 timeout_time.OffsetWithSeconds (timeout_seconds);
455 return WaitForPacketNoLock (response, &timeout_time);
456}
457
458size_t
459GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, TimeValue* timeout_time_ptr)
460{
461 Mutex::Locker locker(m_sequence_mutex);
462 return WaitForPacketNoLock (response, timeout_time_ptr);
463}
464
465size_t
466GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &response, TimeValue* timeout_time_ptr)
467{
468 bool checksum_error = false;
469 response.Clear ();
470
471 EventSP event_sp;
472
473 if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
474 {
475 const uint32_t event_type = event_sp->GetType();
476 if (event_type | Communication::eBroadcastBitPacketAvailable)
477 {
478 const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
479 if (event_bytes)
480 {
481 const char * packet_data = (const char *)event_bytes->GetBytes();
482 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "read packet: %s", packet_data);
483 const size_t packet_size = event_bytes->GetByteSize();
484 if (packet_data && packet_size > 0)
485 {
486 std::string &response_str = response.GetStringRef();
487 if (packet_data[0] == '$')
488 {
489 assert (packet_size >= 4); // Must have at least '$#CC' where CC is checksum
490 assert (packet_data[packet_size-3] == '#');
491 assert (::isxdigit (packet_data[packet_size-2])); // Must be checksum hex byte
492 assert (::isxdigit (packet_data[packet_size-1])); // Must be checksum hex byte
493 response_str.assign (packet_data + 1, packet_size - 4);
494 if (m_send_acks)
495 {
496 char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
Greg Clayton53d68e72010-07-20 22:52:08 +0000497 char actual_checksum = CalculcateChecksum (&response_str[0], response_str.size());
Chris Lattner24943d22010-06-08 16:52:24 +0000498 checksum_error = packet_checksum != actual_checksum;
499 // Send the ack or nack if needed
500 if (checksum_error)
501 SendAck('-');
502 else
503 SendAck('+');
504 }
505 }
506 else
507 {
508 response_str.assign (packet_data, packet_size);
509 }
510 return response_str.size();
511 }
512 }
513 }
514 else if (Communication::eBroadcastBitReadThreadDidExit)
515 {
516 // Our read thread exited on us so just fall through and return zero...
517 }
518 }
519 return 0;
520}
521
522void
523GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast)
524{
525 // Put the packet data into the buffer in a thread safe fashion
526 Mutex::Locker locker(m_bytes_mutex);
527 m_bytes.append ((const char *)src, src_len);
528
529 // Parse up the packets into gdb remote packets
530 while (!m_bytes.empty())
531 {
532 // end_idx must be one past the last valid packet byte. Start
533 // it off with an invalid value that is the same as the current
534 // index.
535 size_t end_idx = 0;
536
537 switch (m_bytes[0])
538 {
539 case '+': // Look for ack
540 case '-': // Look for cancel
541 case '\x03': // ^C to halt target
542 end_idx = 1; // The command is one byte long...
543 break;
544
545 case '$':
546 // Look for a standard gdb packet?
547 end_idx = m_bytes.find('#');
548 if (end_idx != std::string::npos)
549 {
550 if (end_idx + 2 < m_bytes.size())
551 {
552 end_idx += 3;
553 }
554 else
555 {
556 // Checksum bytes aren't all here yet
557 end_idx = std::string::npos;
558 }
559 }
560 break;
561
562 default:
563 break;
564 }
565
566 if (end_idx == std::string::npos)
567 {
568 //ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
569 return;
570 }
571 else if (end_idx > 0)
572 {
573 // We have a valid packet...
574 assert (end_idx <= m_bytes.size());
575 std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
576 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
577 BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
578 m_bytes.erase(0, end_idx);
579 }
580 else
581 {
582 assert (1 <= m_bytes.size());
583 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
584 m_bytes.erase(0, 1);
585 }
586 }
587}
588
589lldb::pid_t
590GDBRemoteCommunication::GetCurrentProcessID (uint32_t timeout_seconds)
591{
592 StringExtractorGDBRemote response;
593 if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, timeout_seconds, false))
594 {
595 if (response.GetChar() == 'Q')
596 if (response.GetChar() == 'C')
597 return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
598 }
599 return LLDB_INVALID_PROCESS_ID;
600}
601
602bool
603GDBRemoteCommunication::GetLaunchSuccess (uint32_t timeout_seconds, std::string &error_str)
604{
605 error_str.clear();
606 StringExtractorGDBRemote response;
607 if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, timeout_seconds, false))
608 {
609 if (response.IsOKPacket())
610 return true;
611 if (response.GetChar() == 'E')
612 {
613 // A string the describes what failed when launching...
614 error_str = response.GetStringRef().substr(1);
615 }
616 else
617 {
618 error_str.assign ("unknown error occurred launching process");
619 }
620 }
621 else
622 {
623 error_str.assign ("failed to send the qLaunchSuccess packet");
624 }
625 return false;
626}
627
628int
629GDBRemoteCommunication::SendArgumentsPacket (char const *argv[], uint32_t timeout_seconds)
630{
631 if (argv && argv[0])
632 {
633 StreamString packet;
634 packet.PutChar('A');
635 const char *arg;
636 for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i)
637 {
638 const int arg_len = strlen(arg);
639 if (i > 0)
640 packet.PutChar(',');
641 packet.Printf("%i,%i,", arg_len * 2, i);
642 packet.PutBytesAsRawHex8(arg, arg_len, eByteOrderHost, eByteOrderHost);
643 }
644
645 StringExtractorGDBRemote response;
646 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
647 {
648 if (response.IsOKPacket())
649 return 0;
650 uint8_t error = response.GetError();
651 if (error)
652 return error;
653 }
654 }
655 return -1;
656}
657
658int
659GDBRemoteCommunication::SendEnvironmentPacket (char const *name_equal_value, uint32_t timeout_seconds)
660{
661 if (name_equal_value && name_equal_value[0])
662 {
663 StreamString packet;
664 packet.Printf("QEnvironment:%s", name_equal_value);
665 StringExtractorGDBRemote response;
666 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
667 {
668 if (response.IsOKPacket())
669 return 0;
670 uint8_t error = response.GetError();
671 if (error)
672 return error;
673 }
674 }
675 return -1;
676}
677
678bool
679GDBRemoteCommunication::GetHostInfo (uint32_t timeout_seconds)
680{
681 m_arch.Clear();
682 m_os.Clear();
683 m_vendor.Clear();
684 m_byte_order = eByteOrderHost;
685 m_pointer_byte_size = 0;
686
687 StringExtractorGDBRemote response;
688 if (SendPacketAndWaitForResponse ("qHostInfo", response, timeout_seconds, false))
689 {
690 if (response.IsUnsupportedPacket())
691 return false;
692
693
694 std::string name;
695 std::string value;
696 while (response.GetNameColonValue(name, value))
697 {
698 if (name.compare("cputype") == 0)
699 {
700 // exception type in big endian hex
701 m_arch.SetCPUType(Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0));
702 }
703 else if (name.compare("cpusubtype") == 0)
704 {
705 // exception count in big endian hex
706 m_arch.SetCPUSubtype(Args::StringToUInt32 (value.c_str(), 0, 0));
707 }
708 else if (name.compare("ostype") == 0)
709 {
710 // exception data in big endian hex
711 m_os.SetCString(value.c_str());
712 }
713 else if (name.compare("vendor") == 0)
714 {
715 m_vendor.SetCString(value.c_str());
716 }
717 else if (name.compare("endian") == 0)
718 {
719 if (value.compare("little") == 0)
720 m_byte_order = eByteOrderLittle;
721 else if (value.compare("big") == 0)
722 m_byte_order = eByteOrderBig;
723 else if (value.compare("pdp") == 0)
724 m_byte_order = eByteOrderPDP;
725 }
726 else if (name.compare("ptrsize") == 0)
727 {
728 m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
729 }
730 }
731 }
732 return HostInfoIsValid();
733}
734
735int
736GDBRemoteCommunication::SendAttach
737(
738 lldb::pid_t pid,
739 uint32_t timeout_seconds,
740 StringExtractorGDBRemote& response
741)
742{
743 if (pid != LLDB_INVALID_PROCESS_ID)
744 {
745 StreamString packet;
746 packet.Printf("vAttach;%x", pid);
747
748 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
749 {
750 if (response.IsErrorPacket())
751 return response.GetError();
752 return 0;
753 }
754 }
755 return -1;
756}
757
758const lldb_private::ArchSpec &
759GDBRemoteCommunication::GetHostArchitecture ()
760{
761 if (!HostInfoIsValid ())
762 GetHostInfo (1);
763 return m_arch;
764}
765
766const lldb_private::ConstString &
767GDBRemoteCommunication::GetOSString ()
768{
769 if (!HostInfoIsValid ())
770 GetHostInfo (1);
771 return m_os;
772}
773
774const lldb_private::ConstString &
775GDBRemoteCommunication::GetVendorString()
776{
777 if (!HostInfoIsValid ())
778 GetHostInfo (1);
779 return m_vendor;
780}
781
782lldb::ByteOrder
783GDBRemoteCommunication::GetByteOrder ()
784{
785 if (!HostInfoIsValid ())
786 GetHostInfo (1);
787 return m_byte_order;
788}
789
790uint32_t
791GDBRemoteCommunication::GetAddressByteSize ()
792{
793 if (!HostInfoIsValid ())
794 GetHostInfo (1);
795 return m_pointer_byte_size;
796}
797
798addr_t
799GDBRemoteCommunication::AllocateMemory (size_t size, uint32_t permissions, uint32_t timeout_seconds)
800{
801 char packet[64];
802 ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
803 permissions & lldb::ePermissionsReadable ? "r" : "",
804 permissions & lldb::ePermissionsWritable ? "w" : "",
805 permissions & lldb::ePermissionsExecutable ? "x" : "");
806 StringExtractorGDBRemote response;
807 if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
808 {
809 if (!response.IsErrorPacket())
810 return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
811 }
812 return LLDB_INVALID_ADDRESS;
813}
814
815bool
816GDBRemoteCommunication::DeallocateMemory (addr_t addr, uint32_t timeout_seconds)
817{
818 char packet[64];
819 snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
820 StringExtractorGDBRemote response;
821 if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
822 {
823 if (!response.IsOKPacket())
824 return true;
825 }
826 return false;
827}