1 //===-- GDBRemoteCommunicationServerCommon.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 "GDBRemoteCommunicationServerCommon.h"
11 
12 #include <errno.h>
13 
14 // C Includes
15 // C++ Includes
16 #include <cstring>
17 #include <chrono>
18 
19 // Other libraries and framework includes
20 #include "llvm/ADT/Triple.h"
21 #include "lldb/Core/Log.h"
22 #include "lldb/Core/StreamGDBRemote.h"
23 #include "lldb/Core/StreamString.h"
24 #include "lldb/Host/Config.h"
25 #include "lldb/Host/Endian.h"
26 #include "lldb/Host/File.h"
27 #include "lldb/Host/FileSystem.h"
28 #include "lldb/Host/Host.h"
29 #include "lldb/Host/HostInfo.h"
30 #include "lldb/Host/StringConvert.h"
31 #include "lldb/Interpreter/Args.h"
32 #include "lldb/Target/FileAction.h"
33 #include "lldb/Target/Platform.h"
34 #include "lldb/Target/Process.h"
35 
36 // Project includes
37 #include "ProcessGDBRemoteLog.h"
38 #include "Utility/StringExtractorGDBRemote.h"
39 
40 using namespace lldb;
41 using namespace lldb_private;
42 
43 //----------------------------------------------------------------------
44 // GDBRemoteCommunicationServerCommon constructor
45 //----------------------------------------------------------------------
46 GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name) :
47     GDBRemoteCommunicationServer (comm_name, listener_name),
48     m_spawned_pids (),
49     m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
50     m_process_launch_info (),
51     m_process_launch_error (),
52     m_proc_infos (),
53     m_proc_infos_index (0),
54     m_thread_suffix_supported (false),
55     m_list_threads_in_stop_reply (false)
56 {
57     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A,
58                                   &GDBRemoteCommunicationServerCommon::Handle_A);
59     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QEnvironment,
60                                   &GDBRemoteCommunicationServerCommon::Handle_QEnvironment);
61     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qfProcessInfo,
62                                   &GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo);
63     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGroupName,
64                                   &GDBRemoteCommunicationServerCommon::Handle_qGroupName);
65     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qHostInfo,
66                                   &GDBRemoteCommunicationServerCommon::Handle_qHostInfo);
67     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
68                                   &GDBRemoteCommunicationServerCommon::Handle_qKillSpawnedProcess);
69     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QLaunchArch,
70                                   &GDBRemoteCommunicationServerCommon::Handle_QLaunchArch);
71     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess,
72                                   &GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess);
73     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply,
74                                   &GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply);
75     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod,
76                                   &GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod);
77     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir,
78                                   &GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir);
79     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qPlatform_shell,
80                                   &GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell);
81     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID,
82                                   &GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID);
83     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetDetachOnError,
84                                   &GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError);
85     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetSTDERR,
86                                   &GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR);
87     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetSTDIN,
88                                   &GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN);
89     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT,
90                                   &GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT);
91     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qSpeedTest,
92                                   &GDBRemoteCommunicationServerCommon::Handle_qSpeedTest);
93     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qsProcessInfo,
94                                   &GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo);
95     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode,
96                                   &GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode);
97     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qSupported,
98                                   &GDBRemoteCommunicationServerCommon::Handle_qSupported);
99     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported,
100                                   &GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported);
101     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qUserName,
102                                   &GDBRemoteCommunicationServerCommon::Handle_qUserName);
103     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_close,
104                                   &GDBRemoteCommunicationServerCommon::Handle_vFile_Close);
105     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_exists,
106                                   &GDBRemoteCommunicationServerCommon::Handle_vFile_Exists);
107     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_md5,
108                                   &GDBRemoteCommunicationServerCommon::Handle_vFile_MD5);
109     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_mode,
110                                   &GDBRemoteCommunicationServerCommon::Handle_vFile_Mode);
111     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_open,
112                                   &GDBRemoteCommunicationServerCommon::Handle_vFile_Open);
113     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_pread,
114                                   &GDBRemoteCommunicationServerCommon::Handle_vFile_pRead);
115     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_pwrite,
116                                   &GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite);
117     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_size,
118                                   &GDBRemoteCommunicationServerCommon::Handle_vFile_Size);
119     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_stat,
120                                   &GDBRemoteCommunicationServerCommon::Handle_vFile_Stat);
121     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_symlink,
122                                   &GDBRemoteCommunicationServerCommon::Handle_vFile_symlink);
123     RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_unlink,
124                                   &GDBRemoteCommunicationServerCommon::Handle_vFile_unlink);
125 }
126 
127 //----------------------------------------------------------------------
128 // Destructor
129 //----------------------------------------------------------------------
130 GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon()
131 {
132 }
133 
134 GDBRemoteCommunication::PacketResult
135 GDBRemoteCommunicationServerCommon::Handle_qHostInfo (StringExtractorGDBRemote &packet)
136 {
137     StreamString response;
138 
139     // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
140 
141     ArchSpec host_arch(HostInfo::GetArchitecture());
142     const llvm::Triple &host_triple = host_arch.GetTriple();
143     response.PutCString("triple:");
144     response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
145     response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
146 
147     const char* distribution_id = host_arch.GetDistributionId ().AsCString ();
148     if (distribution_id)
149     {
150         response.PutCString("distribution_id:");
151         response.PutCStringAsRawHex8(distribution_id);
152         response.PutCString(";");
153     }
154 
155     // Only send out MachO info when lldb-platform/llgs is running on a MachO host.
156 #if defined(__APPLE__)
157     uint32_t cpu = host_arch.GetMachOCPUType();
158     uint32_t sub = host_arch.GetMachOCPUSubType();
159     if (cpu != LLDB_INVALID_CPUTYPE)
160         response.Printf ("cputype:%u;", cpu);
161     if (sub != LLDB_INVALID_CPUTYPE)
162         response.Printf ("cpusubtype:%u;", sub);
163 
164     if (cpu == ArchSpec::kCore_arm_any)
165         response.Printf("watchpoint_exceptions_received:before;");   // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
166     else
167         response.Printf("watchpoint_exceptions_received:after;");
168 #else
169     response.Printf("watchpoint_exceptions_received:after;");
170 #endif
171 
172     switch (lldb::endian::InlHostByteOrder())
173     {
174     case eByteOrderBig:     response.PutCString ("endian:big;"); break;
175     case eByteOrderLittle:  response.PutCString ("endian:little;"); break;
176     case eByteOrderPDP:     response.PutCString ("endian:pdp;"); break;
177     default:                response.PutCString ("endian:unknown;"); break;
178     }
179 
180     uint32_t major = UINT32_MAX;
181     uint32_t minor = UINT32_MAX;
182     uint32_t update = UINT32_MAX;
183     if (HostInfo::GetOSVersion(major, minor, update))
184     {
185         if (major != UINT32_MAX)
186         {
187             response.Printf("os_version:%u", major);
188             if (minor != UINT32_MAX)
189             {
190                 response.Printf(".%u", minor);
191                 if (update != UINT32_MAX)
192                     response.Printf(".%u", update);
193             }
194             response.PutChar(';');
195         }
196     }
197 
198     std::string s;
199     if (HostInfo::GetOSBuildString(s))
200     {
201         response.PutCString ("os_build:");
202         response.PutCStringAsRawHex8(s.c_str());
203         response.PutChar(';');
204     }
205     if (HostInfo::GetOSKernelDescription(s))
206     {
207         response.PutCString ("os_kernel:");
208         response.PutCStringAsRawHex8(s.c_str());
209         response.PutChar(';');
210     }
211 
212 #if defined(__APPLE__)
213 
214 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
215     // For iOS devices, we are connected through a USB Mux so we never pretend
216     // to actually have a hostname as far as the remote lldb that is connecting
217     // to this lldb-platform is concerned
218     response.PutCString ("hostname:");
219     response.PutCStringAsRawHex8("127.0.0.1");
220     response.PutChar(';');
221 #else   // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
222     if (HostInfo::GetHostname(s))
223     {
224         response.PutCString ("hostname:");
225         response.PutCStringAsRawHex8(s.c_str());
226         response.PutChar(';');
227     }
228 #endif  // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
229 
230 #else   // #if defined(__APPLE__)
231     if (HostInfo::GetHostname(s))
232     {
233         response.PutCString ("hostname:");
234         response.PutCStringAsRawHex8(s.c_str());
235         response.PutChar(';');
236     }
237 #endif  // #if defined(__APPLE__)
238 
239     return SendPacketNoLock (response.GetData(), response.GetSize());
240 }
241 
242 GDBRemoteCommunication::PacketResult
243 GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
244 {
245     // Packet format: "qProcessInfoPID:%i" where %i is the pid
246     packet.SetFilePos (::strlen ("qProcessInfoPID:"));
247     lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
248     if (pid != LLDB_INVALID_PROCESS_ID)
249     {
250         ProcessInstanceInfo proc_info;
251         if (Host::GetProcessInfo (pid, proc_info))
252         {
253             StreamString response;
254             CreateProcessInfoResponse (proc_info, response);
255             return SendPacketNoLock (response.GetData(), response.GetSize());
256         }
257     }
258     return SendErrorResponse (1);
259 }
260 
261 GDBRemoteCommunication::PacketResult
262 GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
263 {
264     m_proc_infos_index = 0;
265     m_proc_infos.Clear();
266 
267     ProcessInstanceInfoMatch match_info;
268     packet.SetFilePos(::strlen ("qfProcessInfo"));
269     if (packet.GetChar() == ':')
270     {
271 
272         std::string key;
273         std::string value;
274         while (packet.GetNameColonValue(key, value))
275         {
276             bool success = true;
277             if (key.compare("name") == 0)
278             {
279                 StringExtractor extractor;
280                 extractor.GetStringRef().swap(value);
281                 extractor.GetHexByteString (value);
282                 match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
283             }
284             else if (key.compare("name_match") == 0)
285             {
286                 if (value.compare("equals") == 0)
287                 {
288                     match_info.SetNameMatchType (eNameMatchEquals);
289                 }
290                 else if (value.compare("starts_with") == 0)
291                 {
292                     match_info.SetNameMatchType (eNameMatchStartsWith);
293                 }
294                 else if (value.compare("ends_with") == 0)
295                 {
296                     match_info.SetNameMatchType (eNameMatchEndsWith);
297                 }
298                 else if (value.compare("contains") == 0)
299                 {
300                     match_info.SetNameMatchType (eNameMatchContains);
301                 }
302                 else if (value.compare("regex") == 0)
303                 {
304                     match_info.SetNameMatchType (eNameMatchRegularExpression);
305                 }
306                 else
307                 {
308                     success = false;
309                 }
310             }
311             else if (key.compare("pid") == 0)
312             {
313                 match_info.GetProcessInfo().SetProcessID (StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
314             }
315             else if (key.compare("parent_pid") == 0)
316             {
317                 match_info.GetProcessInfo().SetParentProcessID (StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
318             }
319             else if (key.compare("uid") == 0)
320             {
321                 match_info.GetProcessInfo().SetUserID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success));
322             }
323             else if (key.compare("gid") == 0)
324             {
325                 match_info.GetProcessInfo().SetGroupID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success));
326             }
327             else if (key.compare("euid") == 0)
328             {
329                 match_info.GetProcessInfo().SetEffectiveUserID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success));
330             }
331             else if (key.compare("egid") == 0)
332             {
333                 match_info.GetProcessInfo().SetEffectiveGroupID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success));
334             }
335             else if (key.compare("all_users") == 0)
336             {
337                 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
338             }
339             else if (key.compare("triple") == 0)
340             {
341                 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
342             }
343             else
344             {
345                 success = false;
346             }
347 
348             if (!success)
349                 return SendErrorResponse (2);
350         }
351     }
352 
353     if (Host::FindProcesses (match_info, m_proc_infos))
354     {
355         // We found something, return the first item by calling the get
356         // subsequent process info packet handler...
357         return Handle_qsProcessInfo (packet);
358     }
359     return SendErrorResponse (3);
360 }
361 
362 GDBRemoteCommunication::PacketResult
363 GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
364 {
365     if (m_proc_infos_index < m_proc_infos.GetSize())
366     {
367         StreamString response;
368         CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
369         ++m_proc_infos_index;
370         return SendPacketNoLock (response.GetData(), response.GetSize());
371     }
372     return SendErrorResponse (4);
373 }
374 
375 GDBRemoteCommunication::PacketResult
376 GDBRemoteCommunicationServerCommon::Handle_qUserName (StringExtractorGDBRemote &packet)
377 {
378 #if !defined(LLDB_DISABLE_POSIX)
379     // Packet format: "qUserName:%i" where %i is the uid
380     packet.SetFilePos(::strlen ("qUserName:"));
381     uint32_t uid = packet.GetU32 (UINT32_MAX);
382     if (uid != UINT32_MAX)
383     {
384         std::string name;
385         if (HostInfo::LookupUserName(uid, name))
386         {
387             StreamString response;
388             response.PutCStringAsRawHex8 (name.c_str());
389             return SendPacketNoLock (response.GetData(), response.GetSize());
390         }
391     }
392 #endif
393     return SendErrorResponse (5);
394 
395 }
396 
397 GDBRemoteCommunication::PacketResult
398 GDBRemoteCommunicationServerCommon::Handle_qGroupName (StringExtractorGDBRemote &packet)
399 {
400 #if !defined(LLDB_DISABLE_POSIX)
401     // Packet format: "qGroupName:%i" where %i is the gid
402     packet.SetFilePos(::strlen ("qGroupName:"));
403     uint32_t gid = packet.GetU32 (UINT32_MAX);
404     if (gid != UINT32_MAX)
405     {
406         std::string name;
407         if (HostInfo::LookupGroupName(gid, name))
408         {
409             StreamString response;
410             response.PutCStringAsRawHex8 (name.c_str());
411             return SendPacketNoLock (response.GetData(), response.GetSize());
412         }
413     }
414 #endif
415     return SendErrorResponse (6);
416 }
417 
418 GDBRemoteCommunication::PacketResult
419 GDBRemoteCommunicationServerCommon::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
420 {
421     packet.SetFilePos(::strlen ("qSpeedTest:"));
422 
423     std::string key;
424     std::string value;
425     bool success = packet.GetNameColonValue(key, value);
426     if (success && key.compare("response_size") == 0)
427     {
428         uint32_t response_size = StringConvert::ToUInt32(value.c_str(), 0, 0, &success);
429         if (success)
430         {
431             if (response_size == 0)
432                 return SendOKResponse();
433             StreamString response;
434             uint32_t bytes_left = response_size;
435             response.PutCString("data:");
436             while (bytes_left > 0)
437             {
438                 if (bytes_left >= 26)
439                 {
440                     response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
441                     bytes_left -= 26;
442                 }
443                 else
444                 {
445                     response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
446                     bytes_left = 0;
447                 }
448             }
449             return SendPacketNoLock (response.GetData(), response.GetSize());
450         }
451     }
452     return SendErrorResponse (7);
453 }
454 
455 GDBRemoteCommunication::PacketResult
456 GDBRemoteCommunicationServerCommon::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
457 {
458     packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
459 
460     lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
461 
462     // verify that we know anything about this pid.
463     // Scope for locker
464     {
465         Mutex::Locker locker (m_spawned_pids_mutex);
466         if (m_spawned_pids.find(pid) == m_spawned_pids.end())
467         {
468             // not a pid we know about
469             return SendErrorResponse (10);
470         }
471     }
472 
473     // go ahead and attempt to kill the spawned process
474     if (KillSpawnedProcess (pid))
475         return SendOKResponse ();
476     else
477         return SendErrorResponse (11);
478 }
479 
480 bool
481 GDBRemoteCommunicationServerCommon::KillSpawnedProcess (lldb::pid_t pid)
482 {
483     // make sure we know about this process
484     {
485         Mutex::Locker locker (m_spawned_pids_mutex);
486         if (m_spawned_pids.find(pid) == m_spawned_pids.end())
487             return false;
488     }
489 
490     // first try a SIGTERM (standard kill)
491     Host::Kill (pid, SIGTERM);
492 
493     // check if that worked
494     for (size_t i=0; i<10; ++i)
495     {
496         {
497             Mutex::Locker locker (m_spawned_pids_mutex);
498             if (m_spawned_pids.find(pid) == m_spawned_pids.end())
499             {
500                 // it is now killed
501                 return true;
502             }
503         }
504         usleep (10000);
505     }
506 
507     // check one more time after the final usleep
508     {
509         Mutex::Locker locker (m_spawned_pids_mutex);
510         if (m_spawned_pids.find(pid) == m_spawned_pids.end())
511             return true;
512     }
513 
514     // the launched process still lives.  Now try killing it again,
515     // this time with an unblockable signal.
516     Host::Kill (pid, SIGKILL);
517 
518     for (size_t i=0; i<10; ++i)
519     {
520         {
521             Mutex::Locker locker (m_spawned_pids_mutex);
522             if (m_spawned_pids.find(pid) == m_spawned_pids.end())
523             {
524                 // it is now killed
525                 return true;
526             }
527         }
528         usleep (10000);
529     }
530 
531     // check one more time after the final usleep
532     // Scope for locker
533     {
534         Mutex::Locker locker (m_spawned_pids_mutex);
535         if (m_spawned_pids.find(pid) == m_spawned_pids.end())
536             return true;
537     }
538 
539     // no luck - the process still lives
540     return false;
541 }
542 
543 GDBRemoteCommunication::PacketResult
544 GDBRemoteCommunicationServerCommon::Handle_vFile_Open (StringExtractorGDBRemote &packet)
545 {
546     packet.SetFilePos(::strlen("vFile:open:"));
547     std::string path;
548     packet.GetHexByteStringTerminatedBy(path,',');
549     if (!path.empty())
550     {
551         if (packet.GetChar() == ',')
552         {
553             uint32_t flags = packet.GetHexMaxU32(false, 0);
554             if (packet.GetChar() == ',')
555             {
556                 mode_t mode = packet.GetHexMaxU32(false, 0600);
557                 Error error;
558                 int fd = ::open (path.c_str(), flags, mode);
559                 const int save_errno = fd == -1 ? errno : 0;
560                 StreamString response;
561                 response.PutChar('F');
562                 response.Printf("%i", fd);
563                 if (save_errno)
564                     response.Printf(",%i", save_errno);
565                 return SendPacketNoLock(response.GetData(), response.GetSize());
566             }
567         }
568     }
569     return SendErrorResponse(18);
570 }
571 
572 GDBRemoteCommunication::PacketResult
573 GDBRemoteCommunicationServerCommon::Handle_vFile_Close (StringExtractorGDBRemote &packet)
574 {
575     packet.SetFilePos(::strlen("vFile:close:"));
576     int fd = packet.GetS32(-1);
577     Error error;
578     int err = -1;
579     int save_errno = 0;
580     if (fd >= 0)
581     {
582         err = close(fd);
583         save_errno = err == -1 ? errno : 0;
584     }
585     else
586     {
587         save_errno = EINVAL;
588     }
589     StreamString response;
590     response.PutChar('F');
591     response.Printf("%i", err);
592     if (save_errno)
593         response.Printf(",%i", save_errno);
594     return SendPacketNoLock(response.GetData(), response.GetSize());
595 }
596 
597 GDBRemoteCommunication::PacketResult
598 GDBRemoteCommunicationServerCommon::Handle_vFile_pRead (StringExtractorGDBRemote &packet)
599 {
600 #ifdef _WIN32
601     // Not implemented on Windows
602     return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_vFile_pRead() unimplemented");
603 #else
604     StreamGDBRemote response;
605     packet.SetFilePos(::strlen("vFile:pread:"));
606     int fd = packet.GetS32(-1);
607     if (packet.GetChar() == ',')
608     {
609         uint64_t count = packet.GetU64(UINT64_MAX);
610         if (packet.GetChar() == ',')
611         {
612             uint64_t offset = packet.GetU64(UINT32_MAX);
613             if (count == UINT64_MAX)
614             {
615                 response.Printf("F-1:%i", EINVAL);
616                 return SendPacketNoLock(response.GetData(), response.GetSize());
617             }
618 
619             std::string buffer(count, 0);
620             const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
621             const int save_errno = bytes_read == -1 ? errno : 0;
622             response.PutChar('F');
623             response.Printf("%zi", bytes_read);
624             if (save_errno)
625                 response.Printf(",%i", save_errno);
626             else
627             {
628                 response.PutChar(';');
629                 response.PutEscapedBytes(&buffer[0], bytes_read);
630             }
631             return SendPacketNoLock(response.GetData(), response.GetSize());
632         }
633     }
634     return SendErrorResponse(21);
635 
636 #endif
637 }
638 
639 GDBRemoteCommunication::PacketResult
640 GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
641 {
642 #ifdef _WIN32
643     return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite() unimplemented");
644 #else
645     packet.SetFilePos(::strlen("vFile:pwrite:"));
646 
647     StreamGDBRemote response;
648     response.PutChar('F');
649 
650     int fd = packet.GetU32(UINT32_MAX);
651     if (packet.GetChar() == ',')
652     {
653         off_t offset = packet.GetU64(UINT32_MAX);
654         if (packet.GetChar() == ',')
655         {
656             std::string buffer;
657             if (packet.GetEscapedBinaryData(buffer))
658             {
659                 const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
660                 const int save_errno = bytes_written == -1 ? errno : 0;
661                 response.Printf("%zi", bytes_written);
662                 if (save_errno)
663                     response.Printf(",%i", save_errno);
664             }
665             else
666             {
667                 response.Printf ("-1,%i", EINVAL);
668             }
669             return SendPacketNoLock(response.GetData(), response.GetSize());
670         }
671     }
672     return SendErrorResponse(27);
673 #endif
674 }
675 
676 GDBRemoteCommunication::PacketResult
677 GDBRemoteCommunicationServerCommon::Handle_vFile_Size (StringExtractorGDBRemote &packet)
678 {
679     packet.SetFilePos(::strlen("vFile:size:"));
680     std::string path;
681     packet.GetHexByteString(path);
682     if (!path.empty())
683     {
684         lldb::user_id_t retcode = FileSystem::GetFileSize(FileSpec(path.c_str(), false));
685         StreamString response;
686         response.PutChar('F');
687         response.PutHex64(retcode);
688         if (retcode == UINT64_MAX)
689         {
690             response.PutChar(',');
691             response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
692         }
693         return SendPacketNoLock(response.GetData(), response.GetSize());
694     }
695     return SendErrorResponse(22);
696 }
697 
698 GDBRemoteCommunication::PacketResult
699 GDBRemoteCommunicationServerCommon::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
700 {
701     packet.SetFilePos(::strlen("vFile:mode:"));
702     std::string path;
703     packet.GetHexByteString(path);
704     if (!path.empty())
705     {
706         Error error;
707         const uint32_t mode = File::GetPermissions(path.c_str(), error);
708         StreamString response;
709         response.Printf("F%u", mode);
710         if (mode == 0 || error.Fail())
711             response.Printf(",%i", (int)error.GetError());
712         return SendPacketNoLock(response.GetData(), response.GetSize());
713     }
714     return SendErrorResponse(23);
715 }
716 
717 GDBRemoteCommunication::PacketResult
718 GDBRemoteCommunicationServerCommon::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
719 {
720     packet.SetFilePos(::strlen("vFile:exists:"));
721     std::string path;
722     packet.GetHexByteString(path);
723     if (!path.empty())
724     {
725         bool retcode = FileSystem::GetFileExists(FileSpec(path.c_str(), false));
726         StreamString response;
727         response.PutChar('F');
728         response.PutChar(',');
729         if (retcode)
730             response.PutChar('1');
731         else
732             response.PutChar('0');
733         return SendPacketNoLock(response.GetData(), response.GetSize());
734     }
735     return SendErrorResponse(24);
736 }
737 
738 GDBRemoteCommunication::PacketResult
739 GDBRemoteCommunicationServerCommon::Handle_vFile_symlink (StringExtractorGDBRemote &packet)
740 {
741     packet.SetFilePos(::strlen("vFile:symlink:"));
742     std::string dst, src;
743     packet.GetHexByteStringTerminatedBy(dst, ',');
744     packet.GetChar(); // Skip ',' char
745     packet.GetHexByteString(src);
746     Error error = FileSystem::Symlink(src.c_str(), dst.c_str());
747     StreamString response;
748     response.Printf("F%u,%u", error.GetError(), error.GetError());
749     return SendPacketNoLock(response.GetData(), response.GetSize());
750 }
751 
752 GDBRemoteCommunication::PacketResult
753 GDBRemoteCommunicationServerCommon::Handle_vFile_unlink (StringExtractorGDBRemote &packet)
754 {
755     packet.SetFilePos(::strlen("vFile:unlink:"));
756     std::string path;
757     packet.GetHexByteString(path);
758     Error error = FileSystem::Unlink(path.c_str());
759     StreamString response;
760     response.Printf("F%u,%u", error.GetError(), error.GetError());
761     return SendPacketNoLock(response.GetData(), response.GetSize());
762 }
763 
764 GDBRemoteCommunication::PacketResult
765 GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell (StringExtractorGDBRemote &packet)
766 {
767     packet.SetFilePos(::strlen("qPlatform_shell:"));
768     std::string path;
769     std::string working_dir;
770     packet.GetHexByteStringTerminatedBy(path,',');
771     if (!path.empty())
772     {
773         if (packet.GetChar() == ',')
774         {
775             // FIXME: add timeout to qPlatform_shell packet
776             // uint32_t timeout = packet.GetHexMaxU32(false, 32);
777             uint32_t timeout = 10;
778             if (packet.GetChar() == ',')
779                 packet.GetHexByteString(working_dir);
780             int status, signo;
781             std::string output;
782             Error err = Host::RunShellCommand(path.c_str(),
783                                               working_dir.empty() ? NULL : working_dir.c_str(),
784                                               &status, &signo, &output, timeout);
785             StreamGDBRemote response;
786             if (err.Fail())
787             {
788                 response.PutCString("F,");
789                 response.PutHex32(UINT32_MAX);
790             }
791             else
792             {
793                 response.PutCString("F,");
794                 response.PutHex32(status);
795                 response.PutChar(',');
796                 response.PutHex32(signo);
797                 response.PutChar(',');
798                 response.PutEscapedBytes(output.c_str(), output.size());
799             }
800             return SendPacketNoLock(response.GetData(), response.GetSize());
801         }
802     }
803     return SendErrorResponse(24);
804 }
805 
806 
807 GDBRemoteCommunication::PacketResult
808 GDBRemoteCommunicationServerCommon::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
809 {
810     return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_vFile_Stat() unimplemented");
811 }
812 
813 GDBRemoteCommunication::PacketResult
814 GDBRemoteCommunicationServerCommon::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
815 {
816     packet.SetFilePos(::strlen("vFile:MD5:"));
817     std::string path;
818     packet.GetHexByteString(path);
819     if (!path.empty())
820     {
821         uint64_t a,b;
822         StreamGDBRemote response;
823         if (FileSystem::CalculateMD5(FileSpec(path.c_str(), false), a, b) == false)
824         {
825             response.PutCString("F,");
826             response.PutCString("x");
827         }
828         else
829         {
830             response.PutCString("F,");
831             response.PutHex64(a);
832             response.PutHex64(b);
833         }
834         return SendPacketNoLock(response.GetData(), response.GetSize());
835     }
836     return SendErrorResponse(25);
837 }
838 
839 GDBRemoteCommunication::PacketResult
840 GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet)
841 {
842     packet.SetFilePos(::strlen("qPlatform_mkdir:"));
843     mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
844     if (packet.GetChar() == ',')
845     {
846         std::string path;
847         packet.GetHexByteString(path);
848         Error error = FileSystem::MakeDirectory(path.c_str(), mode);
849 
850         StreamGDBRemote response;
851         response.Printf("F%u", error.GetError());
852 
853         return SendPacketNoLock(response.GetData(), response.GetSize());
854     }
855     return SendErrorResponse(20);
856 }
857 
858 GDBRemoteCommunication::PacketResult
859 GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet)
860 {
861     packet.SetFilePos(::strlen("qPlatform_chmod:"));
862 
863     mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
864     if (packet.GetChar() == ',')
865     {
866         std::string path;
867         packet.GetHexByteString(path);
868         Error error = FileSystem::SetFilePermissions(path.c_str(), mode);
869 
870         StreamGDBRemote response;
871         response.Printf("F%u", error.GetError());
872 
873         return SendPacketNoLock(response.GetData(), response.GetSize());
874     }
875     return SendErrorResponse(19);
876 }
877 
878 GDBRemoteCommunication::PacketResult
879 GDBRemoteCommunicationServerCommon::Handle_qSupported (StringExtractorGDBRemote &packet)
880 {
881     StreamGDBRemote response;
882 
883     // Features common to lldb-platform and llgs.
884     uint32_t max_packet_size = 128 * 1024;  // 128KBytes is a reasonable max packet size--debugger can always use less
885     response.Printf ("PacketSize=%x", max_packet_size);
886 
887     response.PutCString (";QStartNoAckMode+");
888     response.PutCString (";QThreadSuffixSupported+");
889     response.PutCString (";QListThreadsInStopReply+");
890 #if defined(__linux__)
891     response.PutCString (";qXfer:auxv:read+");
892 #endif
893 
894     return SendPacketNoLock(response.GetData(), response.GetSize());
895 }
896 
897 GDBRemoteCommunication::PacketResult
898 GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported (StringExtractorGDBRemote &packet)
899 {
900     m_thread_suffix_supported = true;
901     return SendOKResponse();
902 }
903 
904 GDBRemoteCommunication::PacketResult
905 GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply (StringExtractorGDBRemote &packet)
906 {
907     m_list_threads_in_stop_reply = true;
908     return SendOKResponse();
909 }
910 
911 GDBRemoteCommunication::PacketResult
912 GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError (StringExtractorGDBRemote &packet)
913 {
914     packet.SetFilePos(::strlen ("QSetDetachOnError:"));
915     if (packet.GetU32(0))
916         m_process_launch_info.GetFlags().Set (eLaunchFlagDetachOnError);
917     else
918         m_process_launch_info.GetFlags().Clear (eLaunchFlagDetachOnError);
919     return SendOKResponse ();
920 }
921 
922 GDBRemoteCommunication::PacketResult
923 GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
924 {
925     // Send response first before changing m_send_acks to we ack this packet
926     PacketResult packet_result = SendOKResponse ();
927     m_send_acks = false;
928     return packet_result;
929 }
930 
931 GDBRemoteCommunication::PacketResult
932 GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
933 {
934     packet.SetFilePos(::strlen ("QSetSTDIN:"));
935     FileAction file_action;
936     std::string path;
937     packet.GetHexByteString(path);
938     const bool read = false;
939     const bool write = true;
940     if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
941     {
942         m_process_launch_info.AppendFileAction(file_action);
943         return SendOKResponse ();
944     }
945     return SendErrorResponse (15);
946 }
947 
948 GDBRemoteCommunication::PacketResult
949 GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
950 {
951     packet.SetFilePos(::strlen ("QSetSTDOUT:"));
952     FileAction file_action;
953     std::string path;
954     packet.GetHexByteString(path);
955     const bool read = true;
956     const bool write = false;
957     if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
958     {
959         m_process_launch_info.AppendFileAction(file_action);
960         return SendOKResponse ();
961     }
962     return SendErrorResponse (16);
963 }
964 
965 GDBRemoteCommunication::PacketResult
966 GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
967 {
968     packet.SetFilePos(::strlen ("QSetSTDERR:"));
969     FileAction file_action;
970     std::string path;
971     packet.GetHexByteString(path);
972     const bool read = true;
973     const bool write = false;
974     if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
975     {
976         m_process_launch_info.AppendFileAction(file_action);
977         return SendOKResponse ();
978     }
979     return SendErrorResponse (17);
980 }
981 
982 GDBRemoteCommunication::PacketResult
983 GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
984 {
985     if (m_process_launch_error.Success())
986         return SendOKResponse();
987     StreamString response;
988     response.PutChar('E');
989     response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
990     return SendPacketNoLock (response.GetData(), response.GetSize());
991 }
992 
993 GDBRemoteCommunication::PacketResult
994 GDBRemoteCommunicationServerCommon::Handle_QEnvironment (StringExtractorGDBRemote &packet)
995 {
996     packet.SetFilePos(::strlen ("QEnvironment:"));
997     const uint32_t bytes_left = packet.GetBytesLeft();
998     if (bytes_left > 0)
999     {
1000         m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
1001         return SendOKResponse ();
1002     }
1003     return SendErrorResponse (12);
1004 }
1005 
1006 GDBRemoteCommunication::PacketResult
1007 GDBRemoteCommunicationServerCommon::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
1008 {
1009     packet.SetFilePos(::strlen ("QLaunchArch:"));
1010     const uint32_t bytes_left = packet.GetBytesLeft();
1011     if (bytes_left > 0)
1012     {
1013         const char* arch_triple = packet.Peek();
1014         ArchSpec arch_spec(arch_triple,NULL);
1015         m_process_launch_info.SetArchitecture(arch_spec);
1016         return SendOKResponse();
1017     }
1018     return SendErrorResponse(13);
1019 }
1020 
1021 GDBRemoteCommunication::PacketResult
1022 GDBRemoteCommunicationServerCommon::Handle_A (StringExtractorGDBRemote &packet)
1023 {
1024     // The 'A' packet is the most over designed packet ever here with
1025     // redundant argument indexes, redundant argument lengths and needed hex
1026     // encoded argument string values. Really all that is needed is a comma
1027     // separated hex encoded argument value list, but we will stay true to the
1028     // documented version of the 'A' packet here...
1029 
1030     Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
1031     int actual_arg_index = 0;
1032 
1033     packet.SetFilePos(1); // Skip the 'A'
1034     bool success = true;
1035     while (success && packet.GetBytesLeft() > 0)
1036     {
1037         // Decode the decimal argument string length. This length is the
1038         // number of hex nibbles in the argument string value.
1039         const uint32_t arg_len = packet.GetU32(UINT32_MAX);
1040         if (arg_len == UINT32_MAX)
1041             success = false;
1042         else
1043         {
1044             // Make sure the argument hex string length is followed by a comma
1045             if (packet.GetChar() != ',')
1046                 success = false;
1047             else
1048             {
1049                 // Decode the argument index. We ignore this really because
1050                 // who would really send down the arguments in a random order???
1051                 const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
1052                 if (arg_idx == UINT32_MAX)
1053                     success = false;
1054                 else
1055                 {
1056                     // Make sure the argument index is followed by a comma
1057                     if (packet.GetChar() != ',')
1058                         success = false;
1059                     else
1060                     {
1061                         // Decode the argument string value from hex bytes
1062                         // back into a UTF8 string and make sure the length
1063                         // matches the one supplied in the packet
1064                         std::string arg;
1065                         if (packet.GetHexByteStringFixedLength(arg, arg_len) != (arg_len / 2))
1066                             success = false;
1067                         else
1068                         {
1069                             // If there are any bytes left
1070                             if (packet.GetBytesLeft())
1071                             {
1072                                 if (packet.GetChar() != ',')
1073                                     success = false;
1074                             }
1075 
1076                             if (success)
1077                             {
1078                                 if (arg_idx == 0)
1079                                     m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
1080                                 m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
1081                                 if (log)
1082                                     log->Printf ("LLGSPacketHandler::%s added arg %d: \"%s\"", __FUNCTION__, actual_arg_index, arg.c_str ());
1083                                 ++actual_arg_index;
1084                             }
1085                         }
1086                     }
1087                 }
1088             }
1089         }
1090     }
1091 
1092     if (success)
1093     {
1094         m_process_launch_error = LaunchProcess ();
1095         if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
1096         {
1097             return SendOKResponse ();
1098         }
1099         else
1100         {
1101             Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
1102             if (log)
1103                 log->Printf("LLGSPacketHandler::%s failed to launch exe: %s",
1104                         __FUNCTION__,
1105                         m_process_launch_error.AsCString());
1106 
1107         }
1108     }
1109     return SendErrorResponse (8);
1110 }
1111 
1112 void
1113 GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info,
1114                                                     StreamString &response)
1115 {
1116     response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
1117                      proc_info.GetProcessID(),
1118                      proc_info.GetParentProcessID(),
1119                      proc_info.GetUserID(),
1120                      proc_info.GetGroupID(),
1121                      proc_info.GetEffectiveUserID(),
1122                      proc_info.GetEffectiveGroupID());
1123     response.PutCString ("name:");
1124     response.PutCStringAsRawHex8(proc_info.GetName());
1125     response.PutChar(';');
1126     const ArchSpec &proc_arch = proc_info.GetArchitecture();
1127     if (proc_arch.IsValid())
1128     {
1129         const llvm::Triple &proc_triple = proc_arch.GetTriple();
1130         response.PutCString("triple:");
1131         response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
1132         response.PutChar(';');
1133     }
1134 }
1135 
1136 void
1137 GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse_DebugServerStyle (
1138     const ProcessInstanceInfo &proc_info, StreamString &response)
1139 {
1140     response.Printf ("pid:%" PRIx64 ";parent-pid:%" PRIx64 ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;",
1141                      proc_info.GetProcessID(),
1142                      proc_info.GetParentProcessID(),
1143                      proc_info.GetUserID(),
1144                      proc_info.GetGroupID(),
1145                      proc_info.GetEffectiveUserID(),
1146                      proc_info.GetEffectiveGroupID());
1147 
1148     const ArchSpec &proc_arch = proc_info.GetArchitecture();
1149     if (proc_arch.IsValid())
1150     {
1151         const llvm::Triple &proc_triple = proc_arch.GetTriple();
1152 #if defined(__APPLE__)
1153         // We'll send cputype/cpusubtype.
1154         const uint32_t cpu_type = proc_arch.GetMachOCPUType();
1155         if (cpu_type != 0)
1156             response.Printf ("cputype:%" PRIx32 ";", cpu_type);
1157 
1158         const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType();
1159         if (cpu_subtype != 0)
1160             response.Printf ("cpusubtype:%" PRIx32 ";", cpu_subtype);
1161 
1162         const std::string vendor = proc_triple.getVendorName ();
1163         if (!vendor.empty ())
1164             response.Printf ("vendor:%s;", vendor.c_str ());
1165 #else
1166         // We'll send the triple.
1167         response.PutCString("triple:");
1168         response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
1169         response.PutChar(';');
1170 #endif
1171         std::string ostype = proc_triple.getOSName ();
1172         // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64.
1173         if (proc_triple.getVendor () == llvm::Triple::Apple)
1174         {
1175             switch (proc_triple.getArch ())
1176             {
1177                 case llvm::Triple::arm:
1178                 case llvm::Triple::aarch64:
1179                     ostype = "ios";
1180                     break;
1181                 default:
1182                     // No change.
1183                     break;
1184             }
1185         }
1186         response.Printf ("ostype:%s;", ostype.c_str ());
1187 
1188 
1189         switch (proc_arch.GetByteOrder ())
1190         {
1191             case lldb::eByteOrderLittle: response.PutCString ("endian:little;"); break;
1192             case lldb::eByteOrderBig:    response.PutCString ("endian:big;");    break;
1193             case lldb::eByteOrderPDP:    response.PutCString ("endian:pdp;");    break;
1194             default:
1195                 // Nothing.
1196                 break;
1197         }
1198 
1199         if (proc_triple.isArch64Bit ())
1200             response.PutCString ("ptrsize:8;");
1201         else if (proc_triple.isArch32Bit ())
1202             response.PutCString ("ptrsize:4;");
1203         else if (proc_triple.isArch16Bit ())
1204             response.PutCString ("ptrsize:2;");
1205     }
1206 }
1207