GDBRemoteCommunicationServer.cpp revision 7de2a3b03f37987c67f142ce328cc2484c831468
1//===-- GDBRemoteCommunicationServer.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 "GDBRemoteCommunicationServer.h"
12
13// C Includes
14// C++ Includes
15// Other libraries and framework includes
16#include "llvm/ADT/Triple.h"
17#include "lldb/Interpreter/Args.h"
18#include "lldb/Core/ConnectionFileDescriptor.h"
19#include "lldb/Core/Log.h"
20#include "lldb/Core/State.h"
21#include "lldb/Core/StreamString.h"
22#include "lldb/Host/Endian.h"
23#include "lldb/Host/Host.h"
24#include "lldb/Host/TimeValue.h"
25#include "lldb/Target/Process.h"
26
27// Project includes
28#include "Utility/StringExtractorGDBRemote.h"
29#include "ProcessGDBRemote.h"
30#include "ProcessGDBRemoteLog.h"
31
32using namespace lldb;
33using namespace lldb_private;
34
35//----------------------------------------------------------------------
36// GDBRemoteCommunicationServer constructor
37//----------------------------------------------------------------------
38GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
39    GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
40    m_async_thread (LLDB_INVALID_HOST_THREAD),
41    m_process_launch_info (),
42    m_process_launch_error (),
43    m_proc_infos (),
44    m_proc_infos_index (0),
45    m_lo_port_num (0),
46    m_hi_port_num (0)
47{
48}
49
50//----------------------------------------------------------------------
51// Destructor
52//----------------------------------------------------------------------
53GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
54{
55}
56
57
58//void *
59//GDBRemoteCommunicationServer::AsyncThread (void *arg)
60//{
61//    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
62//
63//    LogSP log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
64//    if (log)
65//        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
66//
67//    StringExtractorGDBRemote packet;
68//
69//    while ()
70//    {
71//        if (packet.
72//    }
73//
74//    if (log)
75//        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
76//
77//    process->m_async_thread = LLDB_INVALID_HOST_THREAD;
78//    return NULL;
79//}
80//
81bool
82GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
83                                                        Error &error,
84                                                        bool &interrupt,
85                                                        bool &quit)
86{
87    StringExtractorGDBRemote packet;
88    if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec))
89    {
90        const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
91        switch (packet_type)
92        {
93            case StringExtractorGDBRemote::eServerPacketType_nack:
94            case StringExtractorGDBRemote::eServerPacketType_ack:
95                break;
96
97            case StringExtractorGDBRemote::eServerPacketType_invalid:
98                error.SetErrorString("invalid packet");
99                quit = true;
100                break;
101
102            case StringExtractorGDBRemote::eServerPacketType_interrupt:
103                error.SetErrorString("interrupt received");
104                interrupt = true;
105                break;
106
107            case StringExtractorGDBRemote::eServerPacketType_unimplemented:
108                return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
109
110            case StringExtractorGDBRemote::eServerPacketType_A:
111                return Handle_A (packet);
112
113            case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
114                return Handle_qfProcessInfo (packet);
115
116            case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
117                return Handle_qsProcessInfo (packet);
118
119            case StringExtractorGDBRemote::eServerPacketType_qC:
120                return Handle_qC (packet);
121
122            case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
123                return Handle_qHostInfo (packet);
124
125            case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
126                return Handle_qLaunchGDBServer (packet);
127
128            case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
129                return Handle_qLaunchSuccess (packet);
130
131            case StringExtractorGDBRemote::eServerPacketType_qGroupName:
132                return Handle_qGroupName (packet);
133
134            case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
135                return Handle_qProcessInfoPID (packet);
136
137            case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
138                return Handle_qSpeedTest (packet);
139
140            case StringExtractorGDBRemote::eServerPacketType_qUserName:
141                return Handle_qUserName (packet);
142
143            case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
144                return Handle_QEnvironment (packet);
145
146            case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
147                return Handle_QSetDisableASLR (packet);
148
149            case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
150                return Handle_QSetSTDIN (packet);
151
152            case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
153                return Handle_QSetSTDOUT (packet);
154
155            case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
156                return Handle_QSetSTDERR (packet);
157
158            case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
159                return Handle_QSetWorkingDir (packet);
160
161            case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
162                return Handle_QStartNoAckMode (packet);
163        }
164        return true;
165    }
166    else
167    {
168        if (!IsConnected())
169            error.SetErrorString("lost connection");
170        else
171            error.SetErrorString("timeout");
172    }
173
174    return false;
175}
176
177size_t
178GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
179{
180    // TODO: Log the packet we aren't handling...
181    return SendPacketNoLock ("", 0);
182}
183
184size_t
185GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
186{
187    char packet[16];
188    int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
189    assert (packet_len < sizeof(packet));
190    return SendPacketNoLock (packet, packet_len);
191}
192
193
194size_t
195GDBRemoteCommunicationServer::SendOKResponse ()
196{
197    return SendPacketNoLock ("OK", 2);
198}
199
200bool
201GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
202{
203    return GetAck();
204}
205
206bool
207GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
208{
209    StreamString response;
210
211    // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
212
213    ArchSpec host_arch (Host::GetArchitecture ());
214    const llvm::Triple &host_triple = host_arch.GetTriple();
215    response.PutCString("triple:");
216    response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
217    response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
218
219    uint32_t cpu = host_arch.GetMachOCPUType();
220    uint32_t sub = host_arch.GetMachOCPUSubType();
221    if (cpu != LLDB_INVALID_CPUTYPE)
222        response.Printf ("cputype:%u;", cpu);
223    if (sub != LLDB_INVALID_CPUTYPE)
224        response.Printf ("cpusubtype:%u;", sub);
225
226    if (cpu == CPU_TYPE_ARM)
227        response.Printf("watchpoint_exceptions_received:before;");   // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
228    else
229        response.Printf("watchpoint_exceptions_received:after;");
230
231    switch (lldb::endian::InlHostByteOrder())
232    {
233    case eByteOrderBig:     response.PutCString ("endian:big;"); break;
234    case eByteOrderLittle:  response.PutCString ("endian:little;"); break;
235    case eByteOrderPDP:     response.PutCString ("endian:pdp;"); break;
236    default:                response.PutCString ("endian:unknown;"); break;
237    }
238
239    uint32_t major = UINT32_MAX;
240    uint32_t minor = UINT32_MAX;
241    uint32_t update = UINT32_MAX;
242    if (Host::GetOSVersion (major, minor, update))
243    {
244        if (major != UINT32_MAX)
245        {
246            response.Printf("os_version:%u", major);
247            if (minor != UINT32_MAX)
248            {
249                response.Printf(".%u", minor);
250                if (update != UINT32_MAX)
251                    response.Printf(".%u", update);
252            }
253            response.PutChar(';');
254        }
255    }
256
257    std::string s;
258    if (Host::GetOSBuildString (s))
259    {
260        response.PutCString ("os_build:");
261        response.PutCStringAsRawHex8(s.c_str());
262        response.PutChar(';');
263    }
264    if (Host::GetOSKernelDescription (s))
265    {
266        response.PutCString ("os_kernel:");
267        response.PutCStringAsRawHex8(s.c_str());
268        response.PutChar(';');
269    }
270    if (Host::GetHostname (s))
271    {
272        response.PutCString ("hostname:");
273        response.PutCStringAsRawHex8(s.c_str());
274        response.PutChar(';');
275    }
276
277    return SendPacketNoLock (response.GetData(), response.GetSize()) > 0;
278}
279
280static void
281CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
282{
283    response.Printf ("pid:%llu;ppid:%llu;uid:%i;gid:%i;euid:%i;egid:%i;",
284                     proc_info.GetProcessID(),
285                     proc_info.GetParentProcessID(),
286                     proc_info.GetUserID(),
287                     proc_info.GetGroupID(),
288                     proc_info.GetEffectiveUserID(),
289                     proc_info.GetEffectiveGroupID());
290    response.PutCString ("name:");
291    response.PutCStringAsRawHex8(proc_info.GetName());
292    response.PutChar(';');
293    const ArchSpec &proc_arch = proc_info.GetArchitecture();
294    if (proc_arch.IsValid())
295    {
296        const llvm::Triple &proc_triple = proc_arch.GetTriple();
297        response.PutCString("triple:");
298        response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
299        response.PutChar(';');
300    }
301}
302
303bool
304GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
305{
306    // Packet format: "qProcessInfoPID:%i" where %i is the pid
307    packet.SetFilePos(::strlen ("qProcessInfoPID:"));
308    lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
309    if (pid != LLDB_INVALID_PROCESS_ID)
310    {
311        ProcessInstanceInfo proc_info;
312        if (Host::GetProcessInfo(pid, proc_info))
313        {
314            StreamString response;
315            CreateProcessInfoResponse (proc_info, response);
316            return SendPacketNoLock (response.GetData(), response.GetSize());
317        }
318    }
319    return SendErrorResponse (1);
320}
321
322bool
323GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
324{
325    m_proc_infos_index = 0;
326    m_proc_infos.Clear();
327
328    ProcessInstanceInfoMatch match_info;
329    packet.SetFilePos(::strlen ("qfProcessInfo"));
330    if (packet.GetChar() == ':')
331    {
332
333        std::string key;
334        std::string value;
335        while (packet.GetNameColonValue(key, value))
336        {
337            bool success = true;
338            if (key.compare("name") == 0)
339            {
340                StringExtractor extractor;
341                extractor.GetStringRef().swap(value);
342                extractor.GetHexByteString (value);
343                match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
344            }
345            else if (key.compare("name_match") == 0)
346            {
347                if (value.compare("equals") == 0)
348                {
349                    match_info.SetNameMatchType (eNameMatchEquals);
350                }
351                else if (value.compare("starts_with") == 0)
352                {
353                    match_info.SetNameMatchType (eNameMatchStartsWith);
354                }
355                else if (value.compare("ends_with") == 0)
356                {
357                    match_info.SetNameMatchType (eNameMatchEndsWith);
358                }
359                else if (value.compare("contains") == 0)
360                {
361                    match_info.SetNameMatchType (eNameMatchContains);
362                }
363                else if (value.compare("regex") == 0)
364                {
365                    match_info.SetNameMatchType (eNameMatchRegularExpression);
366                }
367                else
368                {
369                    success = false;
370                }
371            }
372            else if (key.compare("pid") == 0)
373            {
374                match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
375            }
376            else if (key.compare("parent_pid") == 0)
377            {
378                match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
379            }
380            else if (key.compare("uid") == 0)
381            {
382                match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
383            }
384            else if (key.compare("gid") == 0)
385            {
386                match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
387            }
388            else if (key.compare("euid") == 0)
389            {
390                match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
391            }
392            else if (key.compare("egid") == 0)
393            {
394                match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
395            }
396            else if (key.compare("all_users") == 0)
397            {
398                match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
399            }
400            else if (key.compare("triple") == 0)
401            {
402                match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
403            }
404            else
405            {
406                success = false;
407            }
408
409            if (!success)
410                return SendErrorResponse (2);
411        }
412    }
413
414    if (Host::FindProcesses (match_info, m_proc_infos))
415    {
416        // We found something, return the first item by calling the get
417        // subsequent process info packet handler...
418        return Handle_qsProcessInfo (packet);
419    }
420    return SendErrorResponse (3);
421}
422
423bool
424GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
425{
426    if (m_proc_infos_index < m_proc_infos.GetSize())
427    {
428        StreamString response;
429        CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
430        ++m_proc_infos_index;
431        return SendPacketNoLock (response.GetData(), response.GetSize());
432    }
433    return SendErrorResponse (4);
434}
435
436bool
437GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
438{
439    // Packet format: "qUserName:%i" where %i is the uid
440    packet.SetFilePos(::strlen ("qUserName:"));
441    uint32_t uid = packet.GetU32 (UINT32_MAX);
442    if (uid != UINT32_MAX)
443    {
444        std::string name;
445        if (Host::GetUserName (uid, name))
446        {
447            StreamString response;
448            response.PutCStringAsRawHex8 (name.c_str());
449            return SendPacketNoLock (response.GetData(), response.GetSize());
450        }
451    }
452    return SendErrorResponse (5);
453
454}
455
456bool
457GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
458{
459    // Packet format: "qGroupName:%i" where %i is the gid
460    packet.SetFilePos(::strlen ("qGroupName:"));
461    uint32_t gid = packet.GetU32 (UINT32_MAX);
462    if (gid != UINT32_MAX)
463    {
464        std::string name;
465        if (Host::GetGroupName (gid, name))
466        {
467            StreamString response;
468            response.PutCStringAsRawHex8 (name.c_str());
469            return SendPacketNoLock (response.GetData(), response.GetSize());
470        }
471    }
472    return SendErrorResponse (6);
473}
474
475bool
476GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
477{
478    packet.SetFilePos(::strlen ("qSpeedTest:"));
479
480    std::string key;
481    std::string value;
482    bool success = packet.GetNameColonValue(key, value);
483    if (success && key.compare("response_size") == 0)
484    {
485        uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
486        if (success)
487        {
488            if (response_size == 0)
489                return SendOKResponse();
490            StreamString response;
491            uint32_t bytes_left = response_size;
492            response.PutCString("data:");
493            while (bytes_left > 0)
494            {
495                if (bytes_left >= 26)
496                {
497                    response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
498                    bytes_left -= 26;
499                }
500                else
501                {
502                    response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
503                    bytes_left = 0;
504                }
505            }
506            return SendPacketNoLock (response.GetData(), response.GetSize());
507        }
508    }
509    return SendErrorResponse (7);
510}
511
512
513static void *
514AcceptPortFromInferior (void *arg)
515{
516    const char *connect_url = (const char *)arg;
517    ConnectionFileDescriptor file_conn;
518    Error error;
519    if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
520    {
521        char pid_str[256];
522        ::memset (pid_str, 0, sizeof(pid_str));
523        ConnectionStatus status;
524        const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL);
525        if (pid_str_len > 0)
526        {
527            int pid = atoi (pid_str);
528            return (void *)(intptr_t)pid;
529        }
530    }
531    return NULL;
532}
533//
534//static bool
535//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
536//{
537//    const int time_delta_usecs = 100000;
538//    const int num_retries = timeout_in_seconds/time_delta_usecs;
539//    for (int i=0; i<num_retries; i++)
540//    {
541//        struct proc_bsdinfo bsd_info;
542//        int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
543//                                    (uint64_t) 0,
544//                                    &bsd_info,
545//                                    PROC_PIDTBSDINFO_SIZE);
546//
547//        switch (error)
548//        {
549//            case EINVAL:
550//            case ENOTSUP:
551//            case ESRCH:
552//            case EPERM:
553//                return false;
554//
555//            default:
556//                break;
557//
558//            case 0:
559//                if (bsd_info.pbi_status == SSTOP)
560//                    return true;
561//        }
562//        ::usleep (time_delta_usecs);
563//    }
564//    return false;
565//}
566
567bool
568GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
569{
570    // The 'A' packet is the most over designed packet ever here with
571    // redundant argument indexes, redundant argument lengths and needed hex
572    // encoded argument string values. Really all that is needed is a comma
573    // separated hex encoded argument value list, but we will stay true to the
574    // documented version of the 'A' packet here...
575
576    packet.SetFilePos(1); // Skip the 'A'
577    bool success = true;
578    while (success && packet.GetBytesLeft() > 0)
579    {
580        // Decode the decimal argument string length. This length is the
581        // number of hex nibbles in the argument string value.
582        const uint32_t arg_len = packet.GetU32(UINT32_MAX);
583        if (arg_len == UINT32_MAX)
584            success = false;
585        else
586        {
587            // Make sure the argument hex string length is followed by a comma
588            if (packet.GetChar() != ',')
589                success = false;
590            else
591            {
592                // Decode the argument index. We ignore this really becuase
593                // who would really send down the arguments in a random order???
594                const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
595                if (arg_idx == UINT32_MAX)
596                    success = false;
597                else
598                {
599                    // Make sure the argument index is followed by a comma
600                    if (packet.GetChar() != ',')
601                        success = false;
602                    else
603                    {
604                        // Decode the argument string value from hex bytes
605                        // back into a UTF8 string and make sure the length
606                        // matches the one supplied in the packet
607                        std::string arg;
608                        if (packet.GetHexByteString(arg) != (arg_len / 2))
609                            success = false;
610                        else
611                        {
612                            // If there are any bytes lft
613                            if (packet.GetBytesLeft())
614                            {
615                                if (packet.GetChar() != ',')
616                                    success = false;
617                            }
618
619                            if (success)
620                            {
621                                if (arg_idx == 0)
622                                    m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
623                                m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
624                            }
625                        }
626                    }
627                }
628            }
629        }
630    }
631
632    if (success)
633    {
634        m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
635        m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
636        if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
637        {
638            return SendOKResponse ();
639        }
640    }
641    return SendErrorResponse (8);
642}
643
644bool
645GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
646{
647    lldb::pid_t pid = m_process_launch_info.GetProcessID();
648    StreamString response;
649    response.Printf("QC%llx", pid);
650    if (m_is_platform)
651    {
652        // If we launch a process and this GDB server is acting as a platform,
653        // then we need to clear the process launch state so we can start
654        // launching another process. In order to launch a process a bunch or
655        // packets need to be sent: environment packets, working directory,
656        // disable ASLR, and many more settings. When we launch a process we
657        // then need to know when to clear this information. Currently we are
658        // selecting the 'qC' packet as that packet which seems to make the most
659        // sense.
660        if (pid != LLDB_INVALID_PROCESS_ID)
661        {
662            m_process_launch_info.Clear();
663        }
664    }
665    return SendPacketNoLock (response.GetData(), response.GetSize());
666}
667
668bool
669GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
670{
671    // Spawn a local debugserver as a platform so we can then attach or launch
672    // a process...
673
674    if (m_is_platform)
675    {
676        // Sleep and wait a bit for debugserver to start to listen...
677        ConnectionFileDescriptor file_conn;
678        char connect_url[PATH_MAX];
679        Error error;
680        char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
681        if (::mktemp (unix_socket_name) == NULL)
682        {
683            error.SetErrorString ("failed to make temporary path for a unix socket");
684        }
685        else
686        {
687            ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
688            // Spawn a new thread to accept the port that gets bound after
689            // binding to port 0 (zero).
690            lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
691                                                               AcceptPortFromInferior,
692                                                               connect_url,
693                                                               &error);
694
695            if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
696            {
697                // Spawn a debugserver and try to get
698                ProcessLaunchInfo debugserver_launch_info;
699                error = StartDebugserverProcess ("localhost:0",
700                                                 unix_socket_name,
701                                                 debugserver_launch_info);
702
703                lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
704                if (error.Success())
705                {
706                    bool success = false;
707
708                    thread_result_t accept_thread_result = NULL;
709                    if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
710                    {
711                        if (accept_thread_result)
712                        {
713                            uint16_t port = (intptr_t)accept_thread_result;
714                            char response[256];
715                            const int response_len = ::snprintf (response, sizeof(response), "pid:%llu;port:%u;", debugserver_pid, port);
716                            assert (response_len < sizeof(response));
717                            //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
718                            success = SendPacketNoLock (response, response_len) > 0;
719                        }
720                    }
721                    ::unlink (unix_socket_name);
722
723                    if (!success)
724                    {
725                        if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
726                            ::kill (debugserver_pid, SIGINT);
727                    }
728                    return success;
729                }
730            }
731        }
732    }
733    return SendErrorResponse (13);
734}
735
736bool
737GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
738{
739    if (m_process_launch_error.Success())
740        return SendOKResponse();
741    StreamString response;
742    response.PutChar('E');
743    response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
744    return SendPacketNoLock (response.GetData(), response.GetSize());
745}
746
747bool
748GDBRemoteCommunicationServer::Handle_QEnvironment  (StringExtractorGDBRemote &packet)
749{
750    packet.SetFilePos(::strlen ("QEnvironment:"));
751    const uint32_t bytes_left = packet.GetBytesLeft();
752    if (bytes_left > 0)
753    {
754        m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
755        return SendOKResponse ();
756    }
757    return SendErrorResponse (9);
758}
759
760bool
761GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
762{
763    packet.SetFilePos(::strlen ("QSetDisableASLR:"));
764    if (packet.GetU32(0))
765        m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
766    else
767        m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
768    return SendOKResponse ();
769}
770
771bool
772GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
773{
774    packet.SetFilePos(::strlen ("QSetWorkingDir:"));
775    std::string path;
776    packet.GetHexByteString(path);
777    m_process_launch_info.SwapWorkingDirectory (path);
778    return SendOKResponse ();
779}
780
781bool
782GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
783{
784    packet.SetFilePos(::strlen ("QSetSTDIN:"));
785    ProcessLaunchInfo::FileAction file_action;
786    std::string path;
787    packet.GetHexByteString(path);
788    const bool read = false;
789    const bool write = true;
790    if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
791    {
792        m_process_launch_info.AppendFileAction(file_action);
793        return SendOKResponse ();
794    }
795    return SendErrorResponse (10);
796}
797
798bool
799GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
800{
801    packet.SetFilePos(::strlen ("QSetSTDOUT:"));
802    ProcessLaunchInfo::FileAction file_action;
803    std::string path;
804    packet.GetHexByteString(path);
805    const bool read = true;
806    const bool write = false;
807    if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
808    {
809        m_process_launch_info.AppendFileAction(file_action);
810        return SendOKResponse ();
811    }
812    return SendErrorResponse (11);
813}
814
815bool
816GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
817{
818    packet.SetFilePos(::strlen ("QSetSTDERR:"));
819    ProcessLaunchInfo::FileAction file_action;
820    std::string path;
821    packet.GetHexByteString(path);
822    const bool read = true;
823    const bool write = false;
824    if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
825    {
826        m_process_launch_info.AppendFileAction(file_action);
827        return SendOKResponse ();
828    }
829    return SendErrorResponse (12);
830}
831
832bool
833GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
834{
835    // Send response first before changing m_send_acks to we ack this packet
836    SendOKResponse ();
837    m_send_acks = false;
838    return true;
839}
840