GDBRemoteCommunication.cpp revision 139da72165577f073c14f2d5b86191e2c7b21d4c
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#include <limits.h>
15#include <string.h>
16
17// C++ Includes
18// Other libraries and framework includes
19#include "lldb/Core/Log.h"
20#include "lldb/Core/StreamString.h"
21#include "lldb/Host/FileSpec.h"
22#include "lldb/Host/Host.h"
23#include "lldb/Host/TimeValue.h"
24#include "lldb/Target/Process.h"
25
26// Project includes
27#include "ProcessGDBRemoteLog.h"
28
29#define DEBUGSERVER_BASENAME    "debugserver"
30
31using namespace lldb;
32using namespace lldb_private;
33
34//----------------------------------------------------------------------
35// GDBRemoteCommunication constructor
36//----------------------------------------------------------------------
37GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
38                                               const char *listener_name,
39                                               bool is_platform) :
40    Communication(comm_name),
41    m_packet_timeout (60),
42    m_rx_packet_listener (listener_name),
43    m_sequence_mutex (Mutex::eMutexTypeRecursive),
44    m_public_is_running (false),
45    m_private_is_running (false),
46    m_send_acks (true),
47    m_is_platform (is_platform)
48{
49    m_rx_packet_listener.StartListeningForEvents(this,
50                                                 Communication::eBroadcastBitPacketAvailable  |
51                                                 Communication::eBroadcastBitReadThreadDidExit);
52}
53
54//----------------------------------------------------------------------
55// Destructor
56//----------------------------------------------------------------------
57GDBRemoteCommunication::~GDBRemoteCommunication()
58{
59    m_rx_packet_listener.StopListeningForEvents(this,
60                                                Communication::eBroadcastBitPacketAvailable  |
61                                                Communication::eBroadcastBitReadThreadDidExit);
62    if (IsConnected())
63    {
64        StopReadThread();
65        Disconnect();
66    }
67}
68
69char
70GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
71{
72    int checksum = 0;
73
74    // We only need to compute the checksum if we are sending acks
75    if (GetSendAcks ())
76    {
77        for (size_t i = 0; i < payload_length; ++i)
78            checksum += payload[i];
79    }
80    return checksum & 255;
81}
82
83size_t
84GDBRemoteCommunication::SendAck ()
85{
86    LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
87    if (log)
88        log->Printf ("send packet: +");
89    ConnectionStatus status = eConnectionStatusSuccess;
90    char ack_char = '+';
91    return Write (&ack_char, 1, status, NULL);
92}
93
94size_t
95GDBRemoteCommunication::SendNack ()
96{
97    LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
98    if (log)
99        log->Printf ("send packet: -");
100    ConnectionStatus status = eConnectionStatusSuccess;
101    char nack_char = '-';
102    return Write (&nack_char, 1, status, NULL);
103}
104
105size_t
106GDBRemoteCommunication::SendPacket (lldb_private::StreamString &payload)
107{
108    Mutex::Locker locker(m_sequence_mutex);
109    const std::string &p (payload.GetString());
110    return SendPacketNoLock (p.c_str(), p.size());
111}
112
113size_t
114GDBRemoteCommunication::SendPacket (const char *payload)
115{
116    Mutex::Locker locker(m_sequence_mutex);
117    return SendPacketNoLock (payload, ::strlen (payload));
118}
119
120size_t
121GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
122{
123    Mutex::Locker locker(m_sequence_mutex);
124    return SendPacketNoLock (payload, payload_length);
125}
126
127size_t
128GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
129{
130    if (IsConnected())
131    {
132        StreamString packet(0, 4, eByteOrderBig);
133
134        packet.PutChar('$');
135        packet.Write (payload, payload_length);
136        packet.PutChar('#');
137        packet.PutHex8(CalculcateChecksum (payload, payload_length));
138
139        LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
140        if (log)
141            log->Printf ("send packet: %.*s", (int)packet.GetSize(), packet.GetData());
142        ConnectionStatus status = eConnectionStatusSuccess;
143        size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
144        if (bytes_written == packet.GetSize())
145        {
146            if (GetSendAcks ())
147            {
148                if (GetAck () != '+')
149                {
150                    printf("get ack failed...");
151                    return 0;
152                }
153            }
154        }
155        else
156        {
157            LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
158            if (log)
159                log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData());
160        }
161        return bytes_written;
162    }
163    return 0;
164}
165
166char
167GDBRemoteCommunication::GetAck ()
168{
169    StringExtractorGDBRemote packet;
170    if (WaitForPacket (packet, m_packet_timeout) == 1)
171        return packet.GetChar();
172    return 0;
173}
174
175bool
176GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
177{
178    return locker.TryLock (m_sequence_mutex.GetMutex());
179}
180
181
182bool
183GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
184{
185    return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
186}
187
188size_t
189GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, uint32_t timeout_seconds)
190{
191    Mutex::Locker locker(m_sequence_mutex);
192    TimeValue timeout_time;
193    timeout_time = TimeValue::Now();
194    timeout_time.OffsetWithSeconds (timeout_seconds);
195    return WaitForPacketNoLock (packet, &timeout_time);
196}
197
198size_t
199GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
200{
201    Mutex::Locker locker(m_sequence_mutex);
202    return WaitForPacketNoLock (packet, timeout_time_ptr);
203}
204
205size_t
206GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
207{
208    bool checksum_error = false;
209    packet.Clear ();
210
211    EventSP event_sp;
212
213    if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
214    {
215        const uint32_t event_type = event_sp->GetType();
216        if (event_type | Communication::eBroadcastBitPacketAvailable)
217        {
218            const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
219            if (event_bytes)
220            {
221                const char *packet_data =  (const char *)event_bytes->GetBytes();
222                const uint32_t packet_size =  event_bytes->GetByteSize();
223                LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
224                if (log)
225                    log->Printf ("read packet: %.*s", packet_size, packet_data);
226                if (packet_data && packet_size > 0)
227                {
228                    std::string &packet_str = packet.GetStringRef();
229                    if (packet_data[0] == '$')
230                    {
231                        bool success = false;
232                        if (packet_size < 4)
233                            ::fprintf (stderr, "Packet that starts with $ is too short: '%s'\n", packet_data);
234                        else if (packet_data[packet_size-3] != '#' ||
235                                 !::isxdigit (packet_data[packet_size-2]) ||
236                                 !::isxdigit (packet_data[packet_size-1]))
237                            ::fprintf (stderr, "Invalid checksum footer for packet: '%s'\n", packet_data);
238                        else
239                            success = true;
240
241                        if (success)
242                            packet_str.assign (packet_data + 1, packet_size - 4);
243                        if (GetSendAcks ())
244                        {
245                            if (success)
246                            {
247                                char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
248                                char actual_checksum = CalculcateChecksum (&packet_str[0], packet_str.size());
249                                checksum_error = packet_checksum != actual_checksum;
250                            }
251                            // Send the ack or nack if needed
252                            if (checksum_error || !success)
253                                SendNack();
254                            else
255                                SendAck();
256                        }
257                    }
258                    else
259                    {
260                        packet_str.assign (packet_data, packet_size);
261                    }
262                    return packet_str.size();
263                }
264            }
265        }
266        else if (event_type | Communication::eBroadcastBitReadThreadDidExit)
267        {
268            // Our read thread exited on us so just fall through and return zero...
269            Disconnect();
270        }
271    }
272    return 0;
273}
274
275void
276GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast,
277                                            ConnectionStatus status)
278{
279    // Put the packet data into the buffer in a thread safe fashion
280    Mutex::Locker locker(m_bytes_mutex);
281    m_bytes.append ((const char *)src, src_len);
282
283    // Parse up the packets into gdb remote packets
284    while (!m_bytes.empty())
285    {
286        // end_idx must be one past the last valid packet byte. Start
287        // it off with an invalid value that is the same as the current
288        // index.
289        size_t end_idx = 0;
290
291        switch (m_bytes[0])
292        {
293            case '+':       // Look for ack
294            case '-':       // Look for cancel
295            case '\x03':    // ^C to halt target
296                end_idx = 1;  // The command is one byte long...
297                break;
298
299            case '$':
300                // Look for a standard gdb packet?
301                end_idx = m_bytes.find('#');
302                if (end_idx != std::string::npos)
303                {
304                    if (end_idx + 2 < m_bytes.size())
305                    {
306                        end_idx += 3;
307                    }
308                    else
309                    {
310                        // Checksum bytes aren't all here yet
311                        end_idx = std::string::npos;
312                    }
313                }
314                break;
315
316            default:
317                break;
318        }
319
320        if (end_idx == std::string::npos)
321        {
322            //ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
323            return;
324        }
325        else if (end_idx > 0)
326        {
327            // We have a valid packet...
328            assert (end_idx <= m_bytes.size());
329            std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
330            ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
331            BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
332            m_bytes.erase(0, end_idx);
333        }
334        else
335        {
336            assert (1 <= m_bytes.size());
337            ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
338            m_bytes.erase(0, 1);
339        }
340    }
341}
342
343Error
344GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
345                                                 const char *unix_socket_name,  // For handshaking
346                                                 lldb_private::ProcessLaunchInfo &launch_info)
347{
348    Error error;
349    // If we locate debugserver, keep that located version around
350    static FileSpec g_debugserver_file_spec;
351
352    // This function will fill in the launch information for the debugserver
353    // instance that gets launched.
354    launch_info.Clear();
355
356    char debugserver_path[PATH_MAX];
357    FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
358
359    // Always check to see if we have an environment override for the path
360    // to the debugserver to use and use it if we do.
361    const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
362    if (env_debugserver_path)
363        debugserver_file_spec.SetFile (env_debugserver_path, false);
364    else
365        debugserver_file_spec = g_debugserver_file_spec;
366    bool debugserver_exists = debugserver_file_spec.Exists();
367    if (!debugserver_exists)
368    {
369        // The debugserver binary is in the LLDB.framework/Resources
370        // directory.
371        if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
372        {
373            debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
374            debugserver_exists = debugserver_file_spec.Exists();
375            if (debugserver_exists)
376            {
377                g_debugserver_file_spec = debugserver_file_spec;
378            }
379            else
380            {
381                g_debugserver_file_spec.Clear();
382                debugserver_file_spec.Clear();
383            }
384        }
385    }
386
387    if (debugserver_exists)
388    {
389        debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
390
391        Args &debugserver_args = launch_info.GetArguments();
392        debugserver_args.Clear();
393        char arg_cstr[PATH_MAX];
394
395        // Start args with "debugserver /file/path -r --"
396        debugserver_args.AppendArgument(debugserver_path);
397        debugserver_args.AppendArgument(debugserver_url);
398        // use native registers, not the GDB registers
399        debugserver_args.AppendArgument("--native-regs");
400        // make debugserver run in its own session so signals generated by
401        // special terminal key sequences (^C) don't affect debugserver
402        debugserver_args.AppendArgument("--setsid");
403
404        if (unix_socket_name && unix_socket_name[0])
405        {
406            debugserver_args.AppendArgument("--unix-socket");
407            debugserver_args.AppendArgument(unix_socket_name);
408        }
409
410        const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
411        if (env_debugserver_log_file)
412        {
413            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
414            debugserver_args.AppendArgument(arg_cstr);
415        }
416
417        const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
418        if (env_debugserver_log_flags)
419        {
420            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
421            debugserver_args.AppendArgument(arg_cstr);
422        }
423        //            debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
424        //            debugserver_args.AppendArgument("--log-flags=0x802e0e");
425
426        // We currently send down all arguments, attach pids, or attach
427        // process names in dedicated GDB server packets, so we don't need
428        // to pass them as arguments. This is currently because of all the
429        // things we need to setup prior to launching: the environment,
430        // current working dir, file actions, etc.
431#if 0
432        // Now append the program arguments
433        if (inferior_argv)
434        {
435            // Terminate the debugserver args so we can now append the inferior args
436            debugserver_args.AppendArgument("--");
437
438            for (int i = 0; inferior_argv[i] != NULL; ++i)
439                debugserver_args.AppendArgument (inferior_argv[i]);
440        }
441        else if (attach_pid != LLDB_INVALID_PROCESS_ID)
442        {
443            ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
444            debugserver_args.AppendArgument (arg_cstr);
445        }
446        else if (attach_name && attach_name[0])
447        {
448            if (wait_for_launch)
449                debugserver_args.AppendArgument ("--waitfor");
450            else
451                debugserver_args.AppendArgument ("--attach");
452            debugserver_args.AppendArgument (attach_name);
453        }
454#endif
455
456        // Close STDIN, STDOUT and STDERR. We might need to redirect them
457        // to "/dev/null" if we run into any problems.
458//        launch_info.AppendCloseFileAction (STDIN_FILENO);
459//        launch_info.AppendCloseFileAction (STDOUT_FILENO);
460//        launch_info.AppendCloseFileAction (STDERR_FILENO);
461
462        error = Host::LaunchProcess(launch_info);
463    }
464    else
465    {
466        error.SetErrorStringWithFormat ("Unable to locate " DEBUGSERVER_BASENAME ".\n");
467    }
468    return error;
469}
470
471