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