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