GDBRemoteCommunication.cpp revision 54e7afa84d945f9137f9372ecde432f9e1a702fc
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
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    {
81        for (size_t i = 0; i < payload_length; ++i)
82            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
127    if (locker.TryLock (m_sequence_mutex.GetMutex()))
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(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
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                        {
270                            SendPacketAndWaitForResponse (m_async_packet.data(),
271                                                          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)
368            {
369                if (GetAck (1) != '+')
370                    return 0;
371            }
372        }
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;
399    if (SendInterrupt(1, &timed_out))
400        return true;
401    m_async_signal = -1;
402    return false;
403}
404
405bool
406GDBRemoteCommunication::SendInterrupt (uint32_t seconds_to_wait_for_stop, bool *timed_out)
407{
408    if (timed_out)
409        *timed_out = false;
410
411    if (IsConnected() && IsRunning())
412    {
413        // Only send an interrupt if our debugserver is running...
414        if (m_sequence_mutex.TryLock() != 0)
415        {
416            // Someone has the mutex locked waiting for a response or for the
417            // inferior to stop, so send the interrupt on the down low...
418            char ctrl_c = '\x03';
419            ConnectionStatus status = eConnectionStatusSuccess;
420            TimeValue timeout;
421            if (seconds_to_wait_for_stop)
422            {
423                timeout = TimeValue::Now();
424                timeout.OffsetWithSeconds (seconds_to_wait_for_stop);
425            }
426            ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: \\x03");
427            if (Write (&ctrl_c, 1, status, NULL) > 0)
428            {
429                if (seconds_to_wait_for_stop)
430                    m_is_running.WaitForValueEqualTo (false, &timeout, timed_out);
431                return true;
432            }
433        }
434    }
435    return false;
436}
437
438size_t
439GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, uint32_t timeout_seconds)
440{
441    TimeValue timeout_time;
442    timeout_time = TimeValue::Now();
443    timeout_time.OffsetWithSeconds (timeout_seconds);
444    return WaitForPacketNoLock (response, &timeout_time);
445}
446
447size_t
448GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, TimeValue* timeout_time_ptr)
449{
450    Mutex::Locker locker(m_sequence_mutex);
451    return WaitForPacketNoLock (response, timeout_time_ptr);
452}
453
454size_t
455GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &response, TimeValue* timeout_time_ptr)
456{
457    bool checksum_error = false;
458    response.Clear ();
459
460    EventSP event_sp;
461
462    if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
463    {
464        const uint32_t event_type = event_sp->GetType();
465        if (event_type | Communication::eBroadcastBitPacketAvailable)
466        {
467            const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
468            if (event_bytes)
469            {
470                const char * packet_data =  (const char *)event_bytes->GetBytes();
471                ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "read packet: %s", packet_data);
472                const size_t packet_size =  event_bytes->GetByteSize();
473                if (packet_data && packet_size > 0)
474                {
475                    std::string &response_str = response.GetStringRef();
476                    if (packet_data[0] == '$')
477                    {
478                        assert (packet_size >= 4);  // Must have at least '$#CC' where CC is checksum
479                        assert (packet_data[packet_size-3] == '#');
480                        assert (::isxdigit (packet_data[packet_size-2]));  // Must be checksum hex byte
481                        assert (::isxdigit (packet_data[packet_size-1]));  // Must be checksum hex byte
482                        response_str.assign (packet_data + 1, packet_size - 4);
483                        if (m_send_acks)
484                        {
485                            char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
486                            char actual_checksum = CalculcateChecksum (response_str.data(), response_str.size());
487                            checksum_error = packet_checksum != actual_checksum;
488                            // Send the ack or nack if needed
489                            if (checksum_error)
490                                SendAck('-');
491                            else
492                                SendAck('+');
493                        }
494                    }
495                    else
496                    {
497                        response_str.assign (packet_data, packet_size);
498                    }
499                    return response_str.size();
500                }
501            }
502        }
503        else if (Communication::eBroadcastBitReadThreadDidExit)
504        {
505            // Our read thread exited on us so just fall through and return zero...
506        }
507    }
508    return 0;
509}
510
511void
512GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast)
513{
514    // Put the packet data into the buffer in a thread safe fashion
515    Mutex::Locker locker(m_bytes_mutex);
516    m_bytes.append ((const char *)src, src_len);
517
518    // Parse up the packets into gdb remote packets
519    while (!m_bytes.empty())
520    {
521        // end_idx must be one past the last valid packet byte. Start
522        // it off with an invalid value that is the same as the current
523        // index.
524        size_t end_idx = 0;
525
526        switch (m_bytes[0])
527        {
528            case '+':       // Look for ack
529            case '-':       // Look for cancel
530            case '\x03':    // ^C to halt target
531                end_idx = 1;  // The command is one byte long...
532                break;
533
534            case '$':
535                // Look for a standard gdb packet?
536                end_idx = m_bytes.find('#');
537                if (end_idx != std::string::npos)
538                {
539                    if (end_idx + 2 < m_bytes.size())
540                    {
541                        end_idx += 3;
542                    }
543                    else
544                    {
545                        // Checksum bytes aren't all here yet
546                        end_idx = std::string::npos;
547                    }
548                }
549                break;
550
551            default:
552                break;
553        }
554
555        if (end_idx == std::string::npos)
556        {
557            //ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
558            return;
559        }
560        else if (end_idx > 0)
561        {
562            // We have a valid packet...
563            assert (end_idx <= m_bytes.size());
564            std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
565            ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
566            BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
567            m_bytes.erase(0, end_idx);
568        }
569        else
570        {
571            assert (1 <= m_bytes.size());
572            ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
573            m_bytes.erase(0, 1);
574        }
575    }
576}
577
578lldb::pid_t
579GDBRemoteCommunication::GetCurrentProcessID (uint32_t timeout_seconds)
580{
581    StringExtractorGDBRemote response;
582    if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, timeout_seconds, false))
583    {
584        if (response.GetChar() == 'Q')
585            if (response.GetChar() == 'C')
586                return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
587    }
588    return LLDB_INVALID_PROCESS_ID;
589}
590
591bool
592GDBRemoteCommunication::GetLaunchSuccess (uint32_t timeout_seconds, std::string &error_str)
593{
594    error_str.clear();
595    StringExtractorGDBRemote response;
596    if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, timeout_seconds, false))
597    {
598        if (response.IsOKPacket())
599            return true;
600        if (response.GetChar() == 'E')
601        {
602            // A string the describes what failed when launching...
603            error_str = response.GetStringRef().substr(1);
604        }
605        else
606        {
607            error_str.assign ("unknown error occurred launching process");
608        }
609    }
610    else
611    {
612        error_str.assign ("failed to send the qLaunchSuccess packet");
613    }
614    return false;
615}
616
617int
618GDBRemoteCommunication::SendArgumentsPacket (char const *argv[], uint32_t timeout_seconds)
619{
620    if (argv && argv[0])
621    {
622        StreamString packet;
623        packet.PutChar('A');
624        const char *arg;
625        for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i)
626        {
627            const int arg_len = strlen(arg);
628            if (i > 0)
629                packet.PutChar(',');
630            packet.Printf("%i,%i,", arg_len * 2, i);
631            packet.PutBytesAsRawHex8(arg, arg_len, eByteOrderHost, eByteOrderHost);
632        }
633
634        StringExtractorGDBRemote response;
635        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
636        {
637            if (response.IsOKPacket())
638                return 0;
639            uint8_t error = response.GetError();
640            if (error)
641                return error;
642        }
643    }
644    return -1;
645}
646
647int
648GDBRemoteCommunication::SendEnvironmentPacket (char const *name_equal_value, uint32_t timeout_seconds)
649{
650    if (name_equal_value && name_equal_value[0])
651    {
652        StreamString packet;
653        packet.Printf("QEnvironment:%s", name_equal_value);
654        StringExtractorGDBRemote response;
655        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
656        {
657            if (response.IsOKPacket())
658                return 0;
659            uint8_t error = response.GetError();
660            if (error)
661                return error;
662        }
663    }
664    return -1;
665}
666
667bool
668GDBRemoteCommunication::GetHostInfo (uint32_t timeout_seconds)
669{
670    m_arch.Clear();
671    m_os.Clear();
672    m_vendor.Clear();
673    m_byte_order = eByteOrderHost;
674    m_pointer_byte_size = 0;
675
676    StringExtractorGDBRemote response;
677    if (SendPacketAndWaitForResponse ("qHostInfo", response, timeout_seconds, false))
678    {
679        if (response.IsUnsupportedPacket())
680            return false;
681
682
683        std::string name;
684        std::string value;
685        while (response.GetNameColonValue(name, value))
686        {
687            if (name.compare("cputype") == 0)
688            {
689                // exception type in big endian hex
690                m_arch.SetCPUType(Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0));
691            }
692            else if (name.compare("cpusubtype") == 0)
693            {
694                // exception count in big endian hex
695                m_arch.SetCPUSubtype(Args::StringToUInt32 (value.c_str(), 0, 0));
696            }
697            else if (name.compare("ostype") == 0)
698            {
699                // exception data in big endian hex
700                m_os.SetCString(value.c_str());
701            }
702            else if (name.compare("vendor") == 0)
703            {
704                m_vendor.SetCString(value.c_str());
705            }
706            else if (name.compare("endian") == 0)
707            {
708                if (value.compare("little") == 0)
709                    m_byte_order = eByteOrderLittle;
710                else if (value.compare("big") == 0)
711                    m_byte_order = eByteOrderBig;
712                else if (value.compare("pdp") == 0)
713                    m_byte_order = eByteOrderPDP;
714            }
715            else if (name.compare("ptrsize") == 0)
716            {
717                m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
718            }
719        }
720    }
721    return HostInfoIsValid();
722}
723
724int
725GDBRemoteCommunication::SendAttach
726(
727    lldb::pid_t pid,
728    uint32_t timeout_seconds,
729    StringExtractorGDBRemote& response
730)
731{
732    if (pid != LLDB_INVALID_PROCESS_ID)
733    {
734        StreamString packet;
735        packet.Printf("vAttach;%x", pid);
736
737        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
738        {
739            if (response.IsErrorPacket())
740                return response.GetError();
741            return 0;
742        }
743    }
744    return -1;
745}
746
747const lldb_private::ArchSpec &
748GDBRemoteCommunication::GetHostArchitecture ()
749{
750    if (!HostInfoIsValid ())
751        GetHostInfo (1);
752    return m_arch;
753}
754
755const lldb_private::ConstString &
756GDBRemoteCommunication::GetOSString ()
757{
758    if (!HostInfoIsValid ())
759        GetHostInfo (1);
760    return m_os;
761}
762
763const lldb_private::ConstString &
764GDBRemoteCommunication::GetVendorString()
765{
766    if (!HostInfoIsValid ())
767        GetHostInfo (1);
768    return m_vendor;
769}
770
771lldb::ByteOrder
772GDBRemoteCommunication::GetByteOrder ()
773{
774    if (!HostInfoIsValid ())
775        GetHostInfo (1);
776    return m_byte_order;
777}
778
779uint32_t
780GDBRemoteCommunication::GetAddressByteSize ()
781{
782    if (!HostInfoIsValid ())
783        GetHostInfo (1);
784    return m_pointer_byte_size;
785}
786
787addr_t
788GDBRemoteCommunication::AllocateMemory (size_t size, uint32_t permissions, uint32_t timeout_seconds)
789{
790    char packet[64];
791    ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
792                permissions & lldb::ePermissionsReadable ? "r" : "",
793                permissions & lldb::ePermissionsWritable ? "w" : "",
794                permissions & lldb::ePermissionsExecutable ? "x" : "");
795    StringExtractorGDBRemote response;
796    if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
797    {
798        if (!response.IsErrorPacket())
799            return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
800    }
801    return LLDB_INVALID_ADDRESS;
802}
803
804bool
805GDBRemoteCommunication::DeallocateMemory (addr_t addr, uint32_t timeout_seconds)
806{
807    char packet[64];
808    snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
809    StringExtractorGDBRemote response;
810    if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
811    {
812        if (!response.IsOKPacket())
813            return true;
814    }
815    return false;
816}
817