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