1254721Semaste//===-- GDBRemoteCommunication.cpp ------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste
11254721Semaste#include "GDBRemoteCommunication.h"
12254721Semaste
13254721Semaste// C Includes
14254721Semaste#include <limits.h>
15254721Semaste#include <string.h>
16254721Semaste
17254721Semaste// C++ Includes
18254721Semaste// Other libraries and framework includes
19254721Semaste#include "lldb/Core/Log.h"
20254721Semaste#include "lldb/Core/StreamFile.h"
21254721Semaste#include "lldb/Core/StreamString.h"
22254721Semaste#include "lldb/Host/FileSpec.h"
23254721Semaste#include "lldb/Host/Host.h"
24254721Semaste#include "lldb/Host/TimeValue.h"
25254721Semaste#include "lldb/Target/Process.h"
26254721Semaste
27254721Semaste// Project includes
28254721Semaste#include "ProcessGDBRemoteLog.h"
29254721Semaste
30254721Semaste#define DEBUGSERVER_BASENAME    "debugserver"
31254721Semaste
32254721Semasteusing namespace lldb;
33254721Semasteusing namespace lldb_private;
34254721Semaste
35254721SemasteGDBRemoteCommunication::History::History (uint32_t size) :
36254721Semaste    m_packets(),
37254721Semaste    m_curr_idx (0),
38254721Semaste    m_total_packet_count (0),
39254721Semaste    m_dumped_to_log (false)
40254721Semaste{
41254721Semaste    m_packets.resize(size);
42254721Semaste}
43254721Semaste
44254721SemasteGDBRemoteCommunication::History::~History ()
45254721Semaste{
46254721Semaste}
47254721Semaste
48254721Semastevoid
49254721SemasteGDBRemoteCommunication::History::AddPacket (char packet_char,
50254721Semaste                                            PacketType type,
51254721Semaste                                            uint32_t bytes_transmitted)
52254721Semaste{
53254721Semaste    const size_t size = m_packets.size();
54254721Semaste    if (size > 0)
55254721Semaste    {
56254721Semaste        const uint32_t idx = GetNextIndex();
57254721Semaste        m_packets[idx].packet.assign (1, packet_char);
58254721Semaste        m_packets[idx].type = type;
59254721Semaste        m_packets[idx].bytes_transmitted = bytes_transmitted;
60254721Semaste        m_packets[idx].packet_idx = m_total_packet_count;
61254721Semaste        m_packets[idx].tid = Host::GetCurrentThreadID();
62254721Semaste    }
63254721Semaste}
64254721Semaste
65254721Semastevoid
66254721SemasteGDBRemoteCommunication::History::AddPacket (const std::string &src,
67254721Semaste                                            uint32_t src_len,
68254721Semaste                                            PacketType type,
69254721Semaste                                            uint32_t bytes_transmitted)
70254721Semaste{
71254721Semaste    const size_t size = m_packets.size();
72254721Semaste    if (size > 0)
73254721Semaste    {
74254721Semaste        const uint32_t idx = GetNextIndex();
75254721Semaste        m_packets[idx].packet.assign (src, 0, src_len);
76254721Semaste        m_packets[idx].type = type;
77254721Semaste        m_packets[idx].bytes_transmitted = bytes_transmitted;
78254721Semaste        m_packets[idx].packet_idx = m_total_packet_count;
79254721Semaste        m_packets[idx].tid = Host::GetCurrentThreadID();
80254721Semaste    }
81254721Semaste}
82254721Semaste
83254721Semastevoid
84254721SemasteGDBRemoteCommunication::History::Dump (lldb_private::Stream &strm) const
85254721Semaste{
86254721Semaste    const uint32_t size = GetNumPacketsInHistory ();
87254721Semaste    const uint32_t first_idx = GetFirstSavedPacketIndex ();
88254721Semaste    const uint32_t stop_idx = m_curr_idx + size;
89254721Semaste    for (uint32_t i = first_idx;  i < stop_idx; ++i)
90254721Semaste    {
91254721Semaste        const uint32_t idx = NormalizeIndex (i);
92254721Semaste        const Entry &entry = m_packets[idx];
93254721Semaste        if (entry.type == ePacketTypeInvalid || entry.packet.empty())
94254721Semaste            break;
95254721Semaste        strm.Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n",
96254721Semaste                     entry.packet_idx,
97254721Semaste                     entry.tid,
98254721Semaste                     entry.bytes_transmitted,
99254721Semaste                     (entry.type == ePacketTypeSend) ? "send" : "read",
100254721Semaste                     entry.packet.c_str());
101254721Semaste    }
102254721Semaste}
103254721Semaste
104254721Semastevoid
105254721SemasteGDBRemoteCommunication::History::Dump (lldb_private::Log *log) const
106254721Semaste{
107254721Semaste    if (log && !m_dumped_to_log)
108254721Semaste    {
109254721Semaste        m_dumped_to_log = true;
110254721Semaste        const uint32_t size = GetNumPacketsInHistory ();
111254721Semaste        const uint32_t first_idx = GetFirstSavedPacketIndex ();
112254721Semaste        const uint32_t stop_idx = m_curr_idx + size;
113254721Semaste        for (uint32_t i = first_idx;  i < stop_idx; ++i)
114254721Semaste        {
115254721Semaste            const uint32_t idx = NormalizeIndex (i);
116254721Semaste            const Entry &entry = m_packets[idx];
117254721Semaste            if (entry.type == ePacketTypeInvalid || entry.packet.empty())
118254721Semaste                break;
119254721Semaste            log->Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s",
120254721Semaste                         entry.packet_idx,
121254721Semaste                         entry.tid,
122254721Semaste                         entry.bytes_transmitted,
123254721Semaste                         (entry.type == ePacketTypeSend) ? "send" : "read",
124254721Semaste                         entry.packet.c_str());
125254721Semaste        }
126254721Semaste    }
127254721Semaste}
128254721Semaste
129254721Semaste//----------------------------------------------------------------------
130254721Semaste// GDBRemoteCommunication constructor
131254721Semaste//----------------------------------------------------------------------
132254721SemasteGDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
133254721Semaste                                               const char *listener_name,
134254721Semaste                                               bool is_platform) :
135254721Semaste    Communication(comm_name),
136254721Semaste    m_packet_timeout (1),
137254721Semaste    m_sequence_mutex (Mutex::eMutexTypeRecursive),
138254721Semaste    m_public_is_running (false),
139254721Semaste    m_private_is_running (false),
140254721Semaste    m_history (512),
141254721Semaste    m_send_acks (true),
142254721Semaste    m_is_platform (is_platform)
143254721Semaste{
144254721Semaste}
145254721Semaste
146254721Semaste//----------------------------------------------------------------------
147254721Semaste// Destructor
148254721Semaste//----------------------------------------------------------------------
149254721SemasteGDBRemoteCommunication::~GDBRemoteCommunication()
150254721Semaste{
151254721Semaste    if (IsConnected())
152254721Semaste    {
153254721Semaste        Disconnect();
154254721Semaste    }
155254721Semaste}
156254721Semaste
157254721Semastechar
158254721SemasteGDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
159254721Semaste{
160254721Semaste    int checksum = 0;
161254721Semaste
162254721Semaste    for (size_t i = 0; i < payload_length; ++i)
163254721Semaste        checksum += payload[i];
164254721Semaste
165254721Semaste    return checksum & 255;
166254721Semaste}
167254721Semaste
168254721Semastesize_t
169254721SemasteGDBRemoteCommunication::SendAck ()
170254721Semaste{
171254721Semaste    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
172254721Semaste    ConnectionStatus status = eConnectionStatusSuccess;
173254721Semaste    char ch = '+';
174254721Semaste    const size_t bytes_written = Write (&ch, 1, status, NULL);
175254721Semaste    if (log)
176254721Semaste        log->Printf ("<%4zu> send packet: %c", bytes_written, ch);
177254721Semaste    m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
178254721Semaste    return bytes_written;
179254721Semaste}
180254721Semaste
181254721Semastesize_t
182254721SemasteGDBRemoteCommunication::SendNack ()
183254721Semaste{
184254721Semaste    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
185254721Semaste    ConnectionStatus status = eConnectionStatusSuccess;
186254721Semaste    char ch = '-';
187254721Semaste    const size_t bytes_written = Write (&ch, 1, status, NULL);
188254721Semaste    if (log)
189254721Semaste        log->Printf ("<%4zu> send packet: %c", bytes_written, ch);
190254721Semaste    m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
191254721Semaste    return bytes_written;
192254721Semaste}
193254721Semaste
194254721Semastesize_t
195254721SemasteGDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
196254721Semaste{
197254721Semaste    Mutex::Locker locker(m_sequence_mutex);
198254721Semaste    return SendPacketNoLock (payload, payload_length);
199254721Semaste}
200254721Semaste
201254721Semastesize_t
202254721SemasteGDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
203254721Semaste{
204254721Semaste    if (IsConnected())
205254721Semaste    {
206254721Semaste        StreamString packet(0, 4, eByteOrderBig);
207254721Semaste
208254721Semaste        packet.PutChar('$');
209254721Semaste        packet.Write (payload, payload_length);
210254721Semaste        packet.PutChar('#');
211254721Semaste        packet.PutHex8(CalculcateChecksum (payload, payload_length));
212254721Semaste
213254721Semaste        Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
214254721Semaste        ConnectionStatus status = eConnectionStatusSuccess;
215254721Semaste        size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
216254721Semaste        if (log)
217254721Semaste        {
218254721Semaste            // If logging was just enabled and we have history, then dump out what
219254721Semaste            // we have to the log so we get the historical context. The Dump() call that
220254721Semaste            // logs all of the packet will set a boolean so that we don't dump this more
221254721Semaste            // than once
222254721Semaste            if (!m_history.DidDumpToLog ())
223254721Semaste                m_history.Dump (log);
224254721Semaste
225254721Semaste            log->Printf ("<%4zu> send packet: %.*s", bytes_written, (int)packet.GetSize(), packet.GetData());
226254721Semaste        }
227254721Semaste
228254721Semaste        m_history.AddPacket (packet.GetString(), packet.GetSize(), History::ePacketTypeSend, bytes_written);
229254721Semaste
230254721Semaste
231254721Semaste        if (bytes_written == packet.GetSize())
232254721Semaste        {
233254721Semaste            if (GetSendAcks ())
234254721Semaste            {
235254721Semaste                if (GetAck () != '+')
236254721Semaste                {
237254721Semaste                    if (log)
238254721Semaste                        log->Printf("get ack failed...");
239254721Semaste                    return 0;
240254721Semaste                }
241254721Semaste            }
242254721Semaste        }
243254721Semaste        else
244254721Semaste        {
245254721Semaste            if (log)
246254721Semaste                log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData());
247254721Semaste        }
248254721Semaste        return bytes_written;
249254721Semaste    }
250254721Semaste    return 0;
251254721Semaste}
252254721Semaste
253254721Semastechar
254254721SemasteGDBRemoteCommunication::GetAck ()
255254721Semaste{
256254721Semaste    StringExtractorGDBRemote packet;
257254721Semaste    if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, GetPacketTimeoutInMicroSeconds ()) == 1)
258254721Semaste        return packet.GetChar();
259254721Semaste    return 0;
260254721Semaste}
261254721Semaste
262254721Semastebool
263254721SemasteGDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker, const char *failure_message)
264254721Semaste{
265254721Semaste    if (IsRunning())
266254721Semaste        return locker.TryLock (m_sequence_mutex, failure_message);
267254721Semaste
268254721Semaste    locker.Lock (m_sequence_mutex);
269254721Semaste    return true;
270254721Semaste}
271254721Semaste
272254721Semaste
273254721Semastebool
274254721SemasteGDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
275254721Semaste{
276254721Semaste    return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
277254721Semaste}
278254721Semaste
279254721Semastesize_t
280254721SemasteGDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec)
281254721Semaste{
282254721Semaste    uint8_t buffer[8192];
283254721Semaste    Error error;
284254721Semaste
285254721Semaste    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE));
286254721Semaste
287254721Semaste    // Check for a packet from our cache first without trying any reading...
288254721Semaste    if (CheckForPacket (NULL, 0, packet))
289254721Semaste        return packet.GetStringRef().size();
290254721Semaste
291254721Semaste    bool timed_out = false;
292254721Semaste    while (IsConnected() && !timed_out)
293254721Semaste    {
294254721Semaste        lldb::ConnectionStatus status = eConnectionStatusNoConnection;
295254721Semaste        size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
296254721Semaste
297254721Semaste        if (log)
298254721Semaste            log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64,
299254721Semaste                         __PRETTY_FUNCTION__,
300254721Semaste                         timeout_usec,
301254721Semaste                         Communication::ConnectionStatusAsCString (status),
302254721Semaste                         error.AsCString(),
303254721Semaste                         (uint64_t)bytes_read);
304254721Semaste
305254721Semaste        if (bytes_read > 0)
306254721Semaste        {
307254721Semaste            if (CheckForPacket (buffer, bytes_read, packet))
308254721Semaste                return packet.GetStringRef().size();
309254721Semaste        }
310254721Semaste        else
311254721Semaste        {
312254721Semaste            switch (status)
313254721Semaste            {
314254721Semaste            case eConnectionStatusTimedOut:
315254721Semaste                timed_out = true;
316254721Semaste                break;
317254721Semaste            case eConnectionStatusSuccess:
318254721Semaste                //printf ("status = success but error = %s\n", error.AsCString("<invalid>"));
319254721Semaste                break;
320254721Semaste
321254721Semaste            case eConnectionStatusEndOfFile:
322254721Semaste            case eConnectionStatusNoConnection:
323254721Semaste            case eConnectionStatusLostConnection:
324254721Semaste            case eConnectionStatusError:
325254721Semaste                Disconnect();
326254721Semaste                break;
327254721Semaste            }
328254721Semaste        }
329254721Semaste    }
330254721Semaste    packet.Clear ();
331254721Semaste    return 0;
332254721Semaste}
333254721Semaste
334254721Semastebool
335254721SemasteGDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet)
336254721Semaste{
337254721Semaste    // Put the packet data into the buffer in a thread safe fashion
338254721Semaste    Mutex::Locker locker(m_bytes_mutex);
339254721Semaste
340254721Semaste    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
341254721Semaste
342254721Semaste    if (src && src_len > 0)
343254721Semaste    {
344254721Semaste        if (log && log->GetVerbose())
345254721Semaste        {
346254721Semaste            StreamString s;
347254721Semaste            log->Printf ("GDBRemoteCommunication::%s adding %u bytes: %.*s",
348254721Semaste                         __FUNCTION__,
349254721Semaste                         (uint32_t)src_len,
350254721Semaste                         (uint32_t)src_len,
351254721Semaste                         src);
352254721Semaste        }
353254721Semaste        m_bytes.append ((const char *)src, src_len);
354254721Semaste    }
355254721Semaste
356254721Semaste    // Parse up the packets into gdb remote packets
357254721Semaste    if (!m_bytes.empty())
358254721Semaste    {
359254721Semaste        // end_idx must be one past the last valid packet byte. Start
360254721Semaste        // it off with an invalid value that is the same as the current
361254721Semaste        // index.
362254721Semaste        size_t content_start = 0;
363254721Semaste        size_t content_length = 0;
364254721Semaste        size_t total_length = 0;
365254721Semaste        size_t checksum_idx = std::string::npos;
366254721Semaste
367254721Semaste        switch (m_bytes[0])
368254721Semaste        {
369254721Semaste            case '+':       // Look for ack
370254721Semaste            case '-':       // Look for cancel
371254721Semaste            case '\x03':    // ^C to halt target
372254721Semaste                content_length = total_length = 1;  // The command is one byte long...
373254721Semaste                break;
374254721Semaste
375254721Semaste            case '$':
376254721Semaste                // Look for a standard gdb packet?
377254721Semaste                {
378254721Semaste                    size_t hash_pos = m_bytes.find('#');
379254721Semaste                    if (hash_pos != std::string::npos)
380254721Semaste                    {
381254721Semaste                        if (hash_pos + 2 < m_bytes.size())
382254721Semaste                        {
383254721Semaste                            checksum_idx = hash_pos + 1;
384254721Semaste                            // Skip the dollar sign
385254721Semaste                            content_start = 1;
386254721Semaste                            // Don't include the # in the content or the $ in the content length
387254721Semaste                            content_length = hash_pos - 1;
388254721Semaste
389254721Semaste                            total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes
390254721Semaste                        }
391254721Semaste                        else
392254721Semaste                        {
393254721Semaste                            // Checksum bytes aren't all here yet
394254721Semaste                            content_length = std::string::npos;
395254721Semaste                        }
396254721Semaste                    }
397254721Semaste                }
398254721Semaste                break;
399254721Semaste
400254721Semaste            default:
401254721Semaste                {
402254721Semaste                    // We have an unexpected byte and we need to flush all bad
403254721Semaste                    // data that is in m_bytes, so we need to find the first
404254721Semaste                    // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt),
405254721Semaste                    // or '$' character (start of packet header) or of course,
406254721Semaste                    // the end of the data in m_bytes...
407254721Semaste                    const size_t bytes_len = m_bytes.size();
408254721Semaste                    bool done = false;
409254721Semaste                    uint32_t idx;
410254721Semaste                    for (idx = 1; !done && idx < bytes_len; ++idx)
411254721Semaste                    {
412254721Semaste                        switch (m_bytes[idx])
413254721Semaste                        {
414254721Semaste                        case '+':
415254721Semaste                        case '-':
416254721Semaste                        case '\x03':
417254721Semaste                        case '$':
418254721Semaste                            done = true;
419254721Semaste                            break;
420254721Semaste
421254721Semaste                        default:
422254721Semaste                            break;
423254721Semaste                        }
424254721Semaste                    }
425254721Semaste                    if (log)
426254721Semaste                        log->Printf ("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'",
427254721Semaste                                     __FUNCTION__, idx, idx, m_bytes.c_str());
428254721Semaste                    m_bytes.erase(0, idx);
429254721Semaste                }
430254721Semaste                break;
431254721Semaste        }
432254721Semaste
433254721Semaste        if (content_length == std::string::npos)
434254721Semaste        {
435254721Semaste            packet.Clear();
436254721Semaste            return false;
437254721Semaste        }
438254721Semaste        else if (total_length > 0)
439254721Semaste        {
440254721Semaste
441254721Semaste            // We have a valid packet...
442254721Semaste            assert (content_length <= m_bytes.size());
443254721Semaste            assert (total_length <= m_bytes.size());
444254721Semaste            assert (content_length <= total_length);
445254721Semaste
446254721Semaste            bool success = true;
447254721Semaste            std::string &packet_str = packet.GetStringRef();
448254721Semaste
449254721Semaste
450254721Semaste            if (log)
451254721Semaste            {
452254721Semaste                // If logging was just enabled and we have history, then dump out what
453254721Semaste                // we have to the log so we get the historical context. The Dump() call that
454254721Semaste                // logs all of the packet will set a boolean so that we don't dump this more
455254721Semaste                // than once
456254721Semaste                if (!m_history.DidDumpToLog ())
457254721Semaste                    m_history.Dump (log);
458254721Semaste
459254721Semaste                log->Printf ("<%4zu> read packet: %.*s", total_length, (int)(total_length), m_bytes.c_str());
460254721Semaste            }
461254721Semaste
462254721Semaste            m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length);
463254721Semaste
464254721Semaste            packet_str.assign (m_bytes, content_start, content_length);
465254721Semaste
466254721Semaste            if (m_bytes[0] == '$')
467254721Semaste            {
468254721Semaste                assert (checksum_idx < m_bytes.size());
469254721Semaste                if (::isxdigit (m_bytes[checksum_idx+0]) ||
470254721Semaste                    ::isxdigit (m_bytes[checksum_idx+1]))
471254721Semaste                {
472254721Semaste                    if (GetSendAcks ())
473254721Semaste                    {
474254721Semaste                        const char *packet_checksum_cstr = &m_bytes[checksum_idx];
475254721Semaste                        char packet_checksum = strtol (packet_checksum_cstr, NULL, 16);
476254721Semaste                        char actual_checksum = CalculcateChecksum (packet_str.c_str(), packet_str.size());
477254721Semaste                        success = packet_checksum == actual_checksum;
478254721Semaste                        if (!success)
479254721Semaste                        {
480254721Semaste                            if (log)
481254721Semaste                                log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x",
482254721Semaste                                             (int)(total_length),
483254721Semaste                                             m_bytes.c_str(),
484254721Semaste                                             (uint8_t)packet_checksum,
485254721Semaste                                             (uint8_t)actual_checksum);
486254721Semaste                        }
487254721Semaste                        // Send the ack or nack if needed
488254721Semaste                        if (!success)
489254721Semaste                            SendNack();
490254721Semaste                        else
491254721Semaste                            SendAck();
492254721Semaste                    }
493254721Semaste                }
494254721Semaste                else
495254721Semaste                {
496254721Semaste                    success = false;
497254721Semaste                    if (log)
498254721Semaste                        log->Printf ("error: invalid checksum in packet: '%s'\n", m_bytes.c_str());
499254721Semaste                }
500254721Semaste            }
501254721Semaste
502254721Semaste            m_bytes.erase(0, total_length);
503254721Semaste            packet.SetFilePos(0);
504254721Semaste            return success;
505254721Semaste        }
506254721Semaste    }
507254721Semaste    packet.Clear();
508254721Semaste    return false;
509254721Semaste}
510254721Semaste
511254721SemasteError
512254721SemasteGDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
513254721Semaste                                                 const char *unix_socket_name,  // For handshaking
514254721Semaste                                                 lldb_private::ProcessLaunchInfo &launch_info)
515254721Semaste{
516254721Semaste    Error error;
517254721Semaste    // If we locate debugserver, keep that located version around
518254721Semaste    static FileSpec g_debugserver_file_spec;
519254721Semaste
520254721Semaste    // This function will fill in the launch information for the debugserver
521254721Semaste    // instance that gets launched.
522254721Semaste    launch_info.Clear();
523254721Semaste
524254721Semaste    char debugserver_path[PATH_MAX];
525254721Semaste    FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
526254721Semaste
527254721Semaste    // Always check to see if we have an environment override for the path
528254721Semaste    // to the debugserver to use and use it if we do.
529254721Semaste    const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
530254721Semaste    if (env_debugserver_path)
531254721Semaste        debugserver_file_spec.SetFile (env_debugserver_path, false);
532254721Semaste    else
533254721Semaste        debugserver_file_spec = g_debugserver_file_spec;
534254721Semaste    bool debugserver_exists = debugserver_file_spec.Exists();
535254721Semaste    if (!debugserver_exists)
536254721Semaste    {
537254721Semaste        // The debugserver binary is in the LLDB.framework/Resources
538254721Semaste        // directory.
539254721Semaste        if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
540254721Semaste        {
541254721Semaste            debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
542254721Semaste            debugserver_exists = debugserver_file_spec.Exists();
543254721Semaste            if (debugserver_exists)
544254721Semaste            {
545254721Semaste                g_debugserver_file_spec = debugserver_file_spec;
546254721Semaste            }
547254721Semaste            else
548254721Semaste            {
549254721Semaste                g_debugserver_file_spec.Clear();
550254721Semaste                debugserver_file_spec.Clear();
551254721Semaste            }
552254721Semaste        }
553254721Semaste    }
554254721Semaste
555254721Semaste    if (debugserver_exists)
556254721Semaste    {
557254721Semaste        debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
558254721Semaste
559254721Semaste        Args &debugserver_args = launch_info.GetArguments();
560254721Semaste        debugserver_args.Clear();
561254721Semaste        char arg_cstr[PATH_MAX];
562254721Semaste
563254721Semaste        // Start args with "debugserver /file/path -r --"
564254721Semaste        debugserver_args.AppendArgument(debugserver_path);
565254721Semaste        debugserver_args.AppendArgument(debugserver_url);
566254721Semaste        // use native registers, not the GDB registers
567254721Semaste        debugserver_args.AppendArgument("--native-regs");
568254721Semaste        // make debugserver run in its own session so signals generated by
569254721Semaste        // special terminal key sequences (^C) don't affect debugserver
570254721Semaste        debugserver_args.AppendArgument("--setsid");
571254721Semaste
572254721Semaste        if (unix_socket_name && unix_socket_name[0])
573254721Semaste        {
574254721Semaste            debugserver_args.AppendArgument("--unix-socket");
575254721Semaste            debugserver_args.AppendArgument(unix_socket_name);
576254721Semaste        }
577254721Semaste
578254721Semaste        const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
579254721Semaste        if (env_debugserver_log_file)
580254721Semaste        {
581254721Semaste            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
582254721Semaste            debugserver_args.AppendArgument(arg_cstr);
583254721Semaste        }
584254721Semaste
585254721Semaste        const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
586254721Semaste        if (env_debugserver_log_flags)
587254721Semaste        {
588254721Semaste            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
589254721Semaste            debugserver_args.AppendArgument(arg_cstr);
590254721Semaste        }
591254721Semaste        //            debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
592254721Semaste        //            debugserver_args.AppendArgument("--log-flags=0x802e0e");
593254721Semaste
594254721Semaste        // We currently send down all arguments, attach pids, or attach
595254721Semaste        // process names in dedicated GDB server packets, so we don't need
596254721Semaste        // to pass them as arguments. This is currently because of all the
597254721Semaste        // things we need to setup prior to launching: the environment,
598254721Semaste        // current working dir, file actions, etc.
599254721Semaste#if 0
600254721Semaste        // Now append the program arguments
601254721Semaste        if (inferior_argv)
602254721Semaste        {
603254721Semaste            // Terminate the debugserver args so we can now append the inferior args
604254721Semaste            debugserver_args.AppendArgument("--");
605254721Semaste
606254721Semaste            for (int i = 0; inferior_argv[i] != NULL; ++i)
607254721Semaste                debugserver_args.AppendArgument (inferior_argv[i]);
608254721Semaste        }
609254721Semaste        else if (attach_pid != LLDB_INVALID_PROCESS_ID)
610254721Semaste        {
611254721Semaste            ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
612254721Semaste            debugserver_args.AppendArgument (arg_cstr);
613254721Semaste        }
614254721Semaste        else if (attach_name && attach_name[0])
615254721Semaste        {
616254721Semaste            if (wait_for_launch)
617254721Semaste                debugserver_args.AppendArgument ("--waitfor");
618254721Semaste            else
619254721Semaste                debugserver_args.AppendArgument ("--attach");
620254721Semaste            debugserver_args.AppendArgument (attach_name);
621254721Semaste        }
622254721Semaste#endif
623254721Semaste
624254721Semaste        // Close STDIN, STDOUT and STDERR. We might need to redirect them
625254721Semaste        // to "/dev/null" if we run into any problems.
626254721Semaste//        launch_info.AppendCloseFileAction (STDIN_FILENO);
627254721Semaste//        launch_info.AppendCloseFileAction (STDOUT_FILENO);
628254721Semaste//        launch_info.AppendCloseFileAction (STDERR_FILENO);
629254721Semaste
630254721Semaste        error = Host::LaunchProcess(launch_info);
631254721Semaste    }
632254721Semaste    else
633254721Semaste    {
634254721Semaste        error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME );
635254721Semaste    }
636254721Semaste    return error;
637254721Semaste}
638254721Semaste
639254721Semastevoid
640254721SemasteGDBRemoteCommunication::DumpHistory(Stream &strm)
641254721Semaste{
642254721Semaste    m_history.Dump (strm);
643254721Semaste}
644