GDBRemoteCommunication.cpp revision 1a67946295ac66ff7a8787be25d8b56f49742345
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 (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
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[0],
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    Mutex::Locker locker;
400    if (SendInterrupt (locker, 1, &timed_out))
401        return true;
402    m_async_signal = -1;
403    return false;
404}
405
406// 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
416bool
417GDBRemoteCommunication::SendInterrupt (Mutex::Locker& locker, uint32_t seconds_to_wait_for_stop, bool *timed_out)
418{
419    if (timed_out)
420        *timed_out = false;
421
422    if (IsConnected() && IsRunning())
423    {
424        // Only send an interrupt if our debugserver is running...
425        if (GetSequenceMutex (locker) == false)
426        {
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);
497                            char actual_checksum = CalculcateChecksum (&response_str[0], response_str.size());
498                            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}
828