1254721Semaste//===-- GDBRemoteCommunicationServer.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 "GDBRemoteCommunicationServer.h"
12254721Semaste
13254721Semaste// C Includes
14254721Semaste// C++ Includes
15254721Semaste// Other libraries and framework includes
16254721Semaste#include "llvm/ADT/Triple.h"
17254721Semaste#include "lldb/Interpreter/Args.h"
18254721Semaste#include "lldb/Core/ConnectionFileDescriptor.h"
19254721Semaste#include "lldb/Core/Log.h"
20254721Semaste#include "lldb/Core/State.h"
21254721Semaste#include "lldb/Core/StreamString.h"
22254721Semaste#include "lldb/Host/Endian.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 "Utility/StringExtractorGDBRemote.h"
29254721Semaste#include "ProcessGDBRemote.h"
30254721Semaste#include "ProcessGDBRemoteLog.h"
31254721Semaste
32254721Semasteusing namespace lldb;
33254721Semasteusing namespace lldb_private;
34254721Semaste
35254721Semaste//----------------------------------------------------------------------
36254721Semaste// GDBRemoteCommunicationServer constructor
37254721Semaste//----------------------------------------------------------------------
38254721SemasteGDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
39254721Semaste    GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
40254721Semaste    m_async_thread (LLDB_INVALID_HOST_THREAD),
41254721Semaste    m_process_launch_info (),
42254721Semaste    m_process_launch_error (),
43254721Semaste    m_proc_infos (),
44254721Semaste    m_proc_infos_index (0),
45254721Semaste    m_lo_port_num (0),
46254721Semaste    m_hi_port_num (0)
47254721Semaste{
48254721Semaste}
49254721Semaste
50254721Semaste//----------------------------------------------------------------------
51254721Semaste// Destructor
52254721Semaste//----------------------------------------------------------------------
53254721SemasteGDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
54254721Semaste{
55254721Semaste}
56254721Semaste
57254721Semaste
58254721Semaste//void *
59254721Semaste//GDBRemoteCommunicationServer::AsyncThread (void *arg)
60254721Semaste//{
61254721Semaste//    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
62254721Semaste//
63254721Semaste//    Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
64254721Semaste//    if (log)
65254721Semaste//        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
66254721Semaste//
67254721Semaste//    StringExtractorGDBRemote packet;
68254721Semaste//
69254721Semaste//    while ()
70254721Semaste//    {
71254721Semaste//        if (packet.
72254721Semaste//    }
73254721Semaste//
74254721Semaste//    if (log)
75254721Semaste//        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
76254721Semaste//
77254721Semaste//    process->m_async_thread = LLDB_INVALID_HOST_THREAD;
78254721Semaste//    return NULL;
79254721Semaste//}
80254721Semaste//
81254721Semastebool
82254721SemasteGDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
83254721Semaste                                                        Error &error,
84254721Semaste                                                        bool &interrupt,
85254721Semaste                                                        bool &quit)
86254721Semaste{
87254721Semaste    StringExtractorGDBRemote packet;
88254721Semaste    if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec))
89254721Semaste    {
90254721Semaste        const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
91254721Semaste        switch (packet_type)
92254721Semaste        {
93254721Semaste            case StringExtractorGDBRemote::eServerPacketType_nack:
94254721Semaste            case StringExtractorGDBRemote::eServerPacketType_ack:
95254721Semaste                break;
96254721Semaste
97254721Semaste            case StringExtractorGDBRemote::eServerPacketType_invalid:
98254721Semaste                error.SetErrorString("invalid packet");
99254721Semaste                quit = true;
100254721Semaste                break;
101254721Semaste
102254721Semaste            case StringExtractorGDBRemote::eServerPacketType_interrupt:
103254721Semaste                error.SetErrorString("interrupt received");
104254721Semaste                interrupt = true;
105254721Semaste                break;
106254721Semaste
107254721Semaste            case StringExtractorGDBRemote::eServerPacketType_unimplemented:
108254721Semaste                return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
109254721Semaste
110254721Semaste            case StringExtractorGDBRemote::eServerPacketType_A:
111254721Semaste                return Handle_A (packet);
112254721Semaste
113254721Semaste            case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
114254721Semaste                return Handle_qfProcessInfo (packet);
115254721Semaste
116254721Semaste            case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
117254721Semaste                return Handle_qsProcessInfo (packet);
118254721Semaste
119254721Semaste            case StringExtractorGDBRemote::eServerPacketType_qC:
120254721Semaste                return Handle_qC (packet);
121254721Semaste
122254721Semaste            case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
123254721Semaste                return Handle_qHostInfo (packet);
124254721Semaste
125254721Semaste            case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
126254721Semaste                return Handle_qLaunchGDBServer (packet);
127254721Semaste
128254721Semaste            case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
129254721Semaste                return Handle_qLaunchSuccess (packet);
130254721Semaste
131254721Semaste            case StringExtractorGDBRemote::eServerPacketType_qGroupName:
132254721Semaste                return Handle_qGroupName (packet);
133254721Semaste
134254721Semaste            case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
135254721Semaste                return Handle_qProcessInfoPID (packet);
136254721Semaste
137254721Semaste            case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
138254721Semaste                return Handle_qSpeedTest (packet);
139254721Semaste
140254721Semaste            case StringExtractorGDBRemote::eServerPacketType_qUserName:
141254721Semaste                return Handle_qUserName (packet);
142254721Semaste
143254721Semaste            case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
144254721Semaste                return Handle_QEnvironment (packet);
145254721Semaste
146254721Semaste            case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
147254721Semaste                return Handle_QSetDisableASLR (packet);
148254721Semaste
149254721Semaste            case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
150254721Semaste                return Handle_QSetSTDIN (packet);
151254721Semaste
152254721Semaste            case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
153254721Semaste                return Handle_QSetSTDOUT (packet);
154254721Semaste
155254721Semaste            case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
156254721Semaste                return Handle_QSetSTDERR (packet);
157254721Semaste
158254721Semaste            case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
159254721Semaste                return Handle_QSetWorkingDir (packet);
160254721Semaste
161254721Semaste            case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
162254721Semaste                return Handle_QStartNoAckMode (packet);
163254721Semaste        }
164254721Semaste        return true;
165254721Semaste    }
166254721Semaste    else
167254721Semaste    {
168254721Semaste        if (!IsConnected())
169254721Semaste            error.SetErrorString("lost connection");
170254721Semaste        else
171254721Semaste            error.SetErrorString("timeout");
172254721Semaste    }
173254721Semaste
174254721Semaste    return false;
175254721Semaste}
176254721Semaste
177254721Semastesize_t
178254721SemasteGDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
179254721Semaste{
180254721Semaste    // TODO: Log the packet we aren't handling...
181254721Semaste    return SendPacketNoLock ("", 0);
182254721Semaste}
183254721Semaste
184254721Semastesize_t
185254721SemasteGDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
186254721Semaste{
187254721Semaste    char packet[16];
188254721Semaste    int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
189254721Semaste    assert (packet_len < (int)sizeof(packet));
190254721Semaste    return SendPacketNoLock (packet, packet_len);
191254721Semaste}
192254721Semaste
193254721Semaste
194254721Semastesize_t
195254721SemasteGDBRemoteCommunicationServer::SendOKResponse ()
196254721Semaste{
197254721Semaste    return SendPacketNoLock ("OK", 2);
198254721Semaste}
199254721Semaste
200254721Semastebool
201254721SemasteGDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
202254721Semaste{
203254721Semaste    return GetAck();
204254721Semaste}
205254721Semaste
206254721Semastebool
207254721SemasteGDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
208254721Semaste{
209254721Semaste    StreamString response;
210254721Semaste
211254721Semaste    // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
212254721Semaste
213254721Semaste    ArchSpec host_arch (Host::GetArchitecture ());
214254721Semaste    const llvm::Triple &host_triple = host_arch.GetTriple();
215254721Semaste    response.PutCString("triple:");
216254721Semaste    response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
217254721Semaste    response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
218254721Semaste
219254721Semaste    uint32_t cpu = host_arch.GetMachOCPUType();
220254721Semaste    uint32_t sub = host_arch.GetMachOCPUSubType();
221254721Semaste    if (cpu != LLDB_INVALID_CPUTYPE)
222254721Semaste        response.Printf ("cputype:%u;", cpu);
223254721Semaste    if (sub != LLDB_INVALID_CPUTYPE)
224254721Semaste        response.Printf ("cpusubtype:%u;", sub);
225254721Semaste
226254721Semaste    if (cpu == ArchSpec::kCore_arm_any)
227254721Semaste        response.Printf("watchpoint_exceptions_received:before;");   // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
228254721Semaste    else
229254721Semaste        response.Printf("watchpoint_exceptions_received:after;");
230254721Semaste
231254721Semaste    switch (lldb::endian::InlHostByteOrder())
232254721Semaste    {
233254721Semaste    case eByteOrderBig:     response.PutCString ("endian:big;"); break;
234254721Semaste    case eByteOrderLittle:  response.PutCString ("endian:little;"); break;
235254721Semaste    case eByteOrderPDP:     response.PutCString ("endian:pdp;"); break;
236254721Semaste    default:                response.PutCString ("endian:unknown;"); break;
237254721Semaste    }
238254721Semaste
239254721Semaste    uint32_t major = UINT32_MAX;
240254721Semaste    uint32_t minor = UINT32_MAX;
241254721Semaste    uint32_t update = UINT32_MAX;
242254721Semaste    if (Host::GetOSVersion (major, minor, update))
243254721Semaste    {
244254721Semaste        if (major != UINT32_MAX)
245254721Semaste        {
246254721Semaste            response.Printf("os_version:%u", major);
247254721Semaste            if (minor != UINT32_MAX)
248254721Semaste            {
249254721Semaste                response.Printf(".%u", minor);
250254721Semaste                if (update != UINT32_MAX)
251254721Semaste                    response.Printf(".%u", update);
252254721Semaste            }
253254721Semaste            response.PutChar(';');
254254721Semaste        }
255254721Semaste    }
256254721Semaste
257254721Semaste    std::string s;
258254721Semaste    if (Host::GetOSBuildString (s))
259254721Semaste    {
260254721Semaste        response.PutCString ("os_build:");
261254721Semaste        response.PutCStringAsRawHex8(s.c_str());
262254721Semaste        response.PutChar(';');
263254721Semaste    }
264254721Semaste    if (Host::GetOSKernelDescription (s))
265254721Semaste    {
266254721Semaste        response.PutCString ("os_kernel:");
267254721Semaste        response.PutCStringAsRawHex8(s.c_str());
268254721Semaste        response.PutChar(';');
269254721Semaste    }
270254721Semaste    if (Host::GetHostname (s))
271254721Semaste    {
272254721Semaste        response.PutCString ("hostname:");
273254721Semaste        response.PutCStringAsRawHex8(s.c_str());
274254721Semaste        response.PutChar(';');
275254721Semaste    }
276254721Semaste
277254721Semaste    return SendPacketNoLock (response.GetData(), response.GetSize()) > 0;
278254721Semaste}
279254721Semaste
280254721Semastestatic void
281254721SemasteCreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
282254721Semaste{
283254721Semaste    response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
284254721Semaste                     proc_info.GetProcessID(),
285254721Semaste                     proc_info.GetParentProcessID(),
286254721Semaste                     proc_info.GetUserID(),
287254721Semaste                     proc_info.GetGroupID(),
288254721Semaste                     proc_info.GetEffectiveUserID(),
289254721Semaste                     proc_info.GetEffectiveGroupID());
290254721Semaste    response.PutCString ("name:");
291254721Semaste    response.PutCStringAsRawHex8(proc_info.GetName());
292254721Semaste    response.PutChar(';');
293254721Semaste    const ArchSpec &proc_arch = proc_info.GetArchitecture();
294254721Semaste    if (proc_arch.IsValid())
295254721Semaste    {
296254721Semaste        const llvm::Triple &proc_triple = proc_arch.GetTriple();
297254721Semaste        response.PutCString("triple:");
298254721Semaste        response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
299254721Semaste        response.PutChar(';');
300254721Semaste    }
301254721Semaste}
302254721Semaste
303254721Semastebool
304254721SemasteGDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
305254721Semaste{
306254721Semaste    // Packet format: "qProcessInfoPID:%i" where %i is the pid
307254721Semaste    packet.SetFilePos(::strlen ("qProcessInfoPID:"));
308254721Semaste    lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
309254721Semaste    if (pid != LLDB_INVALID_PROCESS_ID)
310254721Semaste    {
311254721Semaste        ProcessInstanceInfo proc_info;
312254721Semaste        if (Host::GetProcessInfo(pid, proc_info))
313254721Semaste        {
314254721Semaste            StreamString response;
315254721Semaste            CreateProcessInfoResponse (proc_info, response);
316254721Semaste            return SendPacketNoLock (response.GetData(), response.GetSize());
317254721Semaste        }
318254721Semaste    }
319254721Semaste    return SendErrorResponse (1);
320254721Semaste}
321254721Semaste
322254721Semastebool
323254721SemasteGDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
324254721Semaste{
325254721Semaste    m_proc_infos_index = 0;
326254721Semaste    m_proc_infos.Clear();
327254721Semaste
328254721Semaste    ProcessInstanceInfoMatch match_info;
329254721Semaste    packet.SetFilePos(::strlen ("qfProcessInfo"));
330254721Semaste    if (packet.GetChar() == ':')
331254721Semaste    {
332254721Semaste
333254721Semaste        std::string key;
334254721Semaste        std::string value;
335254721Semaste        while (packet.GetNameColonValue(key, value))
336254721Semaste        {
337254721Semaste            bool success = true;
338254721Semaste            if (key.compare("name") == 0)
339254721Semaste            {
340254721Semaste                StringExtractor extractor;
341254721Semaste                extractor.GetStringRef().swap(value);
342254721Semaste                extractor.GetHexByteString (value);
343254721Semaste                match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
344254721Semaste            }
345254721Semaste            else if (key.compare("name_match") == 0)
346254721Semaste            {
347254721Semaste                if (value.compare("equals") == 0)
348254721Semaste                {
349254721Semaste                    match_info.SetNameMatchType (eNameMatchEquals);
350254721Semaste                }
351254721Semaste                else if (value.compare("starts_with") == 0)
352254721Semaste                {
353254721Semaste                    match_info.SetNameMatchType (eNameMatchStartsWith);
354254721Semaste                }
355254721Semaste                else if (value.compare("ends_with") == 0)
356254721Semaste                {
357254721Semaste                    match_info.SetNameMatchType (eNameMatchEndsWith);
358254721Semaste                }
359254721Semaste                else if (value.compare("contains") == 0)
360254721Semaste                {
361254721Semaste                    match_info.SetNameMatchType (eNameMatchContains);
362254721Semaste                }
363254721Semaste                else if (value.compare("regex") == 0)
364254721Semaste                {
365254721Semaste                    match_info.SetNameMatchType (eNameMatchRegularExpression);
366254721Semaste                }
367254721Semaste                else
368254721Semaste                {
369254721Semaste                    success = false;
370254721Semaste                }
371254721Semaste            }
372254721Semaste            else if (key.compare("pid") == 0)
373254721Semaste            {
374254721Semaste                match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
375254721Semaste            }
376254721Semaste            else if (key.compare("parent_pid") == 0)
377254721Semaste            {
378254721Semaste                match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
379254721Semaste            }
380254721Semaste            else if (key.compare("uid") == 0)
381254721Semaste            {
382254721Semaste                match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
383254721Semaste            }
384254721Semaste            else if (key.compare("gid") == 0)
385254721Semaste            {
386254721Semaste                match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
387254721Semaste            }
388254721Semaste            else if (key.compare("euid") == 0)
389254721Semaste            {
390254721Semaste                match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
391254721Semaste            }
392254721Semaste            else if (key.compare("egid") == 0)
393254721Semaste            {
394254721Semaste                match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
395254721Semaste            }
396254721Semaste            else if (key.compare("all_users") == 0)
397254721Semaste            {
398254721Semaste                match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
399254721Semaste            }
400254721Semaste            else if (key.compare("triple") == 0)
401254721Semaste            {
402254721Semaste                match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
403254721Semaste            }
404254721Semaste            else
405254721Semaste            {
406254721Semaste                success = false;
407254721Semaste            }
408254721Semaste
409254721Semaste            if (!success)
410254721Semaste                return SendErrorResponse (2);
411254721Semaste        }
412254721Semaste    }
413254721Semaste
414254721Semaste    if (Host::FindProcesses (match_info, m_proc_infos))
415254721Semaste    {
416254721Semaste        // We found something, return the first item by calling the get
417254721Semaste        // subsequent process info packet handler...
418254721Semaste        return Handle_qsProcessInfo (packet);
419254721Semaste    }
420254721Semaste    return SendErrorResponse (3);
421254721Semaste}
422254721Semaste
423254721Semastebool
424254721SemasteGDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
425254721Semaste{
426254721Semaste    if (m_proc_infos_index < m_proc_infos.GetSize())
427254721Semaste    {
428254721Semaste        StreamString response;
429254721Semaste        CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
430254721Semaste        ++m_proc_infos_index;
431254721Semaste        return SendPacketNoLock (response.GetData(), response.GetSize());
432254721Semaste    }
433254721Semaste    return SendErrorResponse (4);
434254721Semaste}
435254721Semaste
436254721Semastebool
437254721SemasteGDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
438254721Semaste{
439254721Semaste    // Packet format: "qUserName:%i" where %i is the uid
440254721Semaste    packet.SetFilePos(::strlen ("qUserName:"));
441254721Semaste    uint32_t uid = packet.GetU32 (UINT32_MAX);
442254721Semaste    if (uid != UINT32_MAX)
443254721Semaste    {
444254721Semaste        std::string name;
445254721Semaste        if (Host::GetUserName (uid, name))
446254721Semaste        {
447254721Semaste            StreamString response;
448254721Semaste            response.PutCStringAsRawHex8 (name.c_str());
449254721Semaste            return SendPacketNoLock (response.GetData(), response.GetSize());
450254721Semaste        }
451254721Semaste    }
452254721Semaste    return SendErrorResponse (5);
453254721Semaste
454254721Semaste}
455254721Semaste
456254721Semastebool
457254721SemasteGDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
458254721Semaste{
459254721Semaste    // Packet format: "qGroupName:%i" where %i is the gid
460254721Semaste    packet.SetFilePos(::strlen ("qGroupName:"));
461254721Semaste    uint32_t gid = packet.GetU32 (UINT32_MAX);
462254721Semaste    if (gid != UINT32_MAX)
463254721Semaste    {
464254721Semaste        std::string name;
465254721Semaste        if (Host::GetGroupName (gid, name))
466254721Semaste        {
467254721Semaste            StreamString response;
468254721Semaste            response.PutCStringAsRawHex8 (name.c_str());
469254721Semaste            return SendPacketNoLock (response.GetData(), response.GetSize());
470254721Semaste        }
471254721Semaste    }
472254721Semaste    return SendErrorResponse (6);
473254721Semaste}
474254721Semaste
475254721Semastebool
476254721SemasteGDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
477254721Semaste{
478254721Semaste    packet.SetFilePos(::strlen ("qSpeedTest:"));
479254721Semaste
480254721Semaste    std::string key;
481254721Semaste    std::string value;
482254721Semaste    bool success = packet.GetNameColonValue(key, value);
483254721Semaste    if (success && key.compare("response_size") == 0)
484254721Semaste    {
485254721Semaste        uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
486254721Semaste        if (success)
487254721Semaste        {
488254721Semaste            if (response_size == 0)
489254721Semaste                return SendOKResponse();
490254721Semaste            StreamString response;
491254721Semaste            uint32_t bytes_left = response_size;
492254721Semaste            response.PutCString("data:");
493254721Semaste            while (bytes_left > 0)
494254721Semaste            {
495254721Semaste                if (bytes_left >= 26)
496254721Semaste                {
497254721Semaste                    response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
498254721Semaste                    bytes_left -= 26;
499254721Semaste                }
500254721Semaste                else
501254721Semaste                {
502254721Semaste                    response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
503254721Semaste                    bytes_left = 0;
504254721Semaste                }
505254721Semaste            }
506254721Semaste            return SendPacketNoLock (response.GetData(), response.GetSize());
507254721Semaste        }
508254721Semaste    }
509254721Semaste    return SendErrorResponse (7);
510254721Semaste}
511254721Semaste
512254721Semaste
513254721Semastestatic void *
514254721SemasteAcceptPortFromInferior (void *arg)
515254721Semaste{
516254721Semaste    const char *connect_url = (const char *)arg;
517254721Semaste    ConnectionFileDescriptor file_conn;
518254721Semaste    Error error;
519254721Semaste    if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
520254721Semaste    {
521254721Semaste        char pid_str[256];
522254721Semaste        ::memset (pid_str, 0, sizeof(pid_str));
523254721Semaste        ConnectionStatus status;
524254721Semaste        const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL);
525254721Semaste        if (pid_str_len > 0)
526254721Semaste        {
527254721Semaste            int pid = atoi (pid_str);
528254721Semaste            return (void *)(intptr_t)pid;
529254721Semaste        }
530254721Semaste    }
531254721Semaste    return NULL;
532254721Semaste}
533254721Semaste//
534254721Semaste//static bool
535254721Semaste//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
536254721Semaste//{
537254721Semaste//    const int time_delta_usecs = 100000;
538254721Semaste//    const int num_retries = timeout_in_seconds/time_delta_usecs;
539254721Semaste//    for (int i=0; i<num_retries; i++)
540254721Semaste//    {
541254721Semaste//        struct proc_bsdinfo bsd_info;
542254721Semaste//        int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
543254721Semaste//                                    (uint64_t) 0,
544254721Semaste//                                    &bsd_info,
545254721Semaste//                                    PROC_PIDTBSDINFO_SIZE);
546254721Semaste//
547254721Semaste//        switch (error)
548254721Semaste//        {
549254721Semaste//            case EINVAL:
550254721Semaste//            case ENOTSUP:
551254721Semaste//            case ESRCH:
552254721Semaste//            case EPERM:
553254721Semaste//                return false;
554254721Semaste//
555254721Semaste//            default:
556254721Semaste//                break;
557254721Semaste//
558254721Semaste//            case 0:
559254721Semaste//                if (bsd_info.pbi_status == SSTOP)
560254721Semaste//                    return true;
561254721Semaste//        }
562254721Semaste//        ::usleep (time_delta_usecs);
563254721Semaste//    }
564254721Semaste//    return false;
565254721Semaste//}
566254721Semaste
567254721Semastebool
568254721SemasteGDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
569254721Semaste{
570254721Semaste    // The 'A' packet is the most over designed packet ever here with
571254721Semaste    // redundant argument indexes, redundant argument lengths and needed hex
572254721Semaste    // encoded argument string values. Really all that is needed is a comma
573254721Semaste    // separated hex encoded argument value list, but we will stay true to the
574254721Semaste    // documented version of the 'A' packet here...
575254721Semaste
576254721Semaste    packet.SetFilePos(1); // Skip the 'A'
577254721Semaste    bool success = true;
578254721Semaste    while (success && packet.GetBytesLeft() > 0)
579254721Semaste    {
580254721Semaste        // Decode the decimal argument string length. This length is the
581254721Semaste        // number of hex nibbles in the argument string value.
582254721Semaste        const uint32_t arg_len = packet.GetU32(UINT32_MAX);
583254721Semaste        if (arg_len == UINT32_MAX)
584254721Semaste            success = false;
585254721Semaste        else
586254721Semaste        {
587254721Semaste            // Make sure the argument hex string length is followed by a comma
588254721Semaste            if (packet.GetChar() != ',')
589254721Semaste                success = false;
590254721Semaste            else
591254721Semaste            {
592254721Semaste                // Decode the argument index. We ignore this really becuase
593254721Semaste                // who would really send down the arguments in a random order???
594254721Semaste                const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
595254721Semaste                if (arg_idx == UINT32_MAX)
596254721Semaste                    success = false;
597254721Semaste                else
598254721Semaste                {
599254721Semaste                    // Make sure the argument index is followed by a comma
600254721Semaste                    if (packet.GetChar() != ',')
601254721Semaste                        success = false;
602254721Semaste                    else
603254721Semaste                    {
604254721Semaste                        // Decode the argument string value from hex bytes
605254721Semaste                        // back into a UTF8 string and make sure the length
606254721Semaste                        // matches the one supplied in the packet
607254721Semaste                        std::string arg;
608254721Semaste                        if (packet.GetHexByteString(arg) != (arg_len / 2))
609254721Semaste                            success = false;
610254721Semaste                        else
611254721Semaste                        {
612254721Semaste                            // If there are any bytes lft
613254721Semaste                            if (packet.GetBytesLeft())
614254721Semaste                            {
615254721Semaste                                if (packet.GetChar() != ',')
616254721Semaste                                    success = false;
617254721Semaste                            }
618254721Semaste
619254721Semaste                            if (success)
620254721Semaste                            {
621254721Semaste                                if (arg_idx == 0)
622254721Semaste                                    m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
623254721Semaste                                m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
624254721Semaste                            }
625254721Semaste                        }
626254721Semaste                    }
627254721Semaste                }
628254721Semaste            }
629254721Semaste        }
630254721Semaste    }
631254721Semaste
632254721Semaste    if (success)
633254721Semaste    {
634254721Semaste        m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
635254721Semaste        m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
636254721Semaste        if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
637254721Semaste        {
638254721Semaste            return SendOKResponse ();
639254721Semaste        }
640254721Semaste    }
641254721Semaste    return SendErrorResponse (8);
642254721Semaste}
643254721Semaste
644254721Semastebool
645254721SemasteGDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
646254721Semaste{
647254721Semaste    lldb::pid_t pid = m_process_launch_info.GetProcessID();
648254721Semaste    StreamString response;
649254721Semaste    response.Printf("QC%" PRIx64, pid);
650254721Semaste    if (m_is_platform)
651254721Semaste    {
652254721Semaste        // If we launch a process and this GDB server is acting as a platform,
653254721Semaste        // then we need to clear the process launch state so we can start
654254721Semaste        // launching another process. In order to launch a process a bunch or
655254721Semaste        // packets need to be sent: environment packets, working directory,
656254721Semaste        // disable ASLR, and many more settings. When we launch a process we
657254721Semaste        // then need to know when to clear this information. Currently we are
658254721Semaste        // selecting the 'qC' packet as that packet which seems to make the most
659254721Semaste        // sense.
660254721Semaste        if (pid != LLDB_INVALID_PROCESS_ID)
661254721Semaste        {
662254721Semaste            m_process_launch_info.Clear();
663254721Semaste        }
664254721Semaste    }
665254721Semaste    return SendPacketNoLock (response.GetData(), response.GetSize());
666254721Semaste}
667254721Semaste
668254721Semastebool
669254721SemasteGDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
670254721Semaste{
671254721Semaste    // Spawn a local debugserver as a platform so we can then attach or launch
672254721Semaste    // a process...
673254721Semaste
674254721Semaste    if (m_is_platform)
675254721Semaste    {
676254721Semaste        // Sleep and wait a bit for debugserver to start to listen...
677254721Semaste        ConnectionFileDescriptor file_conn;
678254721Semaste        char connect_url[PATH_MAX];
679254721Semaste        Error error;
680254721Semaste        char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
681254721Semaste        if (::mktemp (unix_socket_name) == NULL)
682254721Semaste        {
683254721Semaste            error.SetErrorString ("failed to make temporary path for a unix socket");
684254721Semaste        }
685254721Semaste        else
686254721Semaste        {
687254721Semaste            ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
688254721Semaste            // Spawn a new thread to accept the port that gets bound after
689254721Semaste            // binding to port 0 (zero).
690254721Semaste            lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
691254721Semaste                                                               AcceptPortFromInferior,
692254721Semaste                                                               connect_url,
693254721Semaste                                                               &error);
694254721Semaste
695254721Semaste            if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
696254721Semaste            {
697254721Semaste                // Spawn a debugserver and try to get
698254721Semaste                ProcessLaunchInfo debugserver_launch_info;
699254721Semaste                error = StartDebugserverProcess ("localhost:0",
700254721Semaste                                                 unix_socket_name,
701254721Semaste                                                 debugserver_launch_info);
702254721Semaste
703254721Semaste                lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
704254721Semaste                if (error.Success())
705254721Semaste                {
706254721Semaste                    bool success = false;
707254721Semaste
708254721Semaste                    thread_result_t accept_thread_result = NULL;
709254721Semaste                    if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
710254721Semaste                    {
711254721Semaste                        if (accept_thread_result)
712254721Semaste                        {
713254721Semaste                            uint16_t port = (intptr_t)accept_thread_result;
714254721Semaste                            char response[256];
715254721Semaste                            const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
716254721Semaste                            assert (response_len < (int)sizeof(response));
717254721Semaste                            //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
718254721Semaste                            success = SendPacketNoLock (response, response_len) > 0;
719254721Semaste                        }
720254721Semaste                    }
721254721Semaste                    ::unlink (unix_socket_name);
722254721Semaste
723254721Semaste                    if (!success)
724254721Semaste                    {
725254721Semaste                        if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
726254721Semaste                            ::kill (debugserver_pid, SIGINT);
727254721Semaste                    }
728254721Semaste                    return success;
729254721Semaste                }
730254721Semaste            }
731254721Semaste        }
732254721Semaste    }
733254721Semaste    return SendErrorResponse (13);
734254721Semaste}
735254721Semaste
736254721Semastebool
737254721SemasteGDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
738254721Semaste{
739254721Semaste    if (m_process_launch_error.Success())
740254721Semaste        return SendOKResponse();
741254721Semaste    StreamString response;
742254721Semaste    response.PutChar('E');
743254721Semaste    response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
744254721Semaste    return SendPacketNoLock (response.GetData(), response.GetSize());
745254721Semaste}
746254721Semaste
747254721Semastebool
748254721SemasteGDBRemoteCommunicationServer::Handle_QEnvironment  (StringExtractorGDBRemote &packet)
749254721Semaste{
750254721Semaste    packet.SetFilePos(::strlen ("QEnvironment:"));
751254721Semaste    const uint32_t bytes_left = packet.GetBytesLeft();
752254721Semaste    if (bytes_left > 0)
753254721Semaste    {
754254721Semaste        m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
755254721Semaste        return SendOKResponse ();
756254721Semaste    }
757254721Semaste    return SendErrorResponse (9);
758254721Semaste}
759254721Semaste
760254721Semastebool
761254721SemasteGDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
762254721Semaste{
763254721Semaste    packet.SetFilePos(::strlen ("QSetDisableASLR:"));
764254721Semaste    if (packet.GetU32(0))
765254721Semaste        m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
766254721Semaste    else
767254721Semaste        m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
768254721Semaste    return SendOKResponse ();
769254721Semaste}
770254721Semaste
771254721Semastebool
772254721SemasteGDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
773254721Semaste{
774254721Semaste    packet.SetFilePos(::strlen ("QSetWorkingDir:"));
775254721Semaste    std::string path;
776254721Semaste    packet.GetHexByteString(path);
777254721Semaste    m_process_launch_info.SwapWorkingDirectory (path);
778254721Semaste    return SendOKResponse ();
779254721Semaste}
780254721Semaste
781254721Semastebool
782254721SemasteGDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
783254721Semaste{
784254721Semaste    packet.SetFilePos(::strlen ("QSetSTDIN:"));
785254721Semaste    ProcessLaunchInfo::FileAction file_action;
786254721Semaste    std::string path;
787254721Semaste    packet.GetHexByteString(path);
788254721Semaste    const bool read = false;
789254721Semaste    const bool write = true;
790254721Semaste    if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
791254721Semaste    {
792254721Semaste        m_process_launch_info.AppendFileAction(file_action);
793254721Semaste        return SendOKResponse ();
794254721Semaste    }
795254721Semaste    return SendErrorResponse (10);
796254721Semaste}
797254721Semaste
798254721Semastebool
799254721SemasteGDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
800254721Semaste{
801254721Semaste    packet.SetFilePos(::strlen ("QSetSTDOUT:"));
802254721Semaste    ProcessLaunchInfo::FileAction file_action;
803254721Semaste    std::string path;
804254721Semaste    packet.GetHexByteString(path);
805254721Semaste    const bool read = true;
806254721Semaste    const bool write = false;
807254721Semaste    if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
808254721Semaste    {
809254721Semaste        m_process_launch_info.AppendFileAction(file_action);
810254721Semaste        return SendOKResponse ();
811254721Semaste    }
812254721Semaste    return SendErrorResponse (11);
813254721Semaste}
814254721Semaste
815254721Semastebool
816254721SemasteGDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
817254721Semaste{
818254721Semaste    packet.SetFilePos(::strlen ("QSetSTDERR:"));
819254721Semaste    ProcessLaunchInfo::FileAction file_action;
820254721Semaste    std::string path;
821254721Semaste    packet.GetHexByteString(path);
822254721Semaste    const bool read = true;
823254721Semaste    const bool write = false;
824254721Semaste    if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
825254721Semaste    {
826254721Semaste        m_process_launch_info.AppendFileAction(file_action);
827254721Semaste        return SendOKResponse ();
828254721Semaste    }
829254721Semaste    return SendErrorResponse (12);
830254721Semaste}
831254721Semaste
832254721Semastebool
833254721SemasteGDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
834254721Semaste{
835254721Semaste    // Send response first before changing m_send_acks to we ack this packet
836254721Semaste    SendOKResponse ();
837254721Semaste    m_send_acks = false;
838254721Semaste    return true;
839254721Semaste}
840