xref: /llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (revision fbb7634934d40548b650574a2f2a85ab41527674)
1 //===-- GDBRemoteCommunicationServer.cpp ------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include <errno.h>
11 
12 #include "GDBRemoteCommunicationServer.h"
13 #include "lldb/Core/StreamGDBRemote.h"
14 
15 // C Includes
16 // C++ Includes
17 // Other libraries and framework includes
18 #include "llvm/ADT/Triple.h"
19 #include "lldb/Interpreter/Args.h"
20 #include "lldb/Core/ConnectionFileDescriptor.h"
21 #include "lldb/Core/Log.h"
22 #include "lldb/Core/State.h"
23 #include "lldb/Core/StreamString.h"
24 #include "lldb/Host/Endian.h"
25 #include "lldb/Host/File.h"
26 #include "lldb/Host/Host.h"
27 #include "lldb/Host/TimeValue.h"
28 #include "lldb/Target/Process.h"
29 
30 // Project includes
31 #include "Utility/StringExtractorGDBRemote.h"
32 #include "ProcessGDBRemote.h"
33 #include "ProcessGDBRemoteLog.h"
34 
35 using namespace lldb;
36 using namespace lldb_private;
37 
38 //----------------------------------------------------------------------
39 // GDBRemoteCommunicationServer constructor
40 //----------------------------------------------------------------------
41 GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
42     GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
43     m_async_thread (LLDB_INVALID_HOST_THREAD),
44     m_process_launch_info (),
45     m_process_launch_error (),
46     m_spawned_pids (),
47     m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
48     m_proc_infos (),
49     m_proc_infos_index (0),
50     m_lo_port_num (0),
51     m_hi_port_num (0),
52     m_next_port (0),
53     m_use_port_range (false)
54 {
55     // We seldom need to override the port number that the debugserver process
56     // starts with.  We just pass in 0 to let the system choose a random port.
57     // In rare situation where the need arises, use two environment variables
58     // to override.
59     uint16_t lo_port_num = 0;
60     uint16_t hi_port_num = 0;
61     const char *lo_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_LO_PORT");
62     if (lo_port_c_str)
63         lo_port_num = ::atoi(lo_port_c_str);
64     const char *hi_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_HI_PORT");
65     if (hi_port_c_str)
66         hi_port_num = ::atoi(hi_port_c_str);
67     if (lo_port_num && hi_port_num && lo_port_num < hi_port_num)
68     {
69         SetPortRange(lo_port_num, hi_port_num);
70     }
71 }
72 
73 //----------------------------------------------------------------------
74 // Destructor
75 //----------------------------------------------------------------------
76 GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
77 {
78 }
79 
80 
81 //void *
82 //GDBRemoteCommunicationServer::AsyncThread (void *arg)
83 //{
84 //    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
85 //
86 //    Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
87 //    if (log)
88 //        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
89 //
90 //    StringExtractorGDBRemote packet;
91 //
92 //    while ()
93 //    {
94 //        if (packet.
95 //    }
96 //
97 //    if (log)
98 //        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
99 //
100 //    process->m_async_thread = LLDB_INVALID_HOST_THREAD;
101 //    return NULL;
102 //}
103 //
104 bool
105 GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
106                                                         Error &error,
107                                                         bool &interrupt,
108                                                         bool &quit)
109 {
110     StringExtractorGDBRemote packet;
111     if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec))
112     {
113         const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
114         switch (packet_type)
115         {
116             case StringExtractorGDBRemote::eServerPacketType_nack:
117             case StringExtractorGDBRemote::eServerPacketType_ack:
118                 break;
119 
120             case StringExtractorGDBRemote::eServerPacketType_invalid:
121                 error.SetErrorString("invalid packet");
122                 quit = true;
123                 break;
124 
125             case StringExtractorGDBRemote::eServerPacketType_interrupt:
126                 error.SetErrorString("interrupt received");
127                 interrupt = true;
128                 break;
129 
130             case StringExtractorGDBRemote::eServerPacketType_unimplemented:
131                 return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
132 
133             case StringExtractorGDBRemote::eServerPacketType_A:
134                 return Handle_A (packet);
135 
136             case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
137                 return Handle_qfProcessInfo (packet);
138 
139             case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
140                 return Handle_qsProcessInfo (packet);
141 
142             case StringExtractorGDBRemote::eServerPacketType_qC:
143                 return Handle_qC (packet);
144 
145             case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
146                 return Handle_qHostInfo (packet);
147 
148             case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
149                 return Handle_qLaunchGDBServer (packet);
150 
151             case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess:
152                 return Handle_qKillSpawnedProcess (packet);
153 
154             case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
155                 return Handle_qLaunchSuccess (packet);
156 
157             case StringExtractorGDBRemote::eServerPacketType_qGroupName:
158                 return Handle_qGroupName (packet);
159 
160             case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
161                 return Handle_qProcessInfoPID (packet);
162 
163             case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
164                 return Handle_qSpeedTest (packet);
165 
166             case StringExtractorGDBRemote::eServerPacketType_qUserName:
167                 return Handle_qUserName (packet);
168 
169             case StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir:
170                 return Handle_qGetWorkingDir(packet);
171 
172             case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
173                 return Handle_QEnvironment (packet);
174 
175             case StringExtractorGDBRemote::eServerPacketType_QLaunchArch:
176                 return Handle_QLaunchArch (packet);
177 
178             case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
179                 return Handle_QSetDisableASLR (packet);
180 
181             case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
182                 return Handle_QSetSTDIN (packet);
183 
184             case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
185                 return Handle_QSetSTDOUT (packet);
186 
187             case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
188                 return Handle_QSetSTDERR (packet);
189 
190             case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
191                 return Handle_QSetWorkingDir (packet);
192 
193             case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
194                 return Handle_QStartNoAckMode (packet);
195 
196             case StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir:
197                 return Handle_qPlatform_mkdir (packet);
198 
199             case StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod:
200                 return Handle_qPlatform_chmod (packet);
201 
202             case StringExtractorGDBRemote::eServerPacketType_qPlatform_shell:
203                 return Handle_qPlatform_shell (packet);
204 
205             case StringExtractorGDBRemote::eServerPacketType_vFile_open:
206                 return Handle_vFile_Open (packet);
207 
208             case StringExtractorGDBRemote::eServerPacketType_vFile_close:
209                 return Handle_vFile_Close (packet);
210 
211             case StringExtractorGDBRemote::eServerPacketType_vFile_pread:
212                 return Handle_vFile_pRead (packet);
213 
214             case StringExtractorGDBRemote::eServerPacketType_vFile_pwrite:
215                 return Handle_vFile_pWrite (packet);
216 
217             case StringExtractorGDBRemote::eServerPacketType_vFile_size:
218                 return Handle_vFile_Size (packet);
219 
220             case StringExtractorGDBRemote::eServerPacketType_vFile_mode:
221                 return Handle_vFile_Mode (packet);
222 
223             case StringExtractorGDBRemote::eServerPacketType_vFile_exists:
224                 return Handle_vFile_Exists (packet);
225 
226             case StringExtractorGDBRemote::eServerPacketType_vFile_stat:
227                 return Handle_vFile_Stat (packet);
228 
229             case StringExtractorGDBRemote::eServerPacketType_vFile_md5:
230                 return Handle_vFile_MD5 (packet);
231 
232             case StringExtractorGDBRemote::eServerPacketType_vFile_symlink:
233                 return Handle_vFile_symlink (packet);
234 
235             case StringExtractorGDBRemote::eServerPacketType_vFile_unlink:
236                 return Handle_vFile_unlink (packet);
237         }
238         return true;
239     }
240     else
241     {
242         if (!IsConnected())
243             error.SetErrorString("lost connection");
244         else
245             error.SetErrorString("timeout");
246     }
247 
248     return false;
249 }
250 
251 size_t
252 GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
253 {
254     // TODO: Log the packet we aren't handling...
255     return SendPacketNoLock ("", 0);
256 }
257 
258 size_t
259 GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
260 {
261     char packet[16];
262     int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
263     assert (packet_len < (int)sizeof(packet));
264     return SendPacketNoLock (packet, packet_len);
265 }
266 
267 
268 size_t
269 GDBRemoteCommunicationServer::SendOKResponse ()
270 {
271     return SendPacketNoLock ("OK", 2);
272 }
273 
274 bool
275 GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
276 {
277     return GetAck();
278 }
279 
280 bool
281 GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
282 {
283     StreamString response;
284 
285     // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
286 
287     ArchSpec host_arch (Host::GetArchitecture ());
288     const llvm::Triple &host_triple = host_arch.GetTriple();
289     response.PutCString("triple:");
290     response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
291     response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
292 
293     uint32_t cpu = host_arch.GetMachOCPUType();
294     uint32_t sub = host_arch.GetMachOCPUSubType();
295     if (cpu != LLDB_INVALID_CPUTYPE)
296         response.Printf ("cputype:%u;", cpu);
297     if (sub != LLDB_INVALID_CPUTYPE)
298         response.Printf ("cpusubtype:%u;", sub);
299 
300     if (cpu == ArchSpec::kCore_arm_any)
301         response.Printf("watchpoint_exceptions_received:before;");   // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
302     else
303         response.Printf("watchpoint_exceptions_received:after;");
304 
305     switch (lldb::endian::InlHostByteOrder())
306     {
307     case eByteOrderBig:     response.PutCString ("endian:big;"); break;
308     case eByteOrderLittle:  response.PutCString ("endian:little;"); break;
309     case eByteOrderPDP:     response.PutCString ("endian:pdp;"); break;
310     default:                response.PutCString ("endian:unknown;"); break;
311     }
312 
313     uint32_t major = UINT32_MAX;
314     uint32_t minor = UINT32_MAX;
315     uint32_t update = UINT32_MAX;
316     if (Host::GetOSVersion (major, minor, update))
317     {
318         if (major != UINT32_MAX)
319         {
320             response.Printf("os_version:%u", major);
321             if (minor != UINT32_MAX)
322             {
323                 response.Printf(".%u", minor);
324                 if (update != UINT32_MAX)
325                     response.Printf(".%u", update);
326             }
327             response.PutChar(';');
328         }
329     }
330 
331     std::string s;
332     if (Host::GetOSBuildString (s))
333     {
334         response.PutCString ("os_build:");
335         response.PutCStringAsRawHex8(s.c_str());
336         response.PutChar(';');
337     }
338     if (Host::GetOSKernelDescription (s))
339     {
340         response.PutCString ("os_kernel:");
341         response.PutCStringAsRawHex8(s.c_str());
342         response.PutChar(';');
343     }
344     if (Host::GetHostname (s))
345     {
346         response.PutCString ("hostname:");
347         response.PutCStringAsRawHex8(s.c_str());
348         response.PutChar(';');
349     }
350 
351     return SendPacketNoLock (response.GetData(), response.GetSize()) > 0;
352 }
353 
354 static void
355 CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
356 {
357     response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
358                      proc_info.GetProcessID(),
359                      proc_info.GetParentProcessID(),
360                      proc_info.GetUserID(),
361                      proc_info.GetGroupID(),
362                      proc_info.GetEffectiveUserID(),
363                      proc_info.GetEffectiveGroupID());
364     response.PutCString ("name:");
365     response.PutCStringAsRawHex8(proc_info.GetName());
366     response.PutChar(';');
367     const ArchSpec &proc_arch = proc_info.GetArchitecture();
368     if (proc_arch.IsValid())
369     {
370         const llvm::Triple &proc_triple = proc_arch.GetTriple();
371         response.PutCString("triple:");
372         response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
373         response.PutChar(';');
374     }
375 }
376 
377 bool
378 GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
379 {
380     // Packet format: "qProcessInfoPID:%i" where %i is the pid
381     packet.SetFilePos(::strlen ("qProcessInfoPID:"));
382     lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
383     if (pid != LLDB_INVALID_PROCESS_ID)
384     {
385         ProcessInstanceInfo proc_info;
386         if (Host::GetProcessInfo(pid, proc_info))
387         {
388             StreamString response;
389             CreateProcessInfoResponse (proc_info, response);
390             return SendPacketNoLock (response.GetData(), response.GetSize());
391         }
392     }
393     return SendErrorResponse (1);
394 }
395 
396 bool
397 GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
398 {
399     m_proc_infos_index = 0;
400     m_proc_infos.Clear();
401 
402     ProcessInstanceInfoMatch match_info;
403     packet.SetFilePos(::strlen ("qfProcessInfo"));
404     if (packet.GetChar() == ':')
405     {
406 
407         std::string key;
408         std::string value;
409         while (packet.GetNameColonValue(key, value))
410         {
411             bool success = true;
412             if (key.compare("name") == 0)
413             {
414                 StringExtractor extractor;
415                 extractor.GetStringRef().swap(value);
416                 extractor.GetHexByteString (value);
417                 match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
418             }
419             else if (key.compare("name_match") == 0)
420             {
421                 if (value.compare("equals") == 0)
422                 {
423                     match_info.SetNameMatchType (eNameMatchEquals);
424                 }
425                 else if (value.compare("starts_with") == 0)
426                 {
427                     match_info.SetNameMatchType (eNameMatchStartsWith);
428                 }
429                 else if (value.compare("ends_with") == 0)
430                 {
431                     match_info.SetNameMatchType (eNameMatchEndsWith);
432                 }
433                 else if (value.compare("contains") == 0)
434                 {
435                     match_info.SetNameMatchType (eNameMatchContains);
436                 }
437                 else if (value.compare("regex") == 0)
438                 {
439                     match_info.SetNameMatchType (eNameMatchRegularExpression);
440                 }
441                 else
442                 {
443                     success = false;
444                 }
445             }
446             else if (key.compare("pid") == 0)
447             {
448                 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
449             }
450             else if (key.compare("parent_pid") == 0)
451             {
452                 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
453             }
454             else if (key.compare("uid") == 0)
455             {
456                 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
457             }
458             else if (key.compare("gid") == 0)
459             {
460                 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
461             }
462             else if (key.compare("euid") == 0)
463             {
464                 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
465             }
466             else if (key.compare("egid") == 0)
467             {
468                 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
469             }
470             else if (key.compare("all_users") == 0)
471             {
472                 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
473             }
474             else if (key.compare("triple") == 0)
475             {
476                 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
477             }
478             else
479             {
480                 success = false;
481             }
482 
483             if (!success)
484                 return SendErrorResponse (2);
485         }
486     }
487 
488     if (Host::FindProcesses (match_info, m_proc_infos))
489     {
490         // We found something, return the first item by calling the get
491         // subsequent process info packet handler...
492         return Handle_qsProcessInfo (packet);
493     }
494     return SendErrorResponse (3);
495 }
496 
497 bool
498 GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
499 {
500     if (m_proc_infos_index < m_proc_infos.GetSize())
501     {
502         StreamString response;
503         CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
504         ++m_proc_infos_index;
505         return SendPacketNoLock (response.GetData(), response.GetSize());
506     }
507     return SendErrorResponse (4);
508 }
509 
510 bool
511 GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
512 {
513     // Packet format: "qUserName:%i" where %i is the uid
514     packet.SetFilePos(::strlen ("qUserName:"));
515     uint32_t uid = packet.GetU32 (UINT32_MAX);
516     if (uid != UINT32_MAX)
517     {
518         std::string name;
519         if (Host::GetUserName (uid, name))
520         {
521             StreamString response;
522             response.PutCStringAsRawHex8 (name.c_str());
523             return SendPacketNoLock (response.GetData(), response.GetSize());
524         }
525     }
526     return SendErrorResponse (5);
527 
528 }
529 
530 bool
531 GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
532 {
533     // Packet format: "qGroupName:%i" where %i is the gid
534     packet.SetFilePos(::strlen ("qGroupName:"));
535     uint32_t gid = packet.GetU32 (UINT32_MAX);
536     if (gid != UINT32_MAX)
537     {
538         std::string name;
539         if (Host::GetGroupName (gid, name))
540         {
541             StreamString response;
542             response.PutCStringAsRawHex8 (name.c_str());
543             return SendPacketNoLock (response.GetData(), response.GetSize());
544         }
545     }
546     return SendErrorResponse (6);
547 }
548 
549 bool
550 GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
551 {
552     packet.SetFilePos(::strlen ("qSpeedTest:"));
553 
554     std::string key;
555     std::string value;
556     bool success = packet.GetNameColonValue(key, value);
557     if (success && key.compare("response_size") == 0)
558     {
559         uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
560         if (success)
561         {
562             if (response_size == 0)
563                 return SendOKResponse();
564             StreamString response;
565             uint32_t bytes_left = response_size;
566             response.PutCString("data:");
567             while (bytes_left > 0)
568             {
569                 if (bytes_left >= 26)
570                 {
571                     response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
572                     bytes_left -= 26;
573                 }
574                 else
575                 {
576                     response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
577                     bytes_left = 0;
578                 }
579             }
580             return SendPacketNoLock (response.GetData(), response.GetSize());
581         }
582     }
583     return SendErrorResponse (7);
584 }
585 
586 
587 static void *
588 AcceptPortFromInferior (void *arg)
589 {
590     const char *connect_url = (const char *)arg;
591     ConnectionFileDescriptor file_conn;
592     Error error;
593     if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
594     {
595         char pid_str[256];
596         ::memset (pid_str, 0, sizeof(pid_str));
597         ConnectionStatus status;
598         const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL);
599         if (pid_str_len > 0)
600         {
601             int pid = atoi (pid_str);
602             return (void *)(intptr_t)pid;
603         }
604     }
605     return NULL;
606 }
607 //
608 //static bool
609 //WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
610 //{
611 //    const int time_delta_usecs = 100000;
612 //    const int num_retries = timeout_in_seconds/time_delta_usecs;
613 //    for (int i=0; i<num_retries; i++)
614 //    {
615 //        struct proc_bsdinfo bsd_info;
616 //        int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
617 //                                    (uint64_t) 0,
618 //                                    &bsd_info,
619 //                                    PROC_PIDTBSDINFO_SIZE);
620 //
621 //        switch (error)
622 //        {
623 //            case EINVAL:
624 //            case ENOTSUP:
625 //            case ESRCH:
626 //            case EPERM:
627 //                return false;
628 //
629 //            default:
630 //                break;
631 //
632 //            case 0:
633 //                if (bsd_info.pbi_status == SSTOP)
634 //                    return true;
635 //        }
636 //        ::usleep (time_delta_usecs);
637 //    }
638 //    return false;
639 //}
640 
641 bool
642 GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
643 {
644     // The 'A' packet is the most over designed packet ever here with
645     // redundant argument indexes, redundant argument lengths and needed hex
646     // encoded argument string values. Really all that is needed is a comma
647     // separated hex encoded argument value list, but we will stay true to the
648     // documented version of the 'A' packet here...
649 
650     packet.SetFilePos(1); // Skip the 'A'
651     bool success = true;
652     while (success && packet.GetBytesLeft() > 0)
653     {
654         // Decode the decimal argument string length. This length is the
655         // number of hex nibbles in the argument string value.
656         const uint32_t arg_len = packet.GetU32(UINT32_MAX);
657         if (arg_len == UINT32_MAX)
658             success = false;
659         else
660         {
661             // Make sure the argument hex string length is followed by a comma
662             if (packet.GetChar() != ',')
663                 success = false;
664             else
665             {
666                 // Decode the argument index. We ignore this really becuase
667                 // who would really send down the arguments in a random order???
668                 const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
669                 if (arg_idx == UINT32_MAX)
670                     success = false;
671                 else
672                 {
673                     // Make sure the argument index is followed by a comma
674                     if (packet.GetChar() != ',')
675                         success = false;
676                     else
677                     {
678                         // Decode the argument string value from hex bytes
679                         // back into a UTF8 string and make sure the length
680                         // matches the one supplied in the packet
681                         std::string arg;
682                         if (packet.GetHexByteString(arg) != (arg_len / 2))
683                             success = false;
684                         else
685                         {
686                             // If there are any bytes lft
687                             if (packet.GetBytesLeft())
688                             {
689                                 if (packet.GetChar() != ',')
690                                     success = false;
691                             }
692 
693                             if (success)
694                             {
695                                 if (arg_idx == 0)
696                                     m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
697                                 m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
698                             }
699                         }
700                     }
701                 }
702             }
703         }
704     }
705 
706     if (success)
707     {
708         m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
709         m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
710         if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
711         {
712             return SendOKResponse ();
713         }
714     }
715     return SendErrorResponse (8);
716 }
717 
718 bool
719 GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
720 {
721     lldb::pid_t pid = m_process_launch_info.GetProcessID();
722     StreamString response;
723     response.Printf("QC%" PRIx64, pid);
724     if (m_is_platform)
725     {
726         // If we launch a process and this GDB server is acting as a platform,
727         // then we need to clear the process launch state so we can start
728         // launching another process. In order to launch a process a bunch or
729         // packets need to be sent: environment packets, working directory,
730         // disable ASLR, and many more settings. When we launch a process we
731         // then need to know when to clear this information. Currently we are
732         // selecting the 'qC' packet as that packet which seems to make the most
733         // sense.
734         if (pid != LLDB_INVALID_PROCESS_ID)
735         {
736             m_process_launch_info.Clear();
737         }
738     }
739     return SendPacketNoLock (response.GetData(), response.GetSize());
740 }
741 
742 bool
743 GDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid)
744 {
745     Mutex::Locker locker (m_spawned_pids_mutex);
746     return m_spawned_pids.erase(pid) > 0;
747 }
748 bool
749 GDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton,
750                                                       lldb::pid_t pid,
751                                                       bool exited,
752                                                       int signal,    // Zero for no signal
753                                                       int status)    // Exit value of process if signal is zero
754 {
755     GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
756     server->DebugserverProcessReaped (pid);
757     return true;
758 }
759 
760 bool
761 GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
762 {
763 #ifdef _WIN32
764     // No unix sockets on windows
765     return false;
766 #else
767     // Spawn a local debugserver as a platform so we can then attach or launch
768     // a process...
769 
770     if (m_is_platform)
771     {
772         // Sleep and wait a bit for debugserver to start to listen...
773         ConnectionFileDescriptor file_conn;
774         char connect_url[PATH_MAX];
775         Error error;
776         std::string hostname;
777         // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
778         // with the TMPDIR environnement variable
779         char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
780         if (::mkstemp (unix_socket_name) == -1)
781         {
782             error.SetErrorStringWithFormat("failed to make temporary path for a unix socket: %s", strerror(errno));
783         }
784         else
785         {
786             packet.SetFilePos(::strlen ("qLaunchGDBServer:"));
787             std::string name;
788             std::string value;
789             uint16_t port = UINT16_MAX;
790             while (packet.GetNameColonValue(name, value))
791             {
792                 if (name.compare ("host") == 0)
793                     hostname.swap(value);
794                 else if (name.compare ("port") == 0)
795                     port = Args::StringToUInt32(value.c_str(), 0, 0);
796             }
797             if (port == UINT16_MAX)
798                 port = GetAndUpdateNextPort();
799 
800             ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
801             // Spawn a new thread to accept the port that gets bound after
802             // binding to port 0 (zero).
803             lldb::thread_t accept_thread = LLDB_INVALID_HOST_THREAD;
804 
805             if (port == 0)
806             {
807                 accept_thread = Host::ThreadCreate (unix_socket_name,
808                                                     AcceptPortFromInferior,
809                                                     connect_url,
810                                                     &error);
811             }
812 
813             if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
814             {
815                 // Spawn a debugserver and try to get the port it listens to.
816                 ProcessLaunchInfo debugserver_launch_info;
817                 StreamString host_and_port;
818                 if (hostname.empty())
819                     hostname = "localhost";
820                 host_and_port.Printf("%s:%u", hostname.c_str(), port);
821                 const char *host_and_port_cstr = host_and_port.GetString().c_str();
822                 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
823                 if (log)
824                     log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr);
825 
826                 debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
827 
828                 error = StartDebugserverProcess (host_and_port_cstr,
829                                                  unix_socket_name,
830                                                  debugserver_launch_info);
831 
832                 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
833 
834 
835                 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
836                 {
837                     Mutex::Locker locker (m_spawned_pids_mutex);
838                     m_spawned_pids.insert(debugserver_pid);
839                 }
840 
841                 if (error.Success())
842                 {
843                     bool success = false;
844 
845                     if (accept_thread)
846                     {
847                         thread_result_t accept_thread_result = NULL;
848                         if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
849                         {
850                             if (accept_thread_result)
851                             {
852                                 port = (intptr_t)accept_thread_result;
853                                 char response[256];
854                                 const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
855                                 assert (response_len < sizeof(response));
856                                 //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
857                                 success = SendPacketNoLock (response, response_len) > 0;
858                             }
859                         }
860                     }
861                     else
862                     {
863                         char response[256];
864                         const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
865                         assert (response_len < sizeof(response));
866                         //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
867                         success = SendPacketNoLock (response, response_len) > 0;
868 
869                     }
870                     ::unlink (unix_socket_name);
871 
872                     if (!success)
873                     {
874                         if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
875                             ::kill (debugserver_pid, SIGINT);
876                     }
877                     return success;
878                 }
879             }
880         }
881     }
882     return SendErrorResponse (9);
883 #endif
884 }
885 
886 bool
887 GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
888 {
889     // Spawn a local debugserver as a platform so we can then attach or launch
890     // a process...
891 
892     if (m_is_platform)
893     {
894         packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
895 
896         lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
897 
898         // Scope for locker
899         {
900             Mutex::Locker locker (m_spawned_pids_mutex);
901             if (m_spawned_pids.find(pid) == m_spawned_pids.end())
902                 return SendErrorResponse (10);
903         }
904         Host::Kill (pid, SIGTERM);
905 
906         for (size_t i=0; i<10; ++i)
907         {
908             // Scope for locker
909             {
910                 Mutex::Locker locker (m_spawned_pids_mutex);
911                 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
912                     return true;
913             }
914             usleep (10000);
915         }
916 
917         // Scope for locker
918         {
919             Mutex::Locker locker (m_spawned_pids_mutex);
920             if (m_spawned_pids.find(pid) == m_spawned_pids.end())
921                 return true;
922         }
923         Host::Kill (pid, SIGKILL);
924 
925         for (size_t i=0; i<10; ++i)
926         {
927             // Scope for locker
928             {
929                 Mutex::Locker locker (m_spawned_pids_mutex);
930                 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
931                     return true;
932             }
933             usleep (10000);
934         }
935     }
936     return SendErrorResponse (10);
937 }
938 
939 bool
940 GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
941 {
942     if (m_process_launch_error.Success())
943         return SendOKResponse();
944     StreamString response;
945     response.PutChar('E');
946     response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
947     return SendPacketNoLock (response.GetData(), response.GetSize());
948 }
949 
950 bool
951 GDBRemoteCommunicationServer::Handle_QEnvironment  (StringExtractorGDBRemote &packet)
952 {
953     packet.SetFilePos(::strlen ("QEnvironment:"));
954     const uint32_t bytes_left = packet.GetBytesLeft();
955     if (bytes_left > 0)
956     {
957         m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
958         return SendOKResponse ();
959     }
960     return SendErrorResponse (11);
961 }
962 
963 bool
964 GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
965 {
966     packet.SetFilePos(::strlen ("QLaunchArch:"));
967     const uint32_t bytes_left = packet.GetBytesLeft();
968     if (bytes_left > 0)
969     {
970         const char* arch_triple = packet.Peek();
971         ArchSpec arch_spec(arch_triple,NULL);
972         m_process_launch_info.SetArchitecture(arch_spec);
973         return SendOKResponse();
974     }
975     return SendErrorResponse(12);
976 }
977 
978 bool
979 GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
980 {
981     packet.SetFilePos(::strlen ("QSetDisableASLR:"));
982     if (packet.GetU32(0))
983         m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
984     else
985         m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
986     return SendOKResponse ();
987 }
988 
989 bool
990 GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
991 {
992     packet.SetFilePos(::strlen ("QSetWorkingDir:"));
993     std::string path;
994     packet.GetHexByteString(path);
995     if (m_is_platform)
996     {
997         // If this packet is sent to a platform, then change the current working directory
998         if (::chdir(path.c_str()) != 0)
999             return SendErrorResponse(errno);
1000     }
1001     else
1002     {
1003         m_process_launch_info.SwapWorkingDirectory (path);
1004     }
1005     return SendOKResponse ();
1006 }
1007 
1008 bool
1009 GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
1010 {
1011     StreamString response;
1012 
1013     if (m_is_platform)
1014     {
1015         // If this packet is sent to a platform, then change the current working directory
1016         char cwd[PATH_MAX];
1017         if (getcwd(cwd, sizeof(cwd)) == NULL)
1018         {
1019             return SendErrorResponse(errno);
1020         }
1021         else
1022         {
1023             response.PutBytesAsRawHex8(cwd, strlen(cwd));
1024             SendPacketNoLock(response.GetData(), response.GetSize());
1025             return true;
1026         }
1027     }
1028     else
1029     {
1030         const char *working_dir = m_process_launch_info.GetWorkingDirectory();
1031         if (working_dir && working_dir[0])
1032         {
1033             response.PutBytesAsRawHex8(working_dir, strlen(working_dir));
1034             SendPacketNoLock(response.GetData(), response.GetSize());
1035             return true;
1036         }
1037         else
1038         {
1039             return SendErrorResponse(1);
1040         }
1041     }
1042 }
1043 
1044 bool
1045 GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
1046 {
1047     packet.SetFilePos(::strlen ("QSetSTDIN:"));
1048     ProcessLaunchInfo::FileAction file_action;
1049     std::string path;
1050     packet.GetHexByteString(path);
1051     const bool read = false;
1052     const bool write = true;
1053     if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
1054     {
1055         m_process_launch_info.AppendFileAction(file_action);
1056         return SendOKResponse ();
1057     }
1058     return SendErrorResponse (13);
1059 }
1060 
1061 bool
1062 GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
1063 {
1064     packet.SetFilePos(::strlen ("QSetSTDOUT:"));
1065     ProcessLaunchInfo::FileAction file_action;
1066     std::string path;
1067     packet.GetHexByteString(path);
1068     const bool read = true;
1069     const bool write = false;
1070     if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
1071     {
1072         m_process_launch_info.AppendFileAction(file_action);
1073         return SendOKResponse ();
1074     }
1075     return SendErrorResponse (14);
1076 }
1077 
1078 bool
1079 GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
1080 {
1081     packet.SetFilePos(::strlen ("QSetSTDERR:"));
1082     ProcessLaunchInfo::FileAction file_action;
1083     std::string path;
1084     packet.GetHexByteString(path);
1085     const bool read = true;
1086     const bool write = false;
1087     if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
1088     {
1089         m_process_launch_info.AppendFileAction(file_action);
1090         return SendOKResponse ();
1091     }
1092     return SendErrorResponse (15);
1093 }
1094 
1095 bool
1096 GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
1097 {
1098     // Send response first before changing m_send_acks to we ack this packet
1099     SendOKResponse ();
1100     m_send_acks = false;
1101     return true;
1102 }
1103 
1104 bool
1105 GDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet)
1106 {
1107     packet.SetFilePos(::strlen("qPlatform_mkdir:"));
1108     mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
1109     if (packet.GetChar() != ',')
1110         return false;
1111     std::string path;
1112     packet.GetHexByteString(path);
1113     Error error = Host::MakeDirectory(path.c_str(),mode);
1114     if (error.Success())
1115         return SendPacketNoLock ("OK", 2);
1116     else
1117         return SendErrorResponse(error.GetError());
1118     return true;
1119 }
1120 
1121 bool
1122 GDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet)
1123 {
1124     packet.SetFilePos(::strlen("qPlatform_chmod:"));
1125 
1126     mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
1127     if (packet.GetChar() != ',')
1128         return false;
1129     std::string path;
1130     packet.GetHexByteString(path);
1131     Error error = Host::SetFilePermissions (path.c_str(), mode);
1132     if (error.Success())
1133         return SendPacketNoLock ("OK", 2);
1134     else
1135         return SendErrorResponse(error.GetError());
1136     return true;
1137 }
1138 
1139 bool
1140 GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet)
1141 {
1142     packet.SetFilePos(::strlen("vFile:open:"));
1143     std::string path;
1144     packet.GetHexByteStringTerminatedBy(path,',');
1145     if (path.size() == 0)
1146         return false;
1147     if (packet.GetChar() != ',')
1148         return false;
1149     uint32_t flags = packet.GetHexMaxU32(false, UINT32_MAX);
1150     if (packet.GetChar() != ',')
1151         return false;
1152     mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
1153     Error error;
1154     int fd = ::open (path.c_str(), flags, mode);
1155     const int save_errno = fd == -1 ? errno : 0;
1156     StreamString response;
1157     response.PutChar('F');
1158     response.Printf("%i", fd);
1159     if (save_errno)
1160         response.Printf(",%i", save_errno);
1161     SendPacketNoLock(response.GetData(), response.GetSize());
1162     return true;
1163 }
1164 
1165 bool
1166 GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)
1167 {
1168     packet.SetFilePos(::strlen("vFile:close:"));
1169     int fd = packet.GetS32(-1);
1170     Error error;
1171     int err = -1;
1172     int save_errno = 0;
1173     if (fd >= 0)
1174     {
1175         err = close(fd);
1176         save_errno = err == -1 ? errno : 0;
1177     }
1178     else
1179     {
1180         save_errno = EINVAL;
1181     }
1182     StreamString response;
1183     response.PutChar('F');
1184     response.Printf("%i", err);
1185     if (save_errno)
1186         response.Printf(",%i", save_errno);
1187     SendPacketNoLock(response.GetData(), response.GetSize());
1188     return true;
1189 }
1190 
1191 bool
1192 GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet)
1193 {
1194 #ifdef _WIN32
1195     // Not implemented on Windows
1196     return false;
1197 #else
1198     StreamGDBRemote response;
1199     packet.SetFilePos(::strlen("vFile:pread:"));
1200     int fd = packet.GetS32(-1);
1201     if (packet.GetChar() != ',')
1202         return false;
1203     uint64_t count = packet.GetU64(UINT64_MAX);
1204     if (packet.GetChar() != ',')
1205         return false;
1206     uint64_t offset = packet.GetU64(UINT32_MAX);
1207     if (count == UINT64_MAX)
1208     {
1209         response.Printf("F-1:%i", EINVAL);
1210         SendPacketNoLock(response.GetData(), response.GetSize());
1211         return true;
1212     }
1213     std::string buffer(count, 0);
1214     const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
1215     const int save_errno = bytes_read == -1 ? errno : 0;
1216     response.PutChar('F');
1217     response.Printf("%zi", bytes_read);
1218     if (save_errno)
1219         response.Printf(",%i", save_errno);
1220     else
1221     {
1222         response.PutChar(';');
1223         response.PutEscapedBytes(&buffer[0], bytes_read);
1224     }
1225     SendPacketNoLock(response.GetData(), response.GetSize());
1226     return true;
1227 #endif
1228 }
1229 
1230 bool
1231 GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
1232 {
1233 #ifdef _WIN32
1234     // Not implemented on Windows
1235     return false;
1236 #else
1237     packet.SetFilePos(::strlen("vFile:pwrite:"));
1238 
1239     StreamGDBRemote response;
1240     response.PutChar('F');
1241 
1242     int fd = packet.GetU32(UINT32_MAX);
1243     if (packet.GetChar() != ',')
1244         return false;
1245     off_t offset = packet.GetU64(UINT32_MAX);
1246     if (packet.GetChar() != ',')
1247         return false;
1248     std::string buffer;
1249     if (packet.GetEscapedBinaryData(buffer))
1250     {
1251         const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
1252         const int save_errno = bytes_written == -1 ? errno : 0;
1253         response.Printf("%zi", bytes_written);
1254         if (save_errno)
1255             response.Printf(",%i", save_errno);
1256     }
1257     else
1258     {
1259         response.Printf ("-1,%i", EINVAL);
1260     }
1261 
1262     SendPacketNoLock(response.GetData(), response.GetSize());
1263     return true;
1264 #endif
1265 }
1266 
1267 bool
1268 GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet)
1269 {
1270     packet.SetFilePos(::strlen("vFile:size:"));
1271     std::string path;
1272     packet.GetHexByteString(path);
1273     if (path.empty())
1274         return false;
1275     lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
1276     StreamString response;
1277     response.PutChar('F');
1278     response.PutHex64(retcode);
1279     if (retcode == UINT64_MAX)
1280     {
1281         response.PutChar(',');
1282         response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
1283     }
1284     SendPacketNoLock(response.GetData(), response.GetSize());
1285     return true;
1286 }
1287 
1288 bool
1289 GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
1290 {
1291     packet.SetFilePos(::strlen("vFile:mode:"));
1292     std::string path;
1293     packet.GetHexByteString(path);
1294     if (path.empty())
1295         return false;
1296     Error error;
1297     const uint32_t mode = File::GetPermissions(path.c_str(), error);
1298     StreamString response;
1299     response.Printf("F%u", mode);
1300     if (mode == 0 || error.Fail())
1301         response.Printf(",%i", (int)error.GetError());
1302     SendPacketNoLock(response.GetData(), response.GetSize());
1303     return true;
1304 }
1305 
1306 bool
1307 GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
1308 {
1309     packet.SetFilePos(::strlen("vFile:exists:"));
1310     std::string path;
1311     packet.GetHexByteString(path);
1312     if (path.empty())
1313         return false;
1314     bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
1315     StreamString response;
1316     response.PutChar('F');
1317     response.PutChar(',');
1318     if (retcode)
1319         response.PutChar('1');
1320     else
1321         response.PutChar('0');
1322     SendPacketNoLock(response.GetData(), response.GetSize());
1323     return true;
1324 }
1325 
1326 bool
1327 GDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &packet)
1328 {
1329     packet.SetFilePos(::strlen("vFile:symlink:"));
1330     std::string dst, src;
1331     packet.GetHexByteStringTerminatedBy(dst, ',');
1332     packet.GetChar(); // Skip ',' char
1333     packet.GetHexByteString(src);
1334     Error error = Host::Symlink(src.c_str(), dst.c_str());
1335     StreamString response;
1336     response.Printf("F%u,%u", error.GetError(), error.GetError());
1337     SendPacketNoLock(response.GetData(), response.GetSize());
1338     return true;
1339 }
1340 
1341 bool
1342 GDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &packet)
1343 {
1344     packet.SetFilePos(::strlen("vFile:unlink:"));
1345     std::string path;
1346     packet.GetHexByteString(path);
1347     Error error = Host::Unlink(path.c_str());
1348     StreamString response;
1349     response.Printf("F%u,%u", error.GetError(), error.GetError());
1350     SendPacketNoLock(response.GetData(), response.GetSize());
1351     return true;
1352 }
1353 
1354 bool
1355 GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &packet)
1356 {
1357     packet.SetFilePos(::strlen("qPlatform_shell:"));
1358     std::string path;
1359     std::string working_dir;
1360     packet.GetHexByteStringTerminatedBy(path,',');
1361     if (path.size() == 0)
1362         return false;
1363     if (packet.GetChar() != ',')
1364         return false;
1365     // FIXME: add timeout to qPlatform_shell packet
1366     // uint32_t timeout = packet.GetHexMaxU32(false, 32);
1367     uint32_t timeout = 10;
1368     if (packet.GetChar() == ',')
1369         packet.GetHexByteString(working_dir);
1370     int status, signo;
1371     std::string output;
1372     Error err = Host::RunShellCommand(path.c_str(),
1373                                       working_dir.empty() ? NULL : working_dir.c_str(),
1374                                       &status, &signo, &output, timeout);
1375     StreamGDBRemote response;
1376     if (err.Fail())
1377     {
1378         response.PutCString("F,");
1379         response.PutHex32(UINT32_MAX);
1380     }
1381     else
1382     {
1383         response.PutCString("F,");
1384         response.PutHex32(status);
1385         response.PutChar(',');
1386         response.PutHex32(signo);
1387         response.PutChar(',');
1388         response.PutEscapedBytes(output.c_str(), output.size());
1389     }
1390     SendPacketNoLock(response.GetData(), response.GetSize());
1391     return true;
1392 }
1393 
1394 bool
1395 GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
1396 {
1397     return false;
1398 }
1399 
1400 bool
1401 GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
1402 {
1403     packet.SetFilePos(::strlen("vFile:exists:"));
1404     std::string path;
1405     packet.GetHexByteString(path);
1406     if (path.size() == 0)
1407         return false;
1408     uint64_t a,b;
1409     StreamGDBRemote response;
1410     if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false)
1411     {
1412         response.PutCString("F,");
1413         response.PutCString("x");
1414     }
1415     else
1416     {
1417         response.PutCString("F,");
1418         response.PutHex64(a);
1419         response.PutHex64(b);
1420     }
1421     SendPacketNoLock(response.GetData(), response.GetSize());
1422     return true;
1423 }
1424