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         if (error.Success())
850             return SendPacketNoLock ("OK", 2);
851         else
852             return SendErrorResponse(error.GetError());
853     }
854     return SendErrorResponse(20);
855 }
856 
857 GDBRemoteCommunication::PacketResult
858 GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet)
859 {
860     packet.SetFilePos(::strlen("qPlatform_chmod:"));
861 
862     mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
863     if (packet.GetChar() == ',')
864     {
865         std::string path;
866         packet.GetHexByteString(path);
867         Error error = FileSystem::SetFilePermissions(path.c_str(), mode);
868         if (error.Success())
869             return SendPacketNoLock ("OK", 2);
870         else
871             return SendErrorResponse(error.GetError());
872     }
873     return SendErrorResponse(19);
874 }
875 
876 GDBRemoteCommunication::PacketResult
877 GDBRemoteCommunicationServerCommon::Handle_qSupported (StringExtractorGDBRemote &packet)
878 {
879     StreamGDBRemote response;
880 
881     // Features common to lldb-platform and llgs.
882     uint32_t max_packet_size = 128 * 1024;  // 128KBytes is a reasonable max packet size--debugger can always use less
883     response.Printf ("PacketSize=%x", max_packet_size);
884 
885     response.PutCString (";QStartNoAckMode+");
886     response.PutCString (";QThreadSuffixSupported+");
887     response.PutCString (";QListThreadsInStopReply+");
888 #if defined(__linux__)
889     response.PutCString (";qXfer:auxv:read+");
890 #endif
891 
892     return SendPacketNoLock(response.GetData(), response.GetSize());
893 }
894 
895 GDBRemoteCommunication::PacketResult
896 GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported (StringExtractorGDBRemote &packet)
897 {
898     m_thread_suffix_supported = true;
899     return SendOKResponse();
900 }
901 
902 GDBRemoteCommunication::PacketResult
903 GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply (StringExtractorGDBRemote &packet)
904 {
905     m_list_threads_in_stop_reply = true;
906     return SendOKResponse();
907 }
908 
909 GDBRemoteCommunication::PacketResult
910 GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError (StringExtractorGDBRemote &packet)
911 {
912     packet.SetFilePos(::strlen ("QSetDetachOnError:"));
913     if (packet.GetU32(0))
914         m_process_launch_info.GetFlags().Set (eLaunchFlagDetachOnError);
915     else
916         m_process_launch_info.GetFlags().Clear (eLaunchFlagDetachOnError);
917     return SendOKResponse ();
918 }
919 
920 GDBRemoteCommunication::PacketResult
921 GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
922 {
923     // Send response first before changing m_send_acks to we ack this packet
924     PacketResult packet_result = SendOKResponse ();
925     m_send_acks = false;
926     return packet_result;
927 }
928 
929 GDBRemoteCommunication::PacketResult
930 GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
931 {
932     packet.SetFilePos(::strlen ("QSetSTDIN:"));
933     FileAction file_action;
934     std::string path;
935     packet.GetHexByteString(path);
936     const bool read = false;
937     const bool write = true;
938     if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
939     {
940         m_process_launch_info.AppendFileAction(file_action);
941         return SendOKResponse ();
942     }
943     return SendErrorResponse (15);
944 }
945 
946 GDBRemoteCommunication::PacketResult
947 GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
948 {
949     packet.SetFilePos(::strlen ("QSetSTDOUT:"));
950     FileAction file_action;
951     std::string path;
952     packet.GetHexByteString(path);
953     const bool read = true;
954     const bool write = false;
955     if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
956     {
957         m_process_launch_info.AppendFileAction(file_action);
958         return SendOKResponse ();
959     }
960     return SendErrorResponse (16);
961 }
962 
963 GDBRemoteCommunication::PacketResult
964 GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
965 {
966     packet.SetFilePos(::strlen ("QSetSTDERR:"));
967     FileAction file_action;
968     std::string path;
969     packet.GetHexByteString(path);
970     const bool read = true;
971     const bool write = false;
972     if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
973     {
974         m_process_launch_info.AppendFileAction(file_action);
975         return SendOKResponse ();
976     }
977     return SendErrorResponse (17);
978 }
979 
980 GDBRemoteCommunication::PacketResult
981 GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
982 {
983     if (m_process_launch_error.Success())
984         return SendOKResponse();
985     StreamString response;
986     response.PutChar('E');
987     response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
988     return SendPacketNoLock (response.GetData(), response.GetSize());
989 }
990 
991 GDBRemoteCommunication::PacketResult
992 GDBRemoteCommunicationServerCommon::Handle_QEnvironment (StringExtractorGDBRemote &packet)
993 {
994     packet.SetFilePos(::strlen ("QEnvironment:"));
995     const uint32_t bytes_left = packet.GetBytesLeft();
996     if (bytes_left > 0)
997     {
998         m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
999         return SendOKResponse ();
1000     }
1001     return SendErrorResponse (12);
1002 }
1003 
1004 GDBRemoteCommunication::PacketResult
1005 GDBRemoteCommunicationServerCommon::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
1006 {
1007     packet.SetFilePos(::strlen ("QLaunchArch:"));
1008     const uint32_t bytes_left = packet.GetBytesLeft();
1009     if (bytes_left > 0)
1010     {
1011         const char* arch_triple = packet.Peek();
1012         ArchSpec arch_spec(arch_triple,NULL);
1013         m_process_launch_info.SetArchitecture(arch_spec);
1014         return SendOKResponse();
1015     }
1016     return SendErrorResponse(13);
1017 }
1018 
1019 GDBRemoteCommunication::PacketResult
1020 GDBRemoteCommunicationServerCommon::Handle_A (StringExtractorGDBRemote &packet)
1021 {
1022     // The 'A' packet is the most over designed packet ever here with
1023     // redundant argument indexes, redundant argument lengths and needed hex
1024     // encoded argument string values. Really all that is needed is a comma
1025     // separated hex encoded argument value list, but we will stay true to the
1026     // documented version of the 'A' packet here...
1027 
1028     Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
1029     int actual_arg_index = 0;
1030 
1031     packet.SetFilePos(1); // Skip the 'A'
1032     bool success = true;
1033     while (success && packet.GetBytesLeft() > 0)
1034     {
1035         // Decode the decimal argument string length. This length is the
1036         // number of hex nibbles in the argument string value.
1037         const uint32_t arg_len = packet.GetU32(UINT32_MAX);
1038         if (arg_len == UINT32_MAX)
1039             success = false;
1040         else
1041         {
1042             // Make sure the argument hex string length is followed by a comma
1043             if (packet.GetChar() != ',')
1044                 success = false;
1045             else
1046             {
1047                 // Decode the argument index. We ignore this really because
1048                 // who would really send down the arguments in a random order???
1049                 const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
1050                 if (arg_idx == UINT32_MAX)
1051                     success = false;
1052                 else
1053                 {
1054                     // Make sure the argument index is followed by a comma
1055                     if (packet.GetChar() != ',')
1056                         success = false;
1057                     else
1058                     {
1059                         // Decode the argument string value from hex bytes
1060                         // back into a UTF8 string and make sure the length
1061                         // matches the one supplied in the packet
1062                         std::string arg;
1063                         if (packet.GetHexByteStringFixedLength(arg, arg_len) != (arg_len / 2))
1064                             success = false;
1065                         else
1066                         {
1067                             // If there are any bytes left
1068                             if (packet.GetBytesLeft())
1069                             {
1070                                 if (packet.GetChar() != ',')
1071                                     success = false;
1072                             }
1073 
1074                             if (success)
1075                             {
1076                                 if (arg_idx == 0)
1077                                     m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
1078                                 m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
1079                                 if (log)
1080                                     log->Printf ("LLGSPacketHandler::%s added arg %d: \"%s\"", __FUNCTION__, actual_arg_index, arg.c_str ());
1081                                 ++actual_arg_index;
1082                             }
1083                         }
1084                     }
1085                 }
1086             }
1087         }
1088     }
1089 
1090     if (success)
1091     {
1092         m_process_launch_error = LaunchProcess ();
1093         if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
1094         {
1095             return SendOKResponse ();
1096         }
1097         else
1098         {
1099             Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
1100             if (log)
1101                 log->Printf("LLGSPacketHandler::%s failed to launch exe: %s",
1102                         __FUNCTION__,
1103                         m_process_launch_error.AsCString());
1104 
1105         }
1106     }
1107     return SendErrorResponse (8);
1108 }
1109 
1110 void
1111 GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info,
1112                                                     StreamString &response)
1113 {
1114     response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
1115                      proc_info.GetProcessID(),
1116                      proc_info.GetParentProcessID(),
1117                      proc_info.GetUserID(),
1118                      proc_info.GetGroupID(),
1119                      proc_info.GetEffectiveUserID(),
1120                      proc_info.GetEffectiveGroupID());
1121     response.PutCString ("name:");
1122     response.PutCStringAsRawHex8(proc_info.GetName());
1123     response.PutChar(';');
1124     const ArchSpec &proc_arch = proc_info.GetArchitecture();
1125     if (proc_arch.IsValid())
1126     {
1127         const llvm::Triple &proc_triple = proc_arch.GetTriple();
1128         response.PutCString("triple:");
1129         response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
1130         response.PutChar(';');
1131     }
1132 }
1133 
1134 void
1135 GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse_DebugServerStyle (
1136     const ProcessInstanceInfo &proc_info, StreamString &response)
1137 {
1138     response.Printf ("pid:%" PRIx64 ";parent-pid:%" PRIx64 ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;",
1139                      proc_info.GetProcessID(),
1140                      proc_info.GetParentProcessID(),
1141                      proc_info.GetUserID(),
1142                      proc_info.GetGroupID(),
1143                      proc_info.GetEffectiveUserID(),
1144                      proc_info.GetEffectiveGroupID());
1145 
1146     const ArchSpec &proc_arch = proc_info.GetArchitecture();
1147     if (proc_arch.IsValid())
1148     {
1149         const llvm::Triple &proc_triple = proc_arch.GetTriple();
1150 #if defined(__APPLE__)
1151         // We'll send cputype/cpusubtype.
1152         const uint32_t cpu_type = proc_arch.GetMachOCPUType();
1153         if (cpu_type != 0)
1154             response.Printf ("cputype:%" PRIx32 ";", cpu_type);
1155 
1156         const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType();
1157         if (cpu_subtype != 0)
1158             response.Printf ("cpusubtype:%" PRIx32 ";", cpu_subtype);
1159 
1160         const std::string vendor = proc_triple.getVendorName ();
1161         if (!vendor.empty ())
1162             response.Printf ("vendor:%s;", vendor.c_str ());
1163 #else
1164         // We'll send the triple.
1165         response.PutCString("triple:");
1166         response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
1167         response.PutChar(';');
1168 #endif
1169         std::string ostype = proc_triple.getOSName ();
1170         // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64.
1171         if (proc_triple.getVendor () == llvm::Triple::Apple)
1172         {
1173             switch (proc_triple.getArch ())
1174             {
1175                 case llvm::Triple::arm:
1176                 case llvm::Triple::aarch64:
1177                     ostype = "ios";
1178                     break;
1179                 default:
1180                     // No change.
1181                     break;
1182             }
1183         }
1184         response.Printf ("ostype:%s;", ostype.c_str ());
1185 
1186 
1187         switch (proc_arch.GetByteOrder ())
1188         {
1189             case lldb::eByteOrderLittle: response.PutCString ("endian:little;"); break;
1190             case lldb::eByteOrderBig:    response.PutCString ("endian:big;");    break;
1191             case lldb::eByteOrderPDP:    response.PutCString ("endian:pdp;");    break;
1192             default:
1193                 // Nothing.
1194                 break;
1195         }
1196 
1197         if (proc_triple.isArch64Bit ())
1198             response.PutCString ("ptrsize:8;");
1199         else if (proc_triple.isArch32Bit ())
1200             response.PutCString ("ptrsize:4;");
1201         else if (proc_triple.isArch16Bit ())
1202             response.PutCString ("ptrsize:2;");
1203     }
1204 }
1205