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