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