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