• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 #include "GDBRemoteCommunicationServer.h"
12 
13 // C Includes
14 // C++ Includes
15 // Other libraries and framework includes
16 #include "llvm/ADT/Triple.h"
17 #include "lldb/Interpreter/Args.h"
18 #include "lldb/Core/ConnectionFileDescriptor.h"
19 #include "lldb/Core/Log.h"
20 #include "lldb/Core/State.h"
21 #include "lldb/Core/StreamString.h"
22 #include "lldb/Host/Endian.h"
23 #include "lldb/Host/Host.h"
24 #include "lldb/Host/TimeValue.h"
25 #include "lldb/Target/Process.h"
26 
27 // Project includes
28 #include "Utility/StringExtractorGDBRemote.h"
29 #include "ProcessGDBRemote.h"
30 #include "ProcessGDBRemoteLog.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 //----------------------------------------------------------------------
36 // GDBRemoteCommunicationServer constructor
37 //----------------------------------------------------------------------
GDBRemoteCommunicationServer(bool is_platform)38 GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
39     GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
40     m_async_thread (LLDB_INVALID_HOST_THREAD),
41     m_process_launch_info (),
42     m_process_launch_error (),
43     m_proc_infos (),
44     m_proc_infos_index (0),
45     m_lo_port_num (0),
46     m_hi_port_num (0)
47 {
48 }
49 
50 //----------------------------------------------------------------------
51 // Destructor
52 //----------------------------------------------------------------------
~GDBRemoteCommunicationServer()53 GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
54 {
55 }
56 
57 
58 //void *
59 //GDBRemoteCommunicationServer::AsyncThread (void *arg)
60 //{
61 //    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
62 //
63 //    Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
64 //    if (log)
65 //        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
66 //
67 //    StringExtractorGDBRemote packet;
68 //
69 //    while ()
70 //    {
71 //        if (packet.
72 //    }
73 //
74 //    if (log)
75 //        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
76 //
77 //    process->m_async_thread = LLDB_INVALID_HOST_THREAD;
78 //    return NULL;
79 //}
80 //
81 bool
GetPacketAndSendResponse(uint32_t timeout_usec,Error & error,bool & interrupt,bool & quit)82 GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
83                                                         Error &error,
84                                                         bool &interrupt,
85                                                         bool &quit)
86 {
87     StringExtractorGDBRemote packet;
88     if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec))
89     {
90         const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
91         switch (packet_type)
92         {
93             case StringExtractorGDBRemote::eServerPacketType_nack:
94             case StringExtractorGDBRemote::eServerPacketType_ack:
95                 break;
96 
97             case StringExtractorGDBRemote::eServerPacketType_invalid:
98                 error.SetErrorString("invalid packet");
99                 quit = true;
100                 break;
101 
102             case StringExtractorGDBRemote::eServerPacketType_interrupt:
103                 error.SetErrorString("interrupt received");
104                 interrupt = true;
105                 break;
106 
107             case StringExtractorGDBRemote::eServerPacketType_unimplemented:
108                 return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
109 
110             case StringExtractorGDBRemote::eServerPacketType_A:
111                 return Handle_A (packet);
112 
113             case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
114                 return Handle_qfProcessInfo (packet);
115 
116             case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
117                 return Handle_qsProcessInfo (packet);
118 
119             case StringExtractorGDBRemote::eServerPacketType_qC:
120                 return Handle_qC (packet);
121 
122             case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
123                 return Handle_qHostInfo (packet);
124 
125             case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
126                 return Handle_qLaunchGDBServer (packet);
127 
128             case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
129                 return Handle_qLaunchSuccess (packet);
130 
131             case StringExtractorGDBRemote::eServerPacketType_qGroupName:
132                 return Handle_qGroupName (packet);
133 
134             case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
135                 return Handle_qProcessInfoPID (packet);
136 
137             case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
138                 return Handle_qSpeedTest (packet);
139 
140             case StringExtractorGDBRemote::eServerPacketType_qUserName:
141                 return Handle_qUserName (packet);
142 
143             case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
144                 return Handle_QEnvironment (packet);
145 
146             case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
147                 return Handle_QSetDisableASLR (packet);
148 
149             case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
150                 return Handle_QSetSTDIN (packet);
151 
152             case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
153                 return Handle_QSetSTDOUT (packet);
154 
155             case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
156                 return Handle_QSetSTDERR (packet);
157 
158             case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
159                 return Handle_QSetWorkingDir (packet);
160 
161             case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
162                 return Handle_QStartNoAckMode (packet);
163         }
164         return true;
165     }
166     else
167     {
168         if (!IsConnected())
169             error.SetErrorString("lost connection");
170         else
171             error.SetErrorString("timeout");
172     }
173 
174     return false;
175 }
176 
177 size_t
SendUnimplementedResponse(const char *)178 GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
179 {
180     // TODO: Log the packet we aren't handling...
181     return SendPacketNoLock ("", 0);
182 }
183 
184 size_t
SendErrorResponse(uint8_t err)185 GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
186 {
187     char packet[16];
188     int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
189     assert (packet_len < (int)sizeof(packet));
190     return SendPacketNoLock (packet, packet_len);
191 }
192 
193 
194 size_t
SendOKResponse()195 GDBRemoteCommunicationServer::SendOKResponse ()
196 {
197     return SendPacketNoLock ("OK", 2);
198 }
199 
200 bool
HandshakeWithClient(Error * error_ptr)201 GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
202 {
203     return GetAck();
204 }
205 
206 bool
Handle_qHostInfo(StringExtractorGDBRemote & packet)207 GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
208 {
209     StreamString response;
210 
211     // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
212 
213     ArchSpec host_arch (Host::GetArchitecture ());
214     const llvm::Triple &host_triple = host_arch.GetTriple();
215     response.PutCString("triple:");
216     response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
217     response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
218 
219     uint32_t cpu = host_arch.GetMachOCPUType();
220     uint32_t sub = host_arch.GetMachOCPUSubType();
221     if (cpu != LLDB_INVALID_CPUTYPE)
222         response.Printf ("cputype:%u;", cpu);
223     if (sub != LLDB_INVALID_CPUTYPE)
224         response.Printf ("cpusubtype:%u;", sub);
225 
226     if (cpu == ArchSpec::kCore_arm_any)
227         response.Printf("watchpoint_exceptions_received:before;");   // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
228     else
229         response.Printf("watchpoint_exceptions_received:after;");
230 
231     switch (lldb::endian::InlHostByteOrder())
232     {
233     case eByteOrderBig:     response.PutCString ("endian:big;"); break;
234     case eByteOrderLittle:  response.PutCString ("endian:little;"); break;
235     case eByteOrderPDP:     response.PutCString ("endian:pdp;"); break;
236     default:                response.PutCString ("endian:unknown;"); break;
237     }
238 
239     uint32_t major = UINT32_MAX;
240     uint32_t minor = UINT32_MAX;
241     uint32_t update = UINT32_MAX;
242     if (Host::GetOSVersion (major, minor, update))
243     {
244         if (major != UINT32_MAX)
245         {
246             response.Printf("os_version:%u", major);
247             if (minor != UINT32_MAX)
248             {
249                 response.Printf(".%u", minor);
250                 if (update != UINT32_MAX)
251                     response.Printf(".%u", update);
252             }
253             response.PutChar(';');
254         }
255     }
256 
257     std::string s;
258     if (Host::GetOSBuildString (s))
259     {
260         response.PutCString ("os_build:");
261         response.PutCStringAsRawHex8(s.c_str());
262         response.PutChar(';');
263     }
264     if (Host::GetOSKernelDescription (s))
265     {
266         response.PutCString ("os_kernel:");
267         response.PutCStringAsRawHex8(s.c_str());
268         response.PutChar(';');
269     }
270     if (Host::GetHostname (s))
271     {
272         response.PutCString ("hostname:");
273         response.PutCStringAsRawHex8(s.c_str());
274         response.PutChar(';');
275     }
276 
277     return SendPacketNoLock (response.GetData(), response.GetSize()) > 0;
278 }
279 
280 static void
CreateProcessInfoResponse(const ProcessInstanceInfo & proc_info,StreamString & response)281 CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
282 {
283     response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
284                      proc_info.GetProcessID(),
285                      proc_info.GetParentProcessID(),
286                      proc_info.GetUserID(),
287                      proc_info.GetGroupID(),
288                      proc_info.GetEffectiveUserID(),
289                      proc_info.GetEffectiveGroupID());
290     response.PutCString ("name:");
291     response.PutCStringAsRawHex8(proc_info.GetName());
292     response.PutChar(';');
293     const ArchSpec &proc_arch = proc_info.GetArchitecture();
294     if (proc_arch.IsValid())
295     {
296         const llvm::Triple &proc_triple = proc_arch.GetTriple();
297         response.PutCString("triple:");
298         response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
299         response.PutChar(';');
300     }
301 }
302 
303 bool
Handle_qProcessInfoPID(StringExtractorGDBRemote & packet)304 GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
305 {
306     // Packet format: "qProcessInfoPID:%i" where %i is the pid
307     packet.SetFilePos(::strlen ("qProcessInfoPID:"));
308     lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
309     if (pid != LLDB_INVALID_PROCESS_ID)
310     {
311         ProcessInstanceInfo proc_info;
312         if (Host::GetProcessInfo(pid, proc_info))
313         {
314             StreamString response;
315             CreateProcessInfoResponse (proc_info, response);
316             return SendPacketNoLock (response.GetData(), response.GetSize());
317         }
318     }
319     return SendErrorResponse (1);
320 }
321 
322 bool
Handle_qfProcessInfo(StringExtractorGDBRemote & packet)323 GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
324 {
325     m_proc_infos_index = 0;
326     m_proc_infos.Clear();
327 
328     ProcessInstanceInfoMatch match_info;
329     packet.SetFilePos(::strlen ("qfProcessInfo"));
330     if (packet.GetChar() == ':')
331     {
332 
333         std::string key;
334         std::string value;
335         while (packet.GetNameColonValue(key, value))
336         {
337             bool success = true;
338             if (key.compare("name") == 0)
339             {
340                 StringExtractor extractor;
341                 extractor.GetStringRef().swap(value);
342                 extractor.GetHexByteString (value);
343                 match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
344             }
345             else if (key.compare("name_match") == 0)
346             {
347                 if (value.compare("equals") == 0)
348                 {
349                     match_info.SetNameMatchType (eNameMatchEquals);
350                 }
351                 else if (value.compare("starts_with") == 0)
352                 {
353                     match_info.SetNameMatchType (eNameMatchStartsWith);
354                 }
355                 else if (value.compare("ends_with") == 0)
356                 {
357                     match_info.SetNameMatchType (eNameMatchEndsWith);
358                 }
359                 else if (value.compare("contains") == 0)
360                 {
361                     match_info.SetNameMatchType (eNameMatchContains);
362                 }
363                 else if (value.compare("regex") == 0)
364                 {
365                     match_info.SetNameMatchType (eNameMatchRegularExpression);
366                 }
367                 else
368                 {
369                     success = false;
370                 }
371             }
372             else if (key.compare("pid") == 0)
373             {
374                 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
375             }
376             else if (key.compare("parent_pid") == 0)
377             {
378                 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
379             }
380             else if (key.compare("uid") == 0)
381             {
382                 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
383             }
384             else if (key.compare("gid") == 0)
385             {
386                 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
387             }
388             else if (key.compare("euid") == 0)
389             {
390                 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
391             }
392             else if (key.compare("egid") == 0)
393             {
394                 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
395             }
396             else if (key.compare("all_users") == 0)
397             {
398                 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
399             }
400             else if (key.compare("triple") == 0)
401             {
402                 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
403             }
404             else
405             {
406                 success = false;
407             }
408 
409             if (!success)
410                 return SendErrorResponse (2);
411         }
412     }
413 
414     if (Host::FindProcesses (match_info, m_proc_infos))
415     {
416         // We found something, return the first item by calling the get
417         // subsequent process info packet handler...
418         return Handle_qsProcessInfo (packet);
419     }
420     return SendErrorResponse (3);
421 }
422 
423 bool
Handle_qsProcessInfo(StringExtractorGDBRemote & packet)424 GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
425 {
426     if (m_proc_infos_index < m_proc_infos.GetSize())
427     {
428         StreamString response;
429         CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
430         ++m_proc_infos_index;
431         return SendPacketNoLock (response.GetData(), response.GetSize());
432     }
433     return SendErrorResponse (4);
434 }
435 
436 bool
Handle_qUserName(StringExtractorGDBRemote & packet)437 GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
438 {
439     // Packet format: "qUserName:%i" where %i is the uid
440     packet.SetFilePos(::strlen ("qUserName:"));
441     uint32_t uid = packet.GetU32 (UINT32_MAX);
442     if (uid != UINT32_MAX)
443     {
444         std::string name;
445         if (Host::GetUserName (uid, name))
446         {
447             StreamString response;
448             response.PutCStringAsRawHex8 (name.c_str());
449             return SendPacketNoLock (response.GetData(), response.GetSize());
450         }
451     }
452     return SendErrorResponse (5);
453 
454 }
455 
456 bool
Handle_qGroupName(StringExtractorGDBRemote & packet)457 GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
458 {
459     // Packet format: "qGroupName:%i" where %i is the gid
460     packet.SetFilePos(::strlen ("qGroupName:"));
461     uint32_t gid = packet.GetU32 (UINT32_MAX);
462     if (gid != UINT32_MAX)
463     {
464         std::string name;
465         if (Host::GetGroupName (gid, name))
466         {
467             StreamString response;
468             response.PutCStringAsRawHex8 (name.c_str());
469             return SendPacketNoLock (response.GetData(), response.GetSize());
470         }
471     }
472     return SendErrorResponse (6);
473 }
474 
475 bool
Handle_qSpeedTest(StringExtractorGDBRemote & packet)476 GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
477 {
478     packet.SetFilePos(::strlen ("qSpeedTest:"));
479 
480     std::string key;
481     std::string value;
482     bool success = packet.GetNameColonValue(key, value);
483     if (success && key.compare("response_size") == 0)
484     {
485         uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
486         if (success)
487         {
488             if (response_size == 0)
489                 return SendOKResponse();
490             StreamString response;
491             uint32_t bytes_left = response_size;
492             response.PutCString("data:");
493             while (bytes_left > 0)
494             {
495                 if (bytes_left >= 26)
496                 {
497                     response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
498                     bytes_left -= 26;
499                 }
500                 else
501                 {
502                     response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
503                     bytes_left = 0;
504                 }
505             }
506             return SendPacketNoLock (response.GetData(), response.GetSize());
507         }
508     }
509     return SendErrorResponse (7);
510 }
511 
512 
513 static void *
AcceptPortFromInferior(void * arg)514 AcceptPortFromInferior (void *arg)
515 {
516     const char *connect_url = (const char *)arg;
517     ConnectionFileDescriptor file_conn;
518     Error error;
519     if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
520     {
521         char pid_str[256];
522         ::memset (pid_str, 0, sizeof(pid_str));
523         ConnectionStatus status;
524         const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL);
525         if (pid_str_len > 0)
526         {
527             int pid = atoi (pid_str);
528             return (void *)(intptr_t)pid;
529         }
530     }
531     return NULL;
532 }
533 //
534 //static bool
535 //WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
536 //{
537 //    const int time_delta_usecs = 100000;
538 //    const int num_retries = timeout_in_seconds/time_delta_usecs;
539 //    for (int i=0; i<num_retries; i++)
540 //    {
541 //        struct proc_bsdinfo bsd_info;
542 //        int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
543 //                                    (uint64_t) 0,
544 //                                    &bsd_info,
545 //                                    PROC_PIDTBSDINFO_SIZE);
546 //
547 //        switch (error)
548 //        {
549 //            case EINVAL:
550 //            case ENOTSUP:
551 //            case ESRCH:
552 //            case EPERM:
553 //                return false;
554 //
555 //            default:
556 //                break;
557 //
558 //            case 0:
559 //                if (bsd_info.pbi_status == SSTOP)
560 //                    return true;
561 //        }
562 //        ::usleep (time_delta_usecs);
563 //    }
564 //    return false;
565 //}
566 
567 bool
Handle_A(StringExtractorGDBRemote & packet)568 GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
569 {
570     // The 'A' packet is the most over designed packet ever here with
571     // redundant argument indexes, redundant argument lengths and needed hex
572     // encoded argument string values. Really all that is needed is a comma
573     // separated hex encoded argument value list, but we will stay true to the
574     // documented version of the 'A' packet here...
575 
576     packet.SetFilePos(1); // Skip the 'A'
577     bool success = true;
578     while (success && packet.GetBytesLeft() > 0)
579     {
580         // Decode the decimal argument string length. This length is the
581         // number of hex nibbles in the argument string value.
582         const uint32_t arg_len = packet.GetU32(UINT32_MAX);
583         if (arg_len == UINT32_MAX)
584             success = false;
585         else
586         {
587             // Make sure the argument hex string length is followed by a comma
588             if (packet.GetChar() != ',')
589                 success = false;
590             else
591             {
592                 // Decode the argument index. We ignore this really becuase
593                 // who would really send down the arguments in a random order???
594                 const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
595                 if (arg_idx == UINT32_MAX)
596                     success = false;
597                 else
598                 {
599                     // Make sure the argument index is followed by a comma
600                     if (packet.GetChar() != ',')
601                         success = false;
602                     else
603                     {
604                         // Decode the argument string value from hex bytes
605                         // back into a UTF8 string and make sure the length
606                         // matches the one supplied in the packet
607                         std::string arg;
608                         if (packet.GetHexByteString(arg) != (arg_len / 2))
609                             success = false;
610                         else
611                         {
612                             // If there are any bytes lft
613                             if (packet.GetBytesLeft())
614                             {
615                                 if (packet.GetChar() != ',')
616                                     success = false;
617                             }
618 
619                             if (success)
620                             {
621                                 if (arg_idx == 0)
622                                     m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
623                                 m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
624                             }
625                         }
626                     }
627                 }
628             }
629         }
630     }
631 
632     if (success)
633     {
634         m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
635         m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
636         if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
637         {
638             return SendOKResponse ();
639         }
640     }
641     return SendErrorResponse (8);
642 }
643 
644 bool
Handle_qC(StringExtractorGDBRemote & packet)645 GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
646 {
647     lldb::pid_t pid = m_process_launch_info.GetProcessID();
648     StreamString response;
649     response.Printf("QC%" PRIx64, pid);
650     if (m_is_platform)
651     {
652         // If we launch a process and this GDB server is acting as a platform,
653         // then we need to clear the process launch state so we can start
654         // launching another process. In order to launch a process a bunch or
655         // packets need to be sent: environment packets, working directory,
656         // disable ASLR, and many more settings. When we launch a process we
657         // then need to know when to clear this information. Currently we are
658         // selecting the 'qC' packet as that packet which seems to make the most
659         // sense.
660         if (pid != LLDB_INVALID_PROCESS_ID)
661         {
662             m_process_launch_info.Clear();
663         }
664     }
665     return SendPacketNoLock (response.GetData(), response.GetSize());
666 }
667 
668 bool
Handle_qLaunchGDBServer(StringExtractorGDBRemote & packet)669 GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
670 {
671     // Spawn a local debugserver as a platform so we can then attach or launch
672     // a process...
673 
674     if (m_is_platform)
675     {
676         // Sleep and wait a bit for debugserver to start to listen...
677         ConnectionFileDescriptor file_conn;
678         char connect_url[PATH_MAX];
679         Error error;
680         char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
681         if (::mktemp (unix_socket_name) == NULL)
682         {
683             error.SetErrorString ("failed to make temporary path for a unix socket");
684         }
685         else
686         {
687             ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
688             // Spawn a new thread to accept the port that gets bound after
689             // binding to port 0 (zero).
690             lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
691                                                                AcceptPortFromInferior,
692                                                                connect_url,
693                                                                &error);
694 
695             if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
696             {
697                 // Spawn a debugserver and try to get
698                 ProcessLaunchInfo debugserver_launch_info;
699                 error = StartDebugserverProcess ("localhost:0",
700                                                  unix_socket_name,
701                                                  debugserver_launch_info);
702 
703                 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
704                 if (error.Success())
705                 {
706                     bool success = false;
707 
708                     thread_result_t accept_thread_result = NULL;
709                     if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
710                     {
711                         if (accept_thread_result)
712                         {
713                             uint16_t port = (intptr_t)accept_thread_result;
714                             char response[256];
715                             const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
716                             assert (response_len < (int)sizeof(response));
717                             //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
718                             success = SendPacketNoLock (response, response_len) > 0;
719                         }
720                     }
721                     ::unlink (unix_socket_name);
722 
723                     if (!success)
724                     {
725                         if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
726                             ::kill (debugserver_pid, SIGINT);
727                     }
728                     return success;
729                 }
730             }
731         }
732     }
733     return SendErrorResponse (13);
734 }
735 
736 bool
Handle_qLaunchSuccess(StringExtractorGDBRemote & packet)737 GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
738 {
739     if (m_process_launch_error.Success())
740         return SendOKResponse();
741     StreamString response;
742     response.PutChar('E');
743     response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
744     return SendPacketNoLock (response.GetData(), response.GetSize());
745 }
746 
747 bool
Handle_QEnvironment(StringExtractorGDBRemote & packet)748 GDBRemoteCommunicationServer::Handle_QEnvironment  (StringExtractorGDBRemote &packet)
749 {
750     packet.SetFilePos(::strlen ("QEnvironment:"));
751     const uint32_t bytes_left = packet.GetBytesLeft();
752     if (bytes_left > 0)
753     {
754         m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
755         return SendOKResponse ();
756     }
757     return SendErrorResponse (9);
758 }
759 
760 bool
Handle_QSetDisableASLR(StringExtractorGDBRemote & packet)761 GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
762 {
763     packet.SetFilePos(::strlen ("QSetDisableASLR:"));
764     if (packet.GetU32(0))
765         m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
766     else
767         m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
768     return SendOKResponse ();
769 }
770 
771 bool
Handle_QSetWorkingDir(StringExtractorGDBRemote & packet)772 GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
773 {
774     packet.SetFilePos(::strlen ("QSetWorkingDir:"));
775     std::string path;
776     packet.GetHexByteString(path);
777     m_process_launch_info.SwapWorkingDirectory (path);
778     return SendOKResponse ();
779 }
780 
781 bool
Handle_QSetSTDIN(StringExtractorGDBRemote & packet)782 GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
783 {
784     packet.SetFilePos(::strlen ("QSetSTDIN:"));
785     ProcessLaunchInfo::FileAction file_action;
786     std::string path;
787     packet.GetHexByteString(path);
788     const bool read = false;
789     const bool write = true;
790     if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
791     {
792         m_process_launch_info.AppendFileAction(file_action);
793         return SendOKResponse ();
794     }
795     return SendErrorResponse (10);
796 }
797 
798 bool
Handle_QSetSTDOUT(StringExtractorGDBRemote & packet)799 GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
800 {
801     packet.SetFilePos(::strlen ("QSetSTDOUT:"));
802     ProcessLaunchInfo::FileAction file_action;
803     std::string path;
804     packet.GetHexByteString(path);
805     const bool read = true;
806     const bool write = false;
807     if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
808     {
809         m_process_launch_info.AppendFileAction(file_action);
810         return SendOKResponse ();
811     }
812     return SendErrorResponse (11);
813 }
814 
815 bool
Handle_QSetSTDERR(StringExtractorGDBRemote & packet)816 GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
817 {
818     packet.SetFilePos(::strlen ("QSetSTDERR:"));
819     ProcessLaunchInfo::FileAction file_action;
820     std::string path;
821     packet.GetHexByteString(path);
822     const bool read = true;
823     const bool write = false;
824     if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
825     {
826         m_process_launch_info.AppendFileAction(file_action);
827         return SendOKResponse ();
828     }
829     return SendErrorResponse (12);
830 }
831 
832 bool
Handle_QStartNoAckMode(StringExtractorGDBRemote & packet)833 GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
834 {
835     // Send response first before changing m_send_acks to we ack this packet
836     SendOKResponse ();
837     m_send_acks = false;
838     return true;
839 }
840