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
10263363Semaste#include <errno.h>
11254721Semaste
12254721Semaste#include "GDBRemoteCommunicationServer.h"
13263363Semaste#include "lldb/Core/StreamGDBRemote.h"
14254721Semaste
15254721Semaste// C Includes
16254721Semaste// C++ Includes
17254721Semaste// Other libraries and framework includes
18254721Semaste#include "llvm/ADT/Triple.h"
19254721Semaste#include "lldb/Interpreter/Args.h"
20254721Semaste#include "lldb/Core/ConnectionFileDescriptor.h"
21254721Semaste#include "lldb/Core/Log.h"
22254721Semaste#include "lldb/Core/State.h"
23254721Semaste#include "lldb/Core/StreamString.h"
24254721Semaste#include "lldb/Host/Endian.h"
25263363Semaste#include "lldb/Host/File.h"
26254721Semaste#include "lldb/Host/Host.h"
27254721Semaste#include "lldb/Host/TimeValue.h"
28269024Semaste#include "lldb/Target/Platform.h"
29254721Semaste#include "lldb/Target/Process.h"
30254721Semaste
31254721Semaste// Project includes
32254721Semaste#include "Utility/StringExtractorGDBRemote.h"
33254721Semaste#include "ProcessGDBRemote.h"
34254721Semaste#include "ProcessGDBRemoteLog.h"
35254721Semaste
36254721Semasteusing namespace lldb;
37254721Semasteusing namespace lldb_private;
38254721Semaste
39254721Semaste//----------------------------------------------------------------------
40254721Semaste// GDBRemoteCommunicationServer constructor
41254721Semaste//----------------------------------------------------------------------
42254721SemasteGDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
43254721Semaste    GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
44269024Semaste    m_platform_sp (Platform::GetDefaultPlatform ()),
45254721Semaste    m_async_thread (LLDB_INVALID_HOST_THREAD),
46254721Semaste    m_process_launch_info (),
47254721Semaste    m_process_launch_error (),
48263363Semaste    m_spawned_pids (),
49263363Semaste    m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
50254721Semaste    m_proc_infos (),
51254721Semaste    m_proc_infos_index (0),
52263367Semaste    m_port_map (),
53263367Semaste    m_port_offset(0)
54254721Semaste{
55254721Semaste}
56254721Semaste
57269024SemasteGDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform,
58269024Semaste                                                           const lldb::PlatformSP& platform_sp) :
59269024Semaste    GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
60269024Semaste    m_platform_sp (platform_sp),
61269024Semaste    m_async_thread (LLDB_INVALID_HOST_THREAD),
62269024Semaste    m_process_launch_info (),
63269024Semaste    m_process_launch_error (),
64269024Semaste    m_spawned_pids (),
65269024Semaste    m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
66269024Semaste    m_proc_infos (),
67269024Semaste    m_proc_infos_index (0),
68269024Semaste    m_port_map (),
69269024Semaste    m_port_offset(0)
70269024Semaste{
71269024Semaste    assert(platform_sp);
72269024Semaste}
73269024Semaste
74254721Semaste//----------------------------------------------------------------------
75254721Semaste// Destructor
76254721Semaste//----------------------------------------------------------------------
77254721SemasteGDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
78254721Semaste{
79254721Semaste}
80254721Semaste
81254721Semaste
82254721Semaste//void *
83254721Semaste//GDBRemoteCommunicationServer::AsyncThread (void *arg)
84254721Semaste//{
85254721Semaste//    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
86254721Semaste//
87254721Semaste//    Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
88254721Semaste//    if (log)
89254721Semaste//        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
90254721Semaste//
91254721Semaste//    StringExtractorGDBRemote packet;
92263363Semaste//
93254721Semaste//    while ()
94254721Semaste//    {
95254721Semaste//        if (packet.
96254721Semaste//    }
97254721Semaste//
98254721Semaste//    if (log)
99254721Semaste//        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
100254721Semaste//
101254721Semaste//    process->m_async_thread = LLDB_INVALID_HOST_THREAD;
102254721Semaste//    return NULL;
103254721Semaste//}
104254721Semaste//
105254721Semastebool
106263363SemasteGDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
107254721Semaste                                                        Error &error,
108263363Semaste                                                        bool &interrupt,
109254721Semaste                                                        bool &quit)
110254721Semaste{
111254721Semaste    StringExtractorGDBRemote packet;
112269024Semaste    PacketResult packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
113269024Semaste    if (packet_result == PacketResult::Success)
114254721Semaste    {
115254721Semaste        const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
116254721Semaste        switch (packet_type)
117254721Semaste        {
118269024Semaste        case StringExtractorGDBRemote::eServerPacketType_nack:
119269024Semaste        case StringExtractorGDBRemote::eServerPacketType_ack:
120269024Semaste            break;
121254721Semaste
122269024Semaste        case StringExtractorGDBRemote::eServerPacketType_invalid:
123269024Semaste            error.SetErrorString("invalid packet");
124269024Semaste            quit = true;
125269024Semaste            break;
126254721Semaste
127269024Semaste        case StringExtractorGDBRemote::eServerPacketType_interrupt:
128269024Semaste            error.SetErrorString("interrupt received");
129269024Semaste            interrupt = true;
130269024Semaste            break;
131263363Semaste
132269024Semaste        default:
133269024Semaste        case StringExtractorGDBRemote::eServerPacketType_unimplemented:
134269024Semaste            packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str());
135269024Semaste            break;
136254721Semaste
137269024Semaste        case StringExtractorGDBRemote::eServerPacketType_A:
138269024Semaste            packet_result = Handle_A (packet);
139269024Semaste            break;
140254721Semaste
141269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
142269024Semaste            packet_result = Handle_qfProcessInfo (packet);
143269024Semaste            break;
144263363Semaste
145269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
146269024Semaste            packet_result = Handle_qsProcessInfo (packet);
147269024Semaste            break;
148263363Semaste
149269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qC:
150269024Semaste            packet_result = Handle_qC (packet);
151269024Semaste            break;
152263363Semaste
153269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
154269024Semaste            packet_result = Handle_qHostInfo (packet);
155269024Semaste            break;
156263363Semaste
157269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
158269024Semaste            packet_result = Handle_qLaunchGDBServer (packet);
159269024Semaste            break;
160263363Semaste
161269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess:
162269024Semaste            packet_result = Handle_qKillSpawnedProcess (packet);
163269024Semaste            break;
164263363Semaste
165269024Semaste        case StringExtractorGDBRemote::eServerPacketType_k:
166269024Semaste            packet_result = Handle_k (packet);
167269024Semaste            break;
168263363Semaste
169269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
170269024Semaste            packet_result = Handle_qLaunchSuccess (packet);
171269024Semaste            break;
172254721Semaste
173269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qGroupName:
174269024Semaste            packet_result = Handle_qGroupName (packet);
175269024Semaste            break;
176254721Semaste
177269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
178269024Semaste            packet_result = Handle_qProcessInfoPID (packet);
179269024Semaste            break;
180254721Semaste
181269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
182269024Semaste            packet_result = Handle_qSpeedTest (packet);
183269024Semaste            break;
184254721Semaste
185269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qUserName:
186269024Semaste            packet_result = Handle_qUserName (packet);
187269024Semaste            break;
188263363Semaste
189269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir:
190269024Semaste            packet_result = Handle_qGetWorkingDir(packet);
191269024Semaste            break;
192263363Semaste
193269024Semaste        case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
194269024Semaste            packet_result = Handle_QEnvironment (packet);
195269024Semaste            break;
196263363Semaste
197269024Semaste        case StringExtractorGDBRemote::eServerPacketType_QLaunchArch:
198269024Semaste            packet_result = Handle_QLaunchArch (packet);
199269024Semaste            break;
200263363Semaste
201269024Semaste        case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
202269024Semaste            packet_result = Handle_QSetDisableASLR (packet);
203269024Semaste            break;
204263363Semaste
205269024Semaste        case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
206269024Semaste            packet_result = Handle_QSetSTDIN (packet);
207269024Semaste            break;
208263363Semaste
209269024Semaste        case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
210269024Semaste            packet_result = Handle_QSetSTDOUT (packet);
211269024Semaste            break;
212254721Semaste
213269024Semaste        case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
214269024Semaste            packet_result = Handle_QSetSTDERR (packet);
215269024Semaste            break;
216263363Semaste
217269024Semaste        case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
218269024Semaste            packet_result = Handle_QSetWorkingDir (packet);
219269024Semaste            break;
220263363Semaste
221269024Semaste        case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
222269024Semaste            packet_result = Handle_QStartNoAckMode (packet);
223269024Semaste            break;
224263363Semaste
225269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir:
226269024Semaste            packet_result = Handle_qPlatform_mkdir (packet);
227269024Semaste            break;
228263367Semaste
229269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod:
230269024Semaste            packet_result = Handle_qPlatform_chmod (packet);
231269024Semaste            break;
232263363Semaste
233269024Semaste        case StringExtractorGDBRemote::eServerPacketType_qPlatform_shell:
234269024Semaste            packet_result = Handle_qPlatform_shell (packet);
235269024Semaste            break;
236263363Semaste
237269024Semaste        case StringExtractorGDBRemote::eServerPacketType_vFile_open:
238269024Semaste            packet_result = Handle_vFile_Open (packet);
239269024Semaste            break;
240263363Semaste
241269024Semaste        case StringExtractorGDBRemote::eServerPacketType_vFile_close:
242269024Semaste            packet_result = Handle_vFile_Close (packet);
243269024Semaste            break;
244263363Semaste
245269024Semaste        case StringExtractorGDBRemote::eServerPacketType_vFile_pread:
246269024Semaste            packet_result = Handle_vFile_pRead (packet);
247269024Semaste            break;
248263363Semaste
249269024Semaste        case StringExtractorGDBRemote::eServerPacketType_vFile_pwrite:
250269024Semaste            packet_result = Handle_vFile_pWrite (packet);
251269024Semaste            break;
252263363Semaste
253269024Semaste        case StringExtractorGDBRemote::eServerPacketType_vFile_size:
254269024Semaste            packet_result = Handle_vFile_Size (packet);
255269024Semaste            break;
256263363Semaste
257269024Semaste        case StringExtractorGDBRemote::eServerPacketType_vFile_mode:
258269024Semaste            packet_result = Handle_vFile_Mode (packet);
259269024Semaste            break;
260263363Semaste
261269024Semaste        case StringExtractorGDBRemote::eServerPacketType_vFile_exists:
262269024Semaste            packet_result = Handle_vFile_Exists (packet);
263269024Semaste            break;
264263367Semaste
265269024Semaste        case StringExtractorGDBRemote::eServerPacketType_vFile_stat:
266269024Semaste            packet_result = Handle_vFile_Stat (packet);
267269024Semaste            break;
268269024Semaste
269269024Semaste        case StringExtractorGDBRemote::eServerPacketType_vFile_md5:
270269024Semaste            packet_result = Handle_vFile_MD5 (packet);
271269024Semaste            break;
272269024Semaste
273269024Semaste        case StringExtractorGDBRemote::eServerPacketType_vFile_symlink:
274269024Semaste            packet_result = Handle_vFile_symlink (packet);
275269024Semaste            break;
276269024Semaste
277269024Semaste        case StringExtractorGDBRemote::eServerPacketType_vFile_unlink:
278269024Semaste            packet_result = Handle_vFile_unlink (packet);
279269024Semaste            break;
280254721Semaste        }
281254721Semaste    }
282254721Semaste    else
283254721Semaste    {
284254721Semaste        if (!IsConnected())
285269024Semaste        {
286254721Semaste            error.SetErrorString("lost connection");
287269024Semaste            quit = true;
288269024Semaste        }
289254721Semaste        else
290269024Semaste        {
291254721Semaste            error.SetErrorString("timeout");
292269024Semaste        }
293254721Semaste    }
294269024Semaste    return packet_result == PacketResult::Success;
295269024Semaste}
296254721Semaste
297269024Semastelldb_private::Error
298269024SemasteGDBRemoteCommunicationServer::SetLaunchArguments (const char *const args[], int argc)
299269024Semaste{
300269024Semaste    if ((argc < 1) || !args || !args[0] || !args[0][0])
301269024Semaste        return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__);
302269024Semaste
303269024Semaste    m_process_launch_info.SetArguments (const_cast<const char**> (args), true);
304269024Semaste    return lldb_private::Error ();
305254721Semaste}
306254721Semaste
307269024Semastelldb_private::Error
308269024SemasteGDBRemoteCommunicationServer::SetLaunchFlags (unsigned int launch_flags)
309269024Semaste{
310269024Semaste    m_process_launch_info.GetFlags ().Set (launch_flags);
311269024Semaste    return lldb_private::Error ();
312269024Semaste}
313269024Semaste
314269024Semastelldb_private::Error
315269024SemasteGDBRemoteCommunicationServer::LaunchProcess ()
316269024Semaste{
317269024Semaste    if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
318269024Semaste        return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__);
319269024Semaste
320269024Semaste    // specify the process monitor if not already set.  This should
321269024Semaste    // generally be what happens since we need to reap started
322269024Semaste    // processes.
323269024Semaste    if (!m_process_launch_info.GetMonitorProcessCallback ())
324269024Semaste        m_process_launch_info.SetMonitorProcessCallback(ReapDebuggedProcess, this, false);
325269024Semaste
326269024Semaste    lldb_private::Error error = m_platform_sp->LaunchProcess (m_process_launch_info);
327269024Semaste    if (!error.Success ())
328269024Semaste    {
329269024Semaste        fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
330269024Semaste        return error;
331269024Semaste    }
332269024Semaste
333269024Semaste    printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID());
334269024Semaste
335269024Semaste    // add to list of spawned processes.  On an lldb-gdbserver, we
336269024Semaste    // would expect there to be only one.
337269024Semaste    lldb::pid_t pid;
338269024Semaste    if ( (pid = m_process_launch_info.GetProcessID()) != LLDB_INVALID_PROCESS_ID )
339269024Semaste    {
340269024Semaste        Mutex::Locker locker (m_spawned_pids_mutex);
341269024Semaste        m_spawned_pids.insert(pid);
342269024Semaste    }
343269024Semaste
344269024Semaste    return error;
345269024Semaste}
346269024Semaste
347269024SemasteGDBRemoteCommunication::PacketResult
348254721SemasteGDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
349254721Semaste{
350254721Semaste    // TODO: Log the packet we aren't handling...
351254721Semaste    return SendPacketNoLock ("", 0);
352254721Semaste}
353254721Semaste
354269024SemasteGDBRemoteCommunication::PacketResult
355254721SemasteGDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
356254721Semaste{
357254721Semaste    char packet[16];
358254721Semaste    int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
359254721Semaste    assert (packet_len < (int)sizeof(packet));
360254721Semaste    return SendPacketNoLock (packet, packet_len);
361254721Semaste}
362254721Semaste
363254721Semaste
364269024SemasteGDBRemoteCommunication::PacketResult
365254721SemasteGDBRemoteCommunicationServer::SendOKResponse ()
366254721Semaste{
367254721Semaste    return SendPacketNoLock ("OK", 2);
368254721Semaste}
369254721Semaste
370254721Semastebool
371254721SemasteGDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
372254721Semaste{
373269024Semaste    return GetAck() == PacketResult::Success;
374254721Semaste}
375254721Semaste
376269024SemasteGDBRemoteCommunication::PacketResult
377254721SemasteGDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
378254721Semaste{
379254721Semaste    StreamString response;
380263363Semaste
381254721Semaste    // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
382254721Semaste
383254721Semaste    ArchSpec host_arch (Host::GetArchitecture ());
384254721Semaste    const llvm::Triple &host_triple = host_arch.GetTriple();
385254721Semaste    response.PutCString("triple:");
386254721Semaste    response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
387254721Semaste    response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
388254721Semaste
389269024Semaste    const char* distribution_id = host_arch.GetDistributionId ().AsCString ();
390269024Semaste    if (distribution_id)
391269024Semaste    {
392269024Semaste        response.PutCString("distribution_id:");
393269024Semaste        response.PutCStringAsRawHex8(distribution_id);
394269024Semaste        response.PutCString(";");
395269024Semaste    }
396269024Semaste
397254721Semaste    uint32_t cpu = host_arch.GetMachOCPUType();
398254721Semaste    uint32_t sub = host_arch.GetMachOCPUSubType();
399254721Semaste    if (cpu != LLDB_INVALID_CPUTYPE)
400254721Semaste        response.Printf ("cputype:%u;", cpu);
401254721Semaste    if (sub != LLDB_INVALID_CPUTYPE)
402254721Semaste        response.Printf ("cpusubtype:%u;", sub);
403263363Semaste
404254721Semaste    if (cpu == ArchSpec::kCore_arm_any)
405254721Semaste        response.Printf("watchpoint_exceptions_received:before;");   // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
406254721Semaste    else
407254721Semaste        response.Printf("watchpoint_exceptions_received:after;");
408263363Semaste
409254721Semaste    switch (lldb::endian::InlHostByteOrder())
410254721Semaste    {
411254721Semaste    case eByteOrderBig:     response.PutCString ("endian:big;"); break;
412254721Semaste    case eByteOrderLittle:  response.PutCString ("endian:little;"); break;
413254721Semaste    case eByteOrderPDP:     response.PutCString ("endian:pdp;"); break;
414254721Semaste    default:                response.PutCString ("endian:unknown;"); break;
415254721Semaste    }
416263363Semaste
417254721Semaste    uint32_t major = UINT32_MAX;
418254721Semaste    uint32_t minor = UINT32_MAX;
419254721Semaste    uint32_t update = UINT32_MAX;
420254721Semaste    if (Host::GetOSVersion (major, minor, update))
421254721Semaste    {
422254721Semaste        if (major != UINT32_MAX)
423254721Semaste        {
424254721Semaste            response.Printf("os_version:%u", major);
425254721Semaste            if (minor != UINT32_MAX)
426254721Semaste            {
427254721Semaste                response.Printf(".%u", minor);
428254721Semaste                if (update != UINT32_MAX)
429254721Semaste                    response.Printf(".%u", update);
430254721Semaste            }
431254721Semaste            response.PutChar(';');
432254721Semaste        }
433254721Semaste    }
434254721Semaste
435254721Semaste    std::string s;
436254721Semaste    if (Host::GetOSBuildString (s))
437254721Semaste    {
438254721Semaste        response.PutCString ("os_build:");
439254721Semaste        response.PutCStringAsRawHex8(s.c_str());
440254721Semaste        response.PutChar(';');
441254721Semaste    }
442254721Semaste    if (Host::GetOSKernelDescription (s))
443254721Semaste    {
444254721Semaste        response.PutCString ("os_kernel:");
445254721Semaste        response.PutCStringAsRawHex8(s.c_str());
446254721Semaste        response.PutChar(';');
447254721Semaste    }
448263367Semaste#if defined(__APPLE__)
449263367Semaste
450263367Semaste#if defined(__arm__)
451263367Semaste    // For iOS devices, we are connected through a USB Mux so we never pretend
452263367Semaste    // to actually have a hostname as far as the remote lldb that is connecting
453263367Semaste    // to this lldb-platform is concerned
454263367Semaste    response.PutCString ("hostname:");
455263367Semaste    response.PutCStringAsRawHex8("localhost");
456263367Semaste    response.PutChar(';');
457263367Semaste#else   // #if defined(__arm__)
458254721Semaste    if (Host::GetHostname (s))
459254721Semaste    {
460254721Semaste        response.PutCString ("hostname:");
461254721Semaste        response.PutCStringAsRawHex8(s.c_str());
462254721Semaste        response.PutChar(';');
463254721Semaste    }
464263363Semaste
465263367Semaste#endif  // #if defined(__arm__)
466263367Semaste
467263367Semaste#else   // #if defined(__APPLE__)
468263367Semaste    if (Host::GetHostname (s))
469263367Semaste    {
470263367Semaste        response.PutCString ("hostname:");
471263367Semaste        response.PutCStringAsRawHex8(s.c_str());
472263367Semaste        response.PutChar(';');
473263367Semaste    }
474263367Semaste#endif  // #if defined(__APPLE__)
475263367Semaste
476269024Semaste    return SendPacketNoLock (response.GetData(), response.GetSize());
477254721Semaste}
478254721Semaste
479254721Semastestatic void
480254721SemasteCreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
481254721Semaste{
482254721Semaste    response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
483254721Semaste                     proc_info.GetProcessID(),
484254721Semaste                     proc_info.GetParentProcessID(),
485254721Semaste                     proc_info.GetUserID(),
486254721Semaste                     proc_info.GetGroupID(),
487254721Semaste                     proc_info.GetEffectiveUserID(),
488254721Semaste                     proc_info.GetEffectiveGroupID());
489254721Semaste    response.PutCString ("name:");
490254721Semaste    response.PutCStringAsRawHex8(proc_info.GetName());
491254721Semaste    response.PutChar(';');
492254721Semaste    const ArchSpec &proc_arch = proc_info.GetArchitecture();
493254721Semaste    if (proc_arch.IsValid())
494254721Semaste    {
495254721Semaste        const llvm::Triple &proc_triple = proc_arch.GetTriple();
496254721Semaste        response.PutCString("triple:");
497254721Semaste        response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
498254721Semaste        response.PutChar(';');
499254721Semaste    }
500254721Semaste}
501254721Semaste
502269024SemasteGDBRemoteCommunication::PacketResult
503254721SemasteGDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
504254721Semaste{
505254721Semaste    // Packet format: "qProcessInfoPID:%i" where %i is the pid
506254721Semaste    packet.SetFilePos(::strlen ("qProcessInfoPID:"));
507254721Semaste    lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
508254721Semaste    if (pid != LLDB_INVALID_PROCESS_ID)
509254721Semaste    {
510254721Semaste        ProcessInstanceInfo proc_info;
511254721Semaste        if (Host::GetProcessInfo(pid, proc_info))
512254721Semaste        {
513254721Semaste            StreamString response;
514254721Semaste            CreateProcessInfoResponse (proc_info, response);
515254721Semaste            return SendPacketNoLock (response.GetData(), response.GetSize());
516254721Semaste        }
517254721Semaste    }
518254721Semaste    return SendErrorResponse (1);
519254721Semaste}
520254721Semaste
521269024SemasteGDBRemoteCommunication::PacketResult
522254721SemasteGDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
523254721Semaste{
524254721Semaste    m_proc_infos_index = 0;
525254721Semaste    m_proc_infos.Clear();
526254721Semaste
527254721Semaste    ProcessInstanceInfoMatch match_info;
528254721Semaste    packet.SetFilePos(::strlen ("qfProcessInfo"));
529254721Semaste    if (packet.GetChar() == ':')
530254721Semaste    {
531263363Semaste
532254721Semaste        std::string key;
533254721Semaste        std::string value;
534254721Semaste        while (packet.GetNameColonValue(key, value))
535254721Semaste        {
536254721Semaste            bool success = true;
537254721Semaste            if (key.compare("name") == 0)
538254721Semaste            {
539254721Semaste                StringExtractor extractor;
540254721Semaste                extractor.GetStringRef().swap(value);
541254721Semaste                extractor.GetHexByteString (value);
542254721Semaste                match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
543254721Semaste            }
544254721Semaste            else if (key.compare("name_match") == 0)
545254721Semaste            {
546254721Semaste                if (value.compare("equals") == 0)
547254721Semaste                {
548254721Semaste                    match_info.SetNameMatchType (eNameMatchEquals);
549254721Semaste                }
550254721Semaste                else if (value.compare("starts_with") == 0)
551254721Semaste                {
552254721Semaste                    match_info.SetNameMatchType (eNameMatchStartsWith);
553254721Semaste                }
554254721Semaste                else if (value.compare("ends_with") == 0)
555254721Semaste                {
556254721Semaste                    match_info.SetNameMatchType (eNameMatchEndsWith);
557254721Semaste                }
558254721Semaste                else if (value.compare("contains") == 0)
559254721Semaste                {
560254721Semaste                    match_info.SetNameMatchType (eNameMatchContains);
561254721Semaste                }
562263363Semaste                else if (value.compare("regex") == 0)
563254721Semaste                {
564254721Semaste                    match_info.SetNameMatchType (eNameMatchRegularExpression);
565254721Semaste                }
566263363Semaste                else
567254721Semaste                {
568254721Semaste                    success = false;
569254721Semaste                }
570254721Semaste            }
571254721Semaste            else if (key.compare("pid") == 0)
572254721Semaste            {
573254721Semaste                match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
574254721Semaste            }
575254721Semaste            else if (key.compare("parent_pid") == 0)
576254721Semaste            {
577254721Semaste                match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
578254721Semaste            }
579254721Semaste            else if (key.compare("uid") == 0)
580254721Semaste            {
581254721Semaste                match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
582254721Semaste            }
583254721Semaste            else if (key.compare("gid") == 0)
584254721Semaste            {
585254721Semaste                match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
586254721Semaste            }
587254721Semaste            else if (key.compare("euid") == 0)
588254721Semaste            {
589254721Semaste                match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
590254721Semaste            }
591254721Semaste            else if (key.compare("egid") == 0)
592254721Semaste            {
593254721Semaste                match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
594254721Semaste            }
595254721Semaste            else if (key.compare("all_users") == 0)
596254721Semaste            {
597254721Semaste                match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
598254721Semaste            }
599254721Semaste            else if (key.compare("triple") == 0)
600254721Semaste            {
601254721Semaste                match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
602254721Semaste            }
603254721Semaste            else
604254721Semaste            {
605254721Semaste                success = false;
606254721Semaste            }
607263363Semaste
608254721Semaste            if (!success)
609254721Semaste                return SendErrorResponse (2);
610254721Semaste        }
611254721Semaste    }
612254721Semaste
613254721Semaste    if (Host::FindProcesses (match_info, m_proc_infos))
614254721Semaste    {
615254721Semaste        // We found something, return the first item by calling the get
616254721Semaste        // subsequent process info packet handler...
617254721Semaste        return Handle_qsProcessInfo (packet);
618254721Semaste    }
619254721Semaste    return SendErrorResponse (3);
620254721Semaste}
621254721Semaste
622269024SemasteGDBRemoteCommunication::PacketResult
623254721SemasteGDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
624254721Semaste{
625254721Semaste    if (m_proc_infos_index < m_proc_infos.GetSize())
626254721Semaste    {
627254721Semaste        StreamString response;
628254721Semaste        CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
629254721Semaste        ++m_proc_infos_index;
630254721Semaste        return SendPacketNoLock (response.GetData(), response.GetSize());
631254721Semaste    }
632254721Semaste    return SendErrorResponse (4);
633254721Semaste}
634254721Semaste
635269024SemasteGDBRemoteCommunication::PacketResult
636254721SemasteGDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
637254721Semaste{
638254721Semaste    // Packet format: "qUserName:%i" where %i is the uid
639254721Semaste    packet.SetFilePos(::strlen ("qUserName:"));
640254721Semaste    uint32_t uid = packet.GetU32 (UINT32_MAX);
641254721Semaste    if (uid != UINT32_MAX)
642254721Semaste    {
643254721Semaste        std::string name;
644254721Semaste        if (Host::GetUserName (uid, name))
645254721Semaste        {
646254721Semaste            StreamString response;
647254721Semaste            response.PutCStringAsRawHex8 (name.c_str());
648254721Semaste            return SendPacketNoLock (response.GetData(), response.GetSize());
649254721Semaste        }
650254721Semaste    }
651254721Semaste    return SendErrorResponse (5);
652263363Semaste
653254721Semaste}
654254721Semaste
655269024SemasteGDBRemoteCommunication::PacketResult
656254721SemasteGDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
657254721Semaste{
658254721Semaste    // Packet format: "qGroupName:%i" where %i is the gid
659254721Semaste    packet.SetFilePos(::strlen ("qGroupName:"));
660254721Semaste    uint32_t gid = packet.GetU32 (UINT32_MAX);
661254721Semaste    if (gid != UINT32_MAX)
662254721Semaste    {
663254721Semaste        std::string name;
664254721Semaste        if (Host::GetGroupName (gid, name))
665254721Semaste        {
666254721Semaste            StreamString response;
667254721Semaste            response.PutCStringAsRawHex8 (name.c_str());
668254721Semaste            return SendPacketNoLock (response.GetData(), response.GetSize());
669254721Semaste        }
670254721Semaste    }
671254721Semaste    return SendErrorResponse (6);
672254721Semaste}
673254721Semaste
674269024SemasteGDBRemoteCommunication::PacketResult
675254721SemasteGDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
676254721Semaste{
677254721Semaste    packet.SetFilePos(::strlen ("qSpeedTest:"));
678254721Semaste
679254721Semaste    std::string key;
680254721Semaste    std::string value;
681254721Semaste    bool success = packet.GetNameColonValue(key, value);
682254721Semaste    if (success && key.compare("response_size") == 0)
683254721Semaste    {
684254721Semaste        uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
685254721Semaste        if (success)
686254721Semaste        {
687254721Semaste            if (response_size == 0)
688254721Semaste                return SendOKResponse();
689254721Semaste            StreamString response;
690254721Semaste            uint32_t bytes_left = response_size;
691254721Semaste            response.PutCString("data:");
692254721Semaste            while (bytes_left > 0)
693254721Semaste            {
694254721Semaste                if (bytes_left >= 26)
695254721Semaste                {
696254721Semaste                    response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
697254721Semaste                    bytes_left -= 26;
698254721Semaste                }
699254721Semaste                else
700254721Semaste                {
701254721Semaste                    response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
702254721Semaste                    bytes_left = 0;
703254721Semaste                }
704254721Semaste            }
705254721Semaste            return SendPacketNoLock (response.GetData(), response.GetSize());
706254721Semaste        }
707254721Semaste    }
708254721Semaste    return SendErrorResponse (7);
709254721Semaste}
710254721Semaste
711254721Semaste
712254721Semastestatic void *
713254721SemasteAcceptPortFromInferior (void *arg)
714254721Semaste{
715254721Semaste    const char *connect_url = (const char *)arg;
716254721Semaste    ConnectionFileDescriptor file_conn;
717254721Semaste    Error error;
718254721Semaste    if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
719254721Semaste    {
720254721Semaste        char pid_str[256];
721254721Semaste        ::memset (pid_str, 0, sizeof(pid_str));
722254721Semaste        ConnectionStatus status;
723254721Semaste        const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL);
724254721Semaste        if (pid_str_len > 0)
725254721Semaste        {
726254721Semaste            int pid = atoi (pid_str);
727254721Semaste            return (void *)(intptr_t)pid;
728254721Semaste        }
729254721Semaste    }
730254721Semaste    return NULL;
731254721Semaste}
732254721Semaste//
733254721Semaste//static bool
734254721Semaste//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
735254721Semaste//{
736254721Semaste//    const int time_delta_usecs = 100000;
737254721Semaste//    const int num_retries = timeout_in_seconds/time_delta_usecs;
738254721Semaste//    for (int i=0; i<num_retries; i++)
739254721Semaste//    {
740254721Semaste//        struct proc_bsdinfo bsd_info;
741263363Semaste//        int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
742263363Semaste//                                    (uint64_t) 0,
743263363Semaste//                                    &bsd_info,
744254721Semaste//                                    PROC_PIDTBSDINFO_SIZE);
745263363Semaste//
746254721Semaste//        switch (error)
747254721Semaste//        {
748254721Semaste//            case EINVAL:
749254721Semaste//            case ENOTSUP:
750254721Semaste//            case ESRCH:
751254721Semaste//            case EPERM:
752254721Semaste//                return false;
753263363Semaste//
754254721Semaste//            default:
755254721Semaste//                break;
756263363Semaste//
757254721Semaste//            case 0:
758254721Semaste//                if (bsd_info.pbi_status == SSTOP)
759254721Semaste//                    return true;
760254721Semaste//        }
761254721Semaste//        ::usleep (time_delta_usecs);
762254721Semaste//    }
763254721Semaste//    return false;
764254721Semaste//}
765254721Semaste
766269024SemasteGDBRemoteCommunication::PacketResult
767254721SemasteGDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
768254721Semaste{
769263363Semaste    // The 'A' packet is the most over designed packet ever here with
770263363Semaste    // redundant argument indexes, redundant argument lengths and needed hex
771263363Semaste    // encoded argument string values. Really all that is needed is a comma
772254721Semaste    // separated hex encoded argument value list, but we will stay true to the
773254721Semaste    // documented version of the 'A' packet here...
774254721Semaste
775254721Semaste    packet.SetFilePos(1); // Skip the 'A'
776254721Semaste    bool success = true;
777254721Semaste    while (success && packet.GetBytesLeft() > 0)
778254721Semaste    {
779254721Semaste        // Decode the decimal argument string length. This length is the
780254721Semaste        // number of hex nibbles in the argument string value.
781254721Semaste        const uint32_t arg_len = packet.GetU32(UINT32_MAX);
782254721Semaste        if (arg_len == UINT32_MAX)
783254721Semaste            success = false;
784254721Semaste        else
785254721Semaste        {
786254721Semaste            // Make sure the argument hex string length is followed by a comma
787254721Semaste            if (packet.GetChar() != ',')
788254721Semaste                success = false;
789254721Semaste            else
790254721Semaste            {
791254721Semaste                // Decode the argument index. We ignore this really becuase
792254721Semaste                // who would really send down the arguments in a random order???
793254721Semaste                const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
794254721Semaste                if (arg_idx == UINT32_MAX)
795254721Semaste                    success = false;
796254721Semaste                else
797254721Semaste                {
798254721Semaste                    // Make sure the argument index is followed by a comma
799254721Semaste                    if (packet.GetChar() != ',')
800254721Semaste                        success = false;
801254721Semaste                    else
802254721Semaste                    {
803254721Semaste                        // Decode the argument string value from hex bytes
804254721Semaste                        // back into a UTF8 string and make sure the length
805254721Semaste                        // matches the one supplied in the packet
806254721Semaste                        std::string arg;
807254721Semaste                        if (packet.GetHexByteString(arg) != (arg_len / 2))
808254721Semaste                            success = false;
809254721Semaste                        else
810254721Semaste                        {
811254721Semaste                            // If there are any bytes lft
812254721Semaste                            if (packet.GetBytesLeft())
813254721Semaste                            {
814254721Semaste                                if (packet.GetChar() != ',')
815254721Semaste                                    success = false;
816254721Semaste                            }
817263363Semaste
818254721Semaste                            if (success)
819254721Semaste                            {
820254721Semaste                                if (arg_idx == 0)
821254721Semaste                                    m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
822254721Semaste                                m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
823254721Semaste                            }
824254721Semaste                        }
825254721Semaste                    }
826254721Semaste                }
827254721Semaste            }
828254721Semaste        }
829254721Semaste    }
830254721Semaste
831254721Semaste    if (success)
832254721Semaste    {
833269024Semaste        // FIXME: remove linux restriction once eLaunchFlagDebug is supported
834269024Semaste#if !defined (__linux__)
835254721Semaste        m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
836269024Semaste#endif
837269024Semaste        m_process_launch_error = LaunchProcess ();
838254721Semaste        if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
839254721Semaste        {
840254721Semaste            return SendOKResponse ();
841254721Semaste        }
842254721Semaste    }
843254721Semaste    return SendErrorResponse (8);
844254721Semaste}
845254721Semaste
846269024SemasteGDBRemoteCommunication::PacketResult
847254721SemasteGDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
848254721Semaste{
849254721Semaste    lldb::pid_t pid = m_process_launch_info.GetProcessID();
850254721Semaste    StreamString response;
851254721Semaste    response.Printf("QC%" PRIx64, pid);
852254721Semaste    if (m_is_platform)
853254721Semaste    {
854263363Semaste        // If we launch a process and this GDB server is acting as a platform,
855263363Semaste        // then we need to clear the process launch state so we can start
856254721Semaste        // launching another process. In order to launch a process a bunch or
857254721Semaste        // packets need to be sent: environment packets, working directory,
858263363Semaste        // disable ASLR, and many more settings. When we launch a process we
859254721Semaste        // then need to know when to clear this information. Currently we are
860254721Semaste        // selecting the 'qC' packet as that packet which seems to make the most
861254721Semaste        // sense.
862254721Semaste        if (pid != LLDB_INVALID_PROCESS_ID)
863254721Semaste        {
864254721Semaste            m_process_launch_info.Clear();
865254721Semaste        }
866254721Semaste    }
867254721Semaste    return SendPacketNoLock (response.GetData(), response.GetSize());
868254721Semaste}
869254721Semaste
870254721Semastebool
871263363SemasteGDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid)
872263363Semaste{
873263363Semaste    Mutex::Locker locker (m_spawned_pids_mutex);
874263367Semaste    FreePortForProcess(pid);
875263363Semaste    return m_spawned_pids.erase(pid) > 0;
876263363Semaste}
877263363Semastebool
878263363SemasteGDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton,
879263363Semaste                                                      lldb::pid_t pid,
880263363Semaste                                                      bool exited,
881263363Semaste                                                      int signal,    // Zero for no signal
882263363Semaste                                                      int status)    // Exit value of process if signal is zero
883263363Semaste{
884263363Semaste    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
885263363Semaste    server->DebugserverProcessReaped (pid);
886263363Semaste    return true;
887263363Semaste}
888263363Semaste
889263363Semastebool
890269024SemasteGDBRemoteCommunicationServer::DebuggedProcessReaped (lldb::pid_t pid)
891269024Semaste{
892269024Semaste    // reap a process that we were debugging (but not debugserver)
893269024Semaste    Mutex::Locker locker (m_spawned_pids_mutex);
894269024Semaste    return m_spawned_pids.erase(pid) > 0;
895269024Semaste}
896269024Semaste
897269024Semastebool
898269024SemasteGDBRemoteCommunicationServer::ReapDebuggedProcess (void *callback_baton,
899269024Semaste                                                   lldb::pid_t pid,
900269024Semaste                                                   bool exited,
901269024Semaste                                                   int signal,    // Zero for no signal
902269024Semaste                                                   int status)    // Exit value of process if signal is zero
903269024Semaste{
904269024Semaste    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
905269024Semaste    server->DebuggedProcessReaped (pid);
906269024Semaste    return true;
907269024Semaste}
908269024Semaste
909269024SemasteGDBRemoteCommunication::PacketResult
910254721SemasteGDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
911254721Semaste{
912263363Semaste#ifdef _WIN32
913269024Semaste    return SendErrorResponse(9);
914263363Semaste#else
915254721Semaste    // Spawn a local debugserver as a platform so we can then attach or launch
916254721Semaste    // a process...
917254721Semaste
918254721Semaste    if (m_is_platform)
919254721Semaste    {
920254721Semaste        // Sleep and wait a bit for debugserver to start to listen...
921254721Semaste        ConnectionFileDescriptor file_conn;
922254721Semaste        Error error;
923263363Semaste        std::string hostname;
924263363Semaste        // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
925263363Semaste        // with the TMPDIR environnement variable
926263367Semaste        packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
927263367Semaste        std::string name;
928263367Semaste        std::string value;
929263367Semaste        uint16_t port = UINT16_MAX;
930263367Semaste        while (packet.GetNameColonValue(name, value))
931254721Semaste        {
932263367Semaste            if (name.compare ("host") == 0)
933263367Semaste                hostname.swap(value);
934263367Semaste            else if (name.compare ("port") == 0)
935263367Semaste                port = Args::StringToUInt32(value.c_str(), 0, 0);
936254721Semaste        }
937263367Semaste        if (port == UINT16_MAX)
938263367Semaste            port = GetNextAvailablePort();
939263363Semaste
940263367Semaste        // Spawn a new thread to accept the port that gets bound after
941263367Semaste        // binding to port 0 (zero).
942263363Semaste
943263367Semaste        if (error.Success())
944263367Semaste        {
945263367Semaste            // Spawn a debugserver and try to get the port it listens to.
946263367Semaste            ProcessLaunchInfo debugserver_launch_info;
947263367Semaste            if (hostname.empty())
948263367Semaste                hostname = "localhost";
949263367Semaste            Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
950263367Semaste            if (log)
951269024Semaste                log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);
952263367Semaste
953263367Semaste            debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
954263367Semaste
955269024Semaste            error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(),
956269024Semaste                                             port,
957269024Semaste                                             debugserver_launch_info,
958269024Semaste                                             port);
959263367Semaste
960263367Semaste            lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
961263367Semaste
962263367Semaste
963263367Semaste            if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
964254721Semaste            {
965263367Semaste                Mutex::Locker locker (m_spawned_pids_mutex);
966263367Semaste                m_spawned_pids.insert(debugserver_pid);
967263367Semaste                if (port > 0)
968263367Semaste                    AssociatePortWithProcess(port, debugserver_pid);
969263367Semaste            }
970263367Semaste            else
971263367Semaste            {
972263367Semaste                if (port > 0)
973263367Semaste                    FreePort (port);
974263367Semaste            }
975263363Semaste
976263367Semaste            if (error.Success())
977263367Semaste            {
978269024Semaste                char response[256];
979269024Semaste                const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
980269024Semaste                assert (response_len < sizeof(response));
981269024Semaste                PacketResult packet_result = SendPacketNoLock (response, response_len);
982263363Semaste
983269024Semaste                if (packet_result != PacketResult::Success)
984263363Semaste                {
985263367Semaste                    if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
986263367Semaste                        ::kill (debugserver_pid, SIGINT);
987254721Semaste                }
988269024Semaste                return packet_result;
989254721Semaste            }
990254721Semaste        }
991254721Semaste    }
992263363Semaste    return SendErrorResponse (9);
993263363Semaste#endif
994254721Semaste}
995254721Semaste
996254721Semastebool
997269024SemasteGDBRemoteCommunicationServer::KillSpawnedProcess (lldb::pid_t pid)
998263363Semaste{
999269024Semaste    // make sure we know about this process
1000263363Semaste    {
1001269024Semaste        Mutex::Locker locker (m_spawned_pids_mutex);
1002269024Semaste        if (m_spawned_pids.find(pid) == m_spawned_pids.end())
1003269024Semaste            return false;
1004269024Semaste    }
1005263363Semaste
1006269024Semaste    // first try a SIGTERM (standard kill)
1007269024Semaste    Host::Kill (pid, SIGTERM);
1008263363Semaste
1009269024Semaste    // check if that worked
1010269024Semaste    for (size_t i=0; i<10; ++i)
1011269024Semaste    {
1012263363Semaste        {
1013263363Semaste            Mutex::Locker locker (m_spawned_pids_mutex);
1014263363Semaste            if (m_spawned_pids.find(pid) == m_spawned_pids.end())
1015269024Semaste            {
1016269024Semaste                // it is now killed
1017269024Semaste                return true;
1018269024Semaste            }
1019263363Semaste        }
1020269024Semaste        usleep (10000);
1021269024Semaste    }
1022263363Semaste
1023269024Semaste    // check one more time after the final usleep
1024269024Semaste    {
1025269024Semaste        Mutex::Locker locker (m_spawned_pids_mutex);
1026269024Semaste        if (m_spawned_pids.find(pid) == m_spawned_pids.end())
1027269024Semaste            return true;
1028269024Semaste    }
1029269024Semaste
1030269024Semaste    // the launched process still lives.  Now try killling it again,
1031269024Semaste    // this time with an unblockable signal.
1032269024Semaste    Host::Kill (pid, SIGKILL);
1033269024Semaste
1034269024Semaste    for (size_t i=0; i<10; ++i)
1035269024Semaste    {
1036263363Semaste        {
1037269024Semaste            Mutex::Locker locker (m_spawned_pids_mutex);
1038269024Semaste            if (m_spawned_pids.find(pid) == m_spawned_pids.end())
1039263363Semaste            {
1040269024Semaste                // it is now killed
1041269024Semaste                return true;
1042263363Semaste            }
1043263363Semaste        }
1044269024Semaste        usleep (10000);
1045269024Semaste    }
1046263363Semaste
1047269024Semaste    // check one more time after the final usleep
1048269024Semaste    // Scope for locker
1049269024Semaste    {
1050269024Semaste        Mutex::Locker locker (m_spawned_pids_mutex);
1051269024Semaste        if (m_spawned_pids.find(pid) == m_spawned_pids.end())
1052269024Semaste            return true;
1053269024Semaste    }
1054269024Semaste
1055269024Semaste    // no luck - the process still lives
1056269024Semaste    return false;
1057269024Semaste}
1058269024Semaste
1059269024SemasteGDBRemoteCommunication::PacketResult
1060269024SemasteGDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
1061269024Semaste{
1062269024Semaste    packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
1063269024Semaste
1064269024Semaste    lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
1065269024Semaste
1066269024Semaste    // verify that we know anything about this pid.
1067269024Semaste    // Scope for locker
1068269024Semaste    {
1069269024Semaste        Mutex::Locker locker (m_spawned_pids_mutex);
1070269024Semaste        if (m_spawned_pids.find(pid) == m_spawned_pids.end())
1071263363Semaste        {
1072269024Semaste            // not a pid we know about
1073269024Semaste            return SendErrorResponse (10);
1074263363Semaste        }
1075269024Semaste    }
1076263363Semaste
1077269024Semaste    // go ahead and attempt to kill the spawned process
1078269024Semaste    if (KillSpawnedProcess (pid))
1079269024Semaste        return SendOKResponse ();
1080269024Semaste    else
1081269024Semaste        return SendErrorResponse (11);
1082269024Semaste}
1083269024Semaste
1084269024SemasteGDBRemoteCommunication::PacketResult
1085269024SemasteGDBRemoteCommunicationServer::Handle_k (StringExtractorGDBRemote &packet)
1086269024Semaste{
1087269024Semaste    // ignore for now if we're lldb_platform
1088269024Semaste    if (m_is_platform)
1089269024Semaste        return SendUnimplementedResponse (packet.GetStringRef().c_str());
1090269024Semaste
1091269024Semaste    // shutdown all spawned processes
1092269024Semaste    std::set<lldb::pid_t> spawned_pids_copy;
1093269024Semaste
1094269024Semaste    // copy pids
1095269024Semaste    {
1096269024Semaste        Mutex::Locker locker (m_spawned_pids_mutex);
1097269024Semaste        spawned_pids_copy.insert (m_spawned_pids.begin (), m_spawned_pids.end ());
1098269024Semaste    }
1099269024Semaste
1100269024Semaste    // nuke the spawned processes
1101269024Semaste    for (auto it = spawned_pids_copy.begin (); it != spawned_pids_copy.end (); ++it)
1102269024Semaste    {
1103269024Semaste        lldb::pid_t spawned_pid = *it;
1104269024Semaste        if (!KillSpawnedProcess (spawned_pid))
1105263363Semaste        {
1106269024Semaste            fprintf (stderr, "%s: failed to kill spawned pid %" PRIu64 ", ignoring.\n", __FUNCTION__, spawned_pid);
1107263363Semaste        }
1108263363Semaste    }
1109269024Semaste
1110269024Semaste    // TODO figure out how to shut down gracefully at this point
1111269024Semaste    return SendOKResponse ();
1112263363Semaste}
1113263363Semaste
1114269024SemasteGDBRemoteCommunication::PacketResult
1115254721SemasteGDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
1116254721Semaste{
1117254721Semaste    if (m_process_launch_error.Success())
1118254721Semaste        return SendOKResponse();
1119263363Semaste    StreamString response;
1120254721Semaste    response.PutChar('E');
1121254721Semaste    response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
1122254721Semaste    return SendPacketNoLock (response.GetData(), response.GetSize());
1123254721Semaste}
1124254721Semaste
1125269024SemasteGDBRemoteCommunication::PacketResult
1126254721SemasteGDBRemoteCommunicationServer::Handle_QEnvironment  (StringExtractorGDBRemote &packet)
1127254721Semaste{
1128254721Semaste    packet.SetFilePos(::strlen ("QEnvironment:"));
1129254721Semaste    const uint32_t bytes_left = packet.GetBytesLeft();
1130254721Semaste    if (bytes_left > 0)
1131254721Semaste    {
1132254721Semaste        m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
1133254721Semaste        return SendOKResponse ();
1134254721Semaste    }
1135263367Semaste    return SendErrorResponse (12);
1136254721Semaste}
1137254721Semaste
1138269024SemasteGDBRemoteCommunication::PacketResult
1139263363SemasteGDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
1140263363Semaste{
1141263363Semaste    packet.SetFilePos(::strlen ("QLaunchArch:"));
1142263363Semaste    const uint32_t bytes_left = packet.GetBytesLeft();
1143263363Semaste    if (bytes_left > 0)
1144263363Semaste    {
1145263363Semaste        const char* arch_triple = packet.Peek();
1146263363Semaste        ArchSpec arch_spec(arch_triple,NULL);
1147263363Semaste        m_process_launch_info.SetArchitecture(arch_spec);
1148263363Semaste        return SendOKResponse();
1149263363Semaste    }
1150263367Semaste    return SendErrorResponse(13);
1151263363Semaste}
1152263363Semaste
1153269024SemasteGDBRemoteCommunication::PacketResult
1154254721SemasteGDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
1155254721Semaste{
1156254721Semaste    packet.SetFilePos(::strlen ("QSetDisableASLR:"));
1157254721Semaste    if (packet.GetU32(0))
1158254721Semaste        m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
1159254721Semaste    else
1160254721Semaste        m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
1161254721Semaste    return SendOKResponse ();
1162254721Semaste}
1163254721Semaste
1164269024SemasteGDBRemoteCommunication::PacketResult
1165254721SemasteGDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
1166254721Semaste{
1167254721Semaste    packet.SetFilePos(::strlen ("QSetWorkingDir:"));
1168254721Semaste    std::string path;
1169254721Semaste    packet.GetHexByteString(path);
1170263367Semaste    if (m_is_platform)
1171263367Semaste    {
1172263367Semaste#ifdef _WIN32
1173263367Semaste        // Not implemented on Windows
1174263367Semaste        return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_QSetWorkingDir unimplemented");
1175263367Semaste#else
1176263367Semaste        // If this packet is sent to a platform, then change the current working directory
1177263367Semaste        if (::chdir(path.c_str()) != 0)
1178263367Semaste            return SendErrorResponse(errno);
1179263367Semaste#endif
1180263367Semaste    }
1181263367Semaste    else
1182263367Semaste    {
1183263367Semaste        m_process_launch_info.SwapWorkingDirectory (path);
1184263367Semaste    }
1185254721Semaste    return SendOKResponse ();
1186254721Semaste}
1187254721Semaste
1188269024SemasteGDBRemoteCommunication::PacketResult
1189263367SemasteGDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
1190263367Semaste{
1191263367Semaste    StreamString response;
1192263367Semaste
1193263367Semaste    if (m_is_platform)
1194263367Semaste    {
1195263367Semaste        // If this packet is sent to a platform, then change the current working directory
1196263367Semaste        char cwd[PATH_MAX];
1197263367Semaste        if (getcwd(cwd, sizeof(cwd)) == NULL)
1198263367Semaste        {
1199263367Semaste            return SendErrorResponse(errno);
1200263367Semaste        }
1201263367Semaste        else
1202263367Semaste        {
1203263367Semaste            response.PutBytesAsRawHex8(cwd, strlen(cwd));
1204269024Semaste            return SendPacketNoLock(response.GetData(), response.GetSize());
1205263367Semaste        }
1206263367Semaste    }
1207263367Semaste    else
1208263367Semaste    {
1209263367Semaste        const char *working_dir = m_process_launch_info.GetWorkingDirectory();
1210263367Semaste        if (working_dir && working_dir[0])
1211263367Semaste        {
1212263367Semaste            response.PutBytesAsRawHex8(working_dir, strlen(working_dir));
1213269024Semaste            return SendPacketNoLock(response.GetData(), response.GetSize());
1214263367Semaste        }
1215263367Semaste        else
1216263367Semaste        {
1217263367Semaste            return SendErrorResponse(14);
1218263367Semaste        }
1219263367Semaste    }
1220263367Semaste}
1221263367Semaste
1222269024SemasteGDBRemoteCommunication::PacketResult
1223254721SemasteGDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
1224254721Semaste{
1225254721Semaste    packet.SetFilePos(::strlen ("QSetSTDIN:"));
1226254721Semaste    ProcessLaunchInfo::FileAction file_action;
1227254721Semaste    std::string path;
1228254721Semaste    packet.GetHexByteString(path);
1229254721Semaste    const bool read = false;
1230254721Semaste    const bool write = true;
1231254721Semaste    if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
1232254721Semaste    {
1233254721Semaste        m_process_launch_info.AppendFileAction(file_action);
1234254721Semaste        return SendOKResponse ();
1235254721Semaste    }
1236263367Semaste    return SendErrorResponse (15);
1237254721Semaste}
1238254721Semaste
1239269024SemasteGDBRemoteCommunication::PacketResult
1240254721SemasteGDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
1241254721Semaste{
1242254721Semaste    packet.SetFilePos(::strlen ("QSetSTDOUT:"));
1243254721Semaste    ProcessLaunchInfo::FileAction file_action;
1244254721Semaste    std::string path;
1245254721Semaste    packet.GetHexByteString(path);
1246254721Semaste    const bool read = true;
1247254721Semaste    const bool write = false;
1248254721Semaste    if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
1249254721Semaste    {
1250254721Semaste        m_process_launch_info.AppendFileAction(file_action);
1251254721Semaste        return SendOKResponse ();
1252254721Semaste    }
1253263367Semaste    return SendErrorResponse (16);
1254254721Semaste}
1255254721Semaste
1256269024SemasteGDBRemoteCommunication::PacketResult
1257254721SemasteGDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
1258254721Semaste{
1259254721Semaste    packet.SetFilePos(::strlen ("QSetSTDERR:"));
1260254721Semaste    ProcessLaunchInfo::FileAction file_action;
1261254721Semaste    std::string path;
1262254721Semaste    packet.GetHexByteString(path);
1263254721Semaste    const bool read = true;
1264254721Semaste    const bool write = false;
1265254721Semaste    if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
1266254721Semaste    {
1267254721Semaste        m_process_launch_info.AppendFileAction(file_action);
1268254721Semaste        return SendOKResponse ();
1269254721Semaste    }
1270263367Semaste    return SendErrorResponse (17);
1271254721Semaste}
1272254721Semaste
1273269024SemasteGDBRemoteCommunication::PacketResult
1274254721SemasteGDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
1275254721Semaste{
1276254721Semaste    // Send response first before changing m_send_acks to we ack this packet
1277269024Semaste    PacketResult packet_result = SendOKResponse ();
1278254721Semaste    m_send_acks = false;
1279269024Semaste    return packet_result;
1280254721Semaste}
1281263363Semaste
1282269024SemasteGDBRemoteCommunication::PacketResult
1283263367SemasteGDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet)
1284263363Semaste{
1285263367Semaste    packet.SetFilePos(::strlen("qPlatform_mkdir:"));
1286263363Semaste    mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
1287263367Semaste    if (packet.GetChar() == ',')
1288263367Semaste    {
1289263367Semaste        std::string path;
1290263367Semaste        packet.GetHexByteString(path);
1291263367Semaste        Error error = Host::MakeDirectory(path.c_str(),mode);
1292263367Semaste        if (error.Success())
1293263367Semaste            return SendPacketNoLock ("OK", 2);
1294263367Semaste        else
1295263367Semaste            return SendErrorResponse(error.GetError());
1296263367Semaste    }
1297263367Semaste    return SendErrorResponse(20);
1298263363Semaste}
1299263363Semaste
1300269024SemasteGDBRemoteCommunication::PacketResult
1301263367SemasteGDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet)
1302263367Semaste{
1303263367Semaste    packet.SetFilePos(::strlen("qPlatform_chmod:"));
1304263367Semaste
1305263367Semaste    mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
1306263367Semaste    if (packet.GetChar() == ',')
1307263367Semaste    {
1308263367Semaste        std::string path;
1309263367Semaste        packet.GetHexByteString(path);
1310263367Semaste        Error error = Host::SetFilePermissions (path.c_str(), mode);
1311263367Semaste        if (error.Success())
1312263367Semaste            return SendPacketNoLock ("OK", 2);
1313263367Semaste        else
1314263367Semaste            return SendErrorResponse(error.GetError());
1315263367Semaste    }
1316263367Semaste    return SendErrorResponse(19);
1317263367Semaste}
1318263367Semaste
1319269024SemasteGDBRemoteCommunication::PacketResult
1320263363SemasteGDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet)
1321263363Semaste{
1322263363Semaste    packet.SetFilePos(::strlen("vFile:open:"));
1323263363Semaste    std::string path;
1324263363Semaste    packet.GetHexByteStringTerminatedBy(path,',');
1325263367Semaste    if (!path.empty())
1326263367Semaste    {
1327263367Semaste        if (packet.GetChar() == ',')
1328263367Semaste        {
1329263367Semaste            uint32_t flags = packet.GetHexMaxU32(false, 0);
1330263367Semaste            if (packet.GetChar() == ',')
1331263367Semaste            {
1332263367Semaste                mode_t mode = packet.GetHexMaxU32(false, 0600);
1333263367Semaste                Error error;
1334263367Semaste                int fd = ::open (path.c_str(), flags, mode);
1335263367Semaste                const int save_errno = fd == -1 ? errno : 0;
1336263367Semaste                StreamString response;
1337263367Semaste                response.PutChar('F');
1338263367Semaste                response.Printf("%i", fd);
1339263367Semaste                if (save_errno)
1340263367Semaste                    response.Printf(",%i", save_errno);
1341263367Semaste                return SendPacketNoLock(response.GetData(), response.GetSize());
1342263367Semaste            }
1343263367Semaste        }
1344263367Semaste    }
1345263367Semaste    return SendErrorResponse(18);
1346263363Semaste}
1347263363Semaste
1348269024SemasteGDBRemoteCommunication::PacketResult
1349263363SemasteGDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)
1350263363Semaste{
1351263363Semaste    packet.SetFilePos(::strlen("vFile:close:"));
1352263363Semaste    int fd = packet.GetS32(-1);
1353263363Semaste    Error error;
1354263363Semaste    int err = -1;
1355263363Semaste    int save_errno = 0;
1356263363Semaste    if (fd >= 0)
1357263363Semaste    {
1358263363Semaste        err = close(fd);
1359263363Semaste        save_errno = err == -1 ? errno : 0;
1360263363Semaste    }
1361263363Semaste    else
1362263363Semaste    {
1363263363Semaste        save_errno = EINVAL;
1364263363Semaste    }
1365263363Semaste    StreamString response;
1366263363Semaste    response.PutChar('F');
1367263363Semaste    response.Printf("%i", err);
1368263363Semaste    if (save_errno)
1369263363Semaste        response.Printf(",%i", save_errno);
1370263367Semaste    return SendPacketNoLock(response.GetData(), response.GetSize());
1371263363Semaste}
1372263363Semaste
1373269024SemasteGDBRemoteCommunication::PacketResult
1374263363SemasteGDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet)
1375263363Semaste{
1376263363Semaste#ifdef _WIN32
1377263363Semaste    // Not implemented on Windows
1378263367Semaste    return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pRead() unimplemented");
1379263363Semaste#else
1380263363Semaste    StreamGDBRemote response;
1381263363Semaste    packet.SetFilePos(::strlen("vFile:pread:"));
1382263363Semaste    int fd = packet.GetS32(-1);
1383263367Semaste    if (packet.GetChar() == ',')
1384263363Semaste    {
1385263367Semaste        uint64_t count = packet.GetU64(UINT64_MAX);
1386263367Semaste        if (packet.GetChar() == ',')
1387263367Semaste        {
1388263367Semaste            uint64_t offset = packet.GetU64(UINT32_MAX);
1389263367Semaste            if (count == UINT64_MAX)
1390263367Semaste            {
1391263367Semaste                response.Printf("F-1:%i", EINVAL);
1392263367Semaste                return SendPacketNoLock(response.GetData(), response.GetSize());
1393263367Semaste            }
1394263367Semaste
1395263367Semaste            std::string buffer(count, 0);
1396263367Semaste            const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
1397263367Semaste            const int save_errno = bytes_read == -1 ? errno : 0;
1398263367Semaste            response.PutChar('F');
1399263367Semaste            response.Printf("%zi", bytes_read);
1400263367Semaste            if (save_errno)
1401263367Semaste                response.Printf(",%i", save_errno);
1402263367Semaste            else
1403263367Semaste            {
1404263367Semaste                response.PutChar(';');
1405263367Semaste                response.PutEscapedBytes(&buffer[0], bytes_read);
1406263367Semaste            }
1407263367Semaste            return SendPacketNoLock(response.GetData(), response.GetSize());
1408263367Semaste        }
1409263363Semaste    }
1410263367Semaste    return SendErrorResponse(21);
1411263367Semaste
1412263363Semaste#endif
1413263363Semaste}
1414263363Semaste
1415269024SemasteGDBRemoteCommunication::PacketResult
1416263363SemasteGDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
1417263363Semaste{
1418263363Semaste#ifdef _WIN32
1419263367Semaste    return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pWrite() unimplemented");
1420263363Semaste#else
1421263363Semaste    packet.SetFilePos(::strlen("vFile:pwrite:"));
1422263363Semaste
1423263363Semaste    StreamGDBRemote response;
1424263363Semaste    response.PutChar('F');
1425263363Semaste
1426263363Semaste    int fd = packet.GetU32(UINT32_MAX);
1427263367Semaste    if (packet.GetChar() == ',')
1428263363Semaste    {
1429263367Semaste        off_t offset = packet.GetU64(UINT32_MAX);
1430263367Semaste        if (packet.GetChar() == ',')
1431263367Semaste        {
1432263367Semaste            std::string buffer;
1433263367Semaste            if (packet.GetEscapedBinaryData(buffer))
1434263367Semaste            {
1435263367Semaste                const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
1436263367Semaste                const int save_errno = bytes_written == -1 ? errno : 0;
1437263367Semaste                response.Printf("%zi", bytes_written);
1438263367Semaste                if (save_errno)
1439263367Semaste                    response.Printf(",%i", save_errno);
1440263367Semaste            }
1441263367Semaste            else
1442263367Semaste            {
1443263367Semaste                response.Printf ("-1,%i", EINVAL);
1444263367Semaste            }
1445263367Semaste            return SendPacketNoLock(response.GetData(), response.GetSize());
1446263367Semaste        }
1447263363Semaste    }
1448263367Semaste    return SendErrorResponse(27);
1449263363Semaste#endif
1450263363Semaste}
1451263363Semaste
1452269024SemasteGDBRemoteCommunication::PacketResult
1453263363SemasteGDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet)
1454263363Semaste{
1455263363Semaste    packet.SetFilePos(::strlen("vFile:size:"));
1456263363Semaste    std::string path;
1457263363Semaste    packet.GetHexByteString(path);
1458263367Semaste    if (!path.empty())
1459263363Semaste    {
1460263367Semaste        lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
1461263367Semaste        StreamString response;
1462263367Semaste        response.PutChar('F');
1463263367Semaste        response.PutHex64(retcode);
1464263367Semaste        if (retcode == UINT64_MAX)
1465263367Semaste        {
1466263367Semaste            response.PutChar(',');
1467263367Semaste            response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
1468263367Semaste        }
1469263367Semaste        return SendPacketNoLock(response.GetData(), response.GetSize());
1470263363Semaste    }
1471263367Semaste    return SendErrorResponse(22);
1472263363Semaste}
1473263363Semaste
1474269024SemasteGDBRemoteCommunication::PacketResult
1475263363SemasteGDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
1476263363Semaste{
1477263363Semaste    packet.SetFilePos(::strlen("vFile:mode:"));
1478263363Semaste    std::string path;
1479263363Semaste    packet.GetHexByteString(path);
1480263367Semaste    if (!path.empty())
1481263367Semaste    {
1482263367Semaste        Error error;
1483263367Semaste        const uint32_t mode = File::GetPermissions(path.c_str(), error);
1484263367Semaste        StreamString response;
1485263367Semaste        response.Printf("F%u", mode);
1486263367Semaste        if (mode == 0 || error.Fail())
1487263367Semaste            response.Printf(",%i", (int)error.GetError());
1488263367Semaste        return SendPacketNoLock(response.GetData(), response.GetSize());
1489263367Semaste    }
1490263367Semaste    return SendErrorResponse(23);
1491263363Semaste}
1492263363Semaste
1493269024SemasteGDBRemoteCommunication::PacketResult
1494263363SemasteGDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
1495263363Semaste{
1496263363Semaste    packet.SetFilePos(::strlen("vFile:exists:"));
1497263363Semaste    std::string path;
1498263363Semaste    packet.GetHexByteString(path);
1499263367Semaste    if (!path.empty())
1500263367Semaste    {
1501263367Semaste        bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
1502263367Semaste        StreamString response;
1503263367Semaste        response.PutChar('F');
1504263367Semaste        response.PutChar(',');
1505263367Semaste        if (retcode)
1506263367Semaste            response.PutChar('1');
1507263367Semaste        else
1508263367Semaste            response.PutChar('0');
1509263367Semaste        return SendPacketNoLock(response.GetData(), response.GetSize());
1510263367Semaste    }
1511263367Semaste    return SendErrorResponse(24);
1512263367Semaste}
1513263367Semaste
1514269024SemasteGDBRemoteCommunication::PacketResult
1515263367SemasteGDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &packet)
1516263367Semaste{
1517263367Semaste    packet.SetFilePos(::strlen("vFile:symlink:"));
1518263367Semaste    std::string dst, src;
1519263367Semaste    packet.GetHexByteStringTerminatedBy(dst, ',');
1520263367Semaste    packet.GetChar(); // Skip ',' char
1521263367Semaste    packet.GetHexByteString(src);
1522263367Semaste    Error error = Host::Symlink(src.c_str(), dst.c_str());
1523263363Semaste    StreamString response;
1524263367Semaste    response.Printf("F%u,%u", error.GetError(), error.GetError());
1525263367Semaste    return SendPacketNoLock(response.GetData(), response.GetSize());
1526263363Semaste}
1527263363Semaste
1528269024SemasteGDBRemoteCommunication::PacketResult
1529263367SemasteGDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &packet)
1530263363Semaste{
1531263367Semaste    packet.SetFilePos(::strlen("vFile:unlink:"));
1532263363Semaste    std::string path;
1533263367Semaste    packet.GetHexByteString(path);
1534263367Semaste    Error error = Host::Unlink(path.c_str());
1535263367Semaste    StreamString response;
1536263367Semaste    response.Printf("F%u,%u", error.GetError(), error.GetError());
1537263367Semaste    return SendPacketNoLock(response.GetData(), response.GetSize());
1538263367Semaste}
1539263367Semaste
1540269024SemasteGDBRemoteCommunication::PacketResult
1541263367SemasteGDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &packet)
1542263367Semaste{
1543263367Semaste    packet.SetFilePos(::strlen("qPlatform_shell:"));
1544263367Semaste    std::string path;
1545263363Semaste    std::string working_dir;
1546263363Semaste    packet.GetHexByteStringTerminatedBy(path,',');
1547263367Semaste    if (!path.empty())
1548263363Semaste    {
1549263367Semaste        if (packet.GetChar() == ',')
1550263367Semaste        {
1551263367Semaste            // FIXME: add timeout to qPlatform_shell packet
1552263367Semaste            // uint32_t timeout = packet.GetHexMaxU32(false, 32);
1553263367Semaste            uint32_t timeout = 10;
1554263367Semaste            if (packet.GetChar() == ',')
1555263367Semaste                packet.GetHexByteString(working_dir);
1556263367Semaste            int status, signo;
1557263367Semaste            std::string output;
1558263367Semaste            Error err = Host::RunShellCommand(path.c_str(),
1559263367Semaste                                              working_dir.empty() ? NULL : working_dir.c_str(),
1560263367Semaste                                              &status, &signo, &output, timeout);
1561263367Semaste            StreamGDBRemote response;
1562263367Semaste            if (err.Fail())
1563263367Semaste            {
1564263367Semaste                response.PutCString("F,");
1565263367Semaste                response.PutHex32(UINT32_MAX);
1566263367Semaste            }
1567263367Semaste            else
1568263367Semaste            {
1569263367Semaste                response.PutCString("F,");
1570263367Semaste                response.PutHex32(status);
1571263367Semaste                response.PutChar(',');
1572263367Semaste                response.PutHex32(signo);
1573263367Semaste                response.PutChar(',');
1574263367Semaste                response.PutEscapedBytes(output.c_str(), output.size());
1575263367Semaste            }
1576263367Semaste            return SendPacketNoLock(response.GetData(), response.GetSize());
1577263367Semaste        }
1578263363Semaste    }
1579263367Semaste    return SendErrorResponse(24);
1580263363Semaste}
1581263363Semaste
1582269024SemasteGDBRemoteCommunication::PacketResult
1583263363SemasteGDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
1584263363Semaste{
1585263367Semaste    return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_Stat() unimplemented");
1586263363Semaste}
1587263363Semaste
1588269024SemasteGDBRemoteCommunication::PacketResult
1589263363SemasteGDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
1590263363Semaste{
1591263367Semaste    packet.SetFilePos(::strlen("vFile:MD5:"));
1592263363Semaste    std::string path;
1593263363Semaste    packet.GetHexByteString(path);
1594263367Semaste    if (!path.empty())
1595263363Semaste    {
1596263367Semaste        uint64_t a,b;
1597263367Semaste        StreamGDBRemote response;
1598263367Semaste        if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false)
1599263367Semaste        {
1600263367Semaste            response.PutCString("F,");
1601263367Semaste            response.PutCString("x");
1602263367Semaste        }
1603263367Semaste        else
1604263367Semaste        {
1605263367Semaste            response.PutCString("F,");
1606263367Semaste            response.PutHex64(a);
1607263367Semaste            response.PutHex64(b);
1608263367Semaste        }
1609263367Semaste        return SendPacketNoLock(response.GetData(), response.GetSize());
1610263363Semaste    }
1611263367Semaste    return SendErrorResponse(25);
1612263363Semaste}
1613263367Semaste
1614