1 //===-- PlatformDarwin.cpp ------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "PlatformDarwin.h"
10 
11 #include <string.h>
12 
13 #include <algorithm>
14 #include <memory>
15 #include <mutex>
16 
17 #include "lldb/Breakpoint/BreakpointLocation.h"
18 #include "lldb/Breakpoint/BreakpointSite.h"
19 #include "lldb/Core/Debugger.h"
20 #include "lldb/Core/Module.h"
21 #include "lldb/Core/ModuleSpec.h"
22 #include "lldb/Core/Section.h"
23 #include "lldb/Host/Host.h"
24 #include "lldb/Host/HostInfo.h"
25 #include "lldb/Host/XML.h"
26 #include "lldb/Interpreter/CommandInterpreter.h"
27 #include "lldb/Symbol/LocateSymbolFile.h"
28 #include "lldb/Symbol/ObjectFile.h"
29 #include "lldb/Symbol/SymbolFile.h"
30 #include "lldb/Symbol/SymbolVendor.h"
31 #include "lldb/Target/Platform.h"
32 #include "lldb/Target/Process.h"
33 #include "lldb/Target/Target.h"
34 #include "lldb/Utility/Log.h"
35 #include "lldb/Utility/ProcessInfo.h"
36 #include "lldb/Utility/Status.h"
37 #include "lldb/Utility/Timer.h"
38 #include "llvm/ADT/STLExtras.h"
39 #include "llvm/Support/FileSystem.h"
40 #include "llvm/Support/Threading.h"
41 #include "llvm/Support/VersionTuple.h"
42 
43 #if defined(__APPLE__)
44 #include <TargetConditionals.h>
45 #endif
46 
47 using namespace lldb;
48 using namespace lldb_private;
49 
50 /// Default Constructor
51 PlatformDarwin::PlatformDarwin(bool is_host) : PlatformPOSIX(is_host) {}
52 
53 /// Destructor.
54 ///
55 /// The destructor is virtual since this class is designed to be
56 /// inherited from by the plug-in instance.
57 PlatformDarwin::~PlatformDarwin() {}
58 
59 lldb_private::Status
60 PlatformDarwin::PutFile(const lldb_private::FileSpec &source,
61                         const lldb_private::FileSpec &destination, uint32_t uid,
62                         uint32_t gid) {
63   // Unconditionally unlink the destination. If it is an executable,
64   // simply opening it and truncating its contents would invalidate
65   // its cached code signature.
66   Unlink(destination);
67   return PlatformPOSIX::PutFile(source, destination, uid, gid);
68 }
69 
70 FileSpecList PlatformDarwin::LocateExecutableScriptingResources(
71     Target *target, Module &module, Stream *feedback_stream) {
72   FileSpecList file_list;
73   if (target &&
74       target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython) {
75     // NB some extensions might be meaningful and should not be stripped -
76     // "this.binary.file"
77     // should not lose ".file" but GetFileNameStrippingExtension() will do
78     // precisely that. Ideally, we should have a per-platform list of
79     // extensions (".exe", ".app", ".dSYM", ".framework") which should be
80     // stripped while leaving "this.binary.file" as-is.
81 
82     FileSpec module_spec = module.GetFileSpec();
83 
84     if (module_spec) {
85       if (SymbolFile *symfile = module.GetSymbolFile()) {
86         ObjectFile *objfile = symfile->GetObjectFile();
87         if (objfile) {
88           FileSpec symfile_spec(objfile->GetFileSpec());
89           if (symfile_spec &&
90               strcasestr(symfile_spec.GetPath().c_str(),
91                          ".dSYM/Contents/Resources/DWARF") != nullptr &&
92               FileSystem::Instance().Exists(symfile_spec)) {
93             while (module_spec.GetFilename()) {
94               std::string module_basename(
95                   module_spec.GetFilename().GetCString());
96               std::string original_module_basename(module_basename);
97 
98               bool was_keyword = false;
99 
100               // FIXME: for Python, we cannot allow certain characters in
101               // module
102               // filenames we import. Theoretically, different scripting
103               // languages may have different sets of forbidden tokens in
104               // filenames, and that should be dealt with by each
105               // ScriptInterpreter. For now, we just replace dots with
106               // underscores, but if we ever support anything other than
107               // Python we will need to rework this
108               std::replace(module_basename.begin(), module_basename.end(), '.',
109                            '_');
110               std::replace(module_basename.begin(), module_basename.end(), ' ',
111                            '_');
112               std::replace(module_basename.begin(), module_basename.end(), '-',
113                            '_');
114               ScriptInterpreter *script_interpreter =
115                   target->GetDebugger().GetScriptInterpreter();
116               if (script_interpreter &&
117                   script_interpreter->IsReservedWord(module_basename.c_str())) {
118                 module_basename.insert(module_basename.begin(), '_');
119                 was_keyword = true;
120               }
121 
122               StreamString path_string;
123               StreamString original_path_string;
124               // for OSX we are going to be in
125               // .dSYM/Contents/Resources/DWARF/<basename> let us go to
126               // .dSYM/Contents/Resources/Python/<basename>.py and see if the
127               // file exists
128               path_string.Printf("%s/../Python/%s.py",
129                                  symfile_spec.GetDirectory().GetCString(),
130                                  module_basename.c_str());
131               original_path_string.Printf(
132                   "%s/../Python/%s.py",
133                   symfile_spec.GetDirectory().GetCString(),
134                   original_module_basename.c_str());
135               FileSpec script_fspec(path_string.GetString());
136               FileSystem::Instance().Resolve(script_fspec);
137               FileSpec orig_script_fspec(original_path_string.GetString());
138               FileSystem::Instance().Resolve(orig_script_fspec);
139 
140               // if we did some replacements of reserved characters, and a
141               // file with the untampered name exists, then warn the user
142               // that the file as-is shall not be loaded
143               if (feedback_stream) {
144                 if (module_basename != original_module_basename &&
145                     FileSystem::Instance().Exists(orig_script_fspec)) {
146                   const char *reason_for_complaint =
147                       was_keyword ? "conflicts with a keyword"
148                                   : "contains reserved characters";
149                   if (FileSystem::Instance().Exists(script_fspec))
150                     feedback_stream->Printf(
151                         "warning: the symbol file '%s' contains a debug "
152                         "script. However, its name"
153                         " '%s' %s and as such cannot be loaded. LLDB will"
154                         " load '%s' instead. Consider removing the file with "
155                         "the malformed name to"
156                         " eliminate this warning.\n",
157                         symfile_spec.GetPath().c_str(),
158                         original_path_string.GetData(), reason_for_complaint,
159                         path_string.GetData());
160                   else
161                     feedback_stream->Printf(
162                         "warning: the symbol file '%s' contains a debug "
163                         "script. However, its name"
164                         " %s and as such cannot be loaded. If you intend"
165                         " to have this script loaded, please rename '%s' to "
166                         "'%s' and retry.\n",
167                         symfile_spec.GetPath().c_str(), reason_for_complaint,
168                         original_path_string.GetData(), path_string.GetData());
169                 }
170               }
171 
172               if (FileSystem::Instance().Exists(script_fspec)) {
173                 file_list.Append(script_fspec);
174                 break;
175               }
176 
177               // If we didn't find the python file, then keep stripping the
178               // extensions and try again
179               ConstString filename_no_extension(
180                   module_spec.GetFileNameStrippingExtension());
181               if (module_spec.GetFilename() == filename_no_extension)
182                 break;
183 
184               module_spec.GetFilename() = filename_no_extension;
185             }
186           }
187         }
188       }
189     }
190   }
191   return file_list;
192 }
193 
194 Status PlatformDarwin::ResolveSymbolFile(Target &target,
195                                          const ModuleSpec &sym_spec,
196                                          FileSpec &sym_file) {
197   sym_file = sym_spec.GetSymbolFileSpec();
198   if (FileSystem::Instance().IsDirectory(sym_file)) {
199     sym_file = Symbols::FindSymbolFileInBundle(sym_file, sym_spec.GetUUIDPtr(),
200                                                sym_spec.GetArchitecturePtr());
201   }
202   return {};
203 }
204 
205 static lldb_private::Status
206 MakeCacheFolderForFile(const FileSpec &module_cache_spec) {
207   FileSpec module_cache_folder =
208       module_cache_spec.CopyByRemovingLastPathComponent();
209   return llvm::sys::fs::create_directory(module_cache_folder.GetPath());
210 }
211 
212 static lldb_private::Status
213 BringInRemoteFile(Platform *platform,
214                   const lldb_private::ModuleSpec &module_spec,
215                   const FileSpec &module_cache_spec) {
216   MakeCacheFolderForFile(module_cache_spec);
217   Status err = platform->GetFile(module_spec.GetFileSpec(), module_cache_spec);
218   return err;
219 }
220 
221 lldb_private::Status PlatformDarwin::GetSharedModuleWithLocalCache(
222     const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp,
223     const lldb_private::FileSpecList *module_search_paths_ptr,
224     lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr) {
225 
226   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
227   LLDB_LOGF(log,
228             "[%s] Trying to find module %s/%s - platform path %s/%s symbol "
229             "path %s/%s",
230             (IsHost() ? "host" : "remote"),
231             module_spec.GetFileSpec().GetDirectory().AsCString(),
232             module_spec.GetFileSpec().GetFilename().AsCString(),
233             module_spec.GetPlatformFileSpec().GetDirectory().AsCString(),
234             module_spec.GetPlatformFileSpec().GetFilename().AsCString(),
235             module_spec.GetSymbolFileSpec().GetDirectory().AsCString(),
236             module_spec.GetSymbolFileSpec().GetFilename().AsCString());
237 
238   Status err;
239 
240   err = ModuleList::GetSharedModule(module_spec, module_sp,
241                                     module_search_paths_ptr, old_module_sp_ptr,
242                                     did_create_ptr);
243   if (module_sp)
244     return err;
245 
246   if (!IsHost()) {
247     std::string cache_path(GetLocalCacheDirectory());
248     // Only search for a locally cached file if we have a valid cache path
249     if (!cache_path.empty()) {
250       std::string module_path(module_spec.GetFileSpec().GetPath());
251       cache_path.append(module_path);
252       FileSpec module_cache_spec(cache_path);
253 
254       // if rsync is supported, always bring in the file - rsync will be very
255       // efficient when files are the same on the local and remote end of the
256       // connection
257       if (this->GetSupportsRSync()) {
258         err = BringInRemoteFile(this, module_spec, module_cache_spec);
259         if (err.Fail())
260           return err;
261         if (FileSystem::Instance().Exists(module_cache_spec)) {
262           Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
263           LLDB_LOGF(log, "[%s] module %s/%s was rsynced and is now there",
264                     (IsHost() ? "host" : "remote"),
265                     module_spec.GetFileSpec().GetDirectory().AsCString(),
266                     module_spec.GetFileSpec().GetFilename().AsCString());
267           ModuleSpec local_spec(module_cache_spec,
268                                 module_spec.GetArchitecture());
269           module_sp = std::make_shared<Module>(local_spec);
270           module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
271           return Status();
272         }
273       }
274 
275       // try to find the module in the cache
276       if (FileSystem::Instance().Exists(module_cache_spec)) {
277         // get the local and remote MD5 and compare
278         if (m_remote_platform_sp) {
279           // when going over the *slow* GDB remote transfer mechanism we first
280           // check the hashes of the files - and only do the actual transfer if
281           // they differ
282           uint64_t high_local, high_remote, low_local, low_remote;
283           auto MD5 = llvm::sys::fs::md5_contents(module_cache_spec.GetPath());
284           if (!MD5)
285             return Status(MD5.getError());
286           std::tie(high_local, low_local) = MD5->words();
287 
288           m_remote_platform_sp->CalculateMD5(module_spec.GetFileSpec(),
289                                              low_remote, high_remote);
290           if (low_local != low_remote || high_local != high_remote) {
291             // bring in the remote file
292             Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
293             LLDB_LOGF(log,
294                       "[%s] module %s/%s needs to be replaced from remote copy",
295                       (IsHost() ? "host" : "remote"),
296                       module_spec.GetFileSpec().GetDirectory().AsCString(),
297                       module_spec.GetFileSpec().GetFilename().AsCString());
298             Status err =
299                 BringInRemoteFile(this, module_spec, module_cache_spec);
300             if (err.Fail())
301               return err;
302           }
303         }
304 
305         ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
306         module_sp = std::make_shared<Module>(local_spec);
307         module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
308         Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
309         LLDB_LOGF(log, "[%s] module %s/%s was found in the cache",
310                   (IsHost() ? "host" : "remote"),
311                   module_spec.GetFileSpec().GetDirectory().AsCString(),
312                   module_spec.GetFileSpec().GetFilename().AsCString());
313         return Status();
314       }
315 
316       // bring in the remote module file
317       LLDB_LOGF(log, "[%s] module %s/%s needs to come in remotely",
318                 (IsHost() ? "host" : "remote"),
319                 module_spec.GetFileSpec().GetDirectory().AsCString(),
320                 module_spec.GetFileSpec().GetFilename().AsCString());
321       Status err = BringInRemoteFile(this, module_spec, module_cache_spec);
322       if (err.Fail())
323         return err;
324       if (FileSystem::Instance().Exists(module_cache_spec)) {
325         Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
326         LLDB_LOGF(log, "[%s] module %s/%s is now cached and fine",
327                   (IsHost() ? "host" : "remote"),
328                   module_spec.GetFileSpec().GetDirectory().AsCString(),
329                   module_spec.GetFileSpec().GetFilename().AsCString());
330         ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
331         module_sp = std::make_shared<Module>(local_spec);
332         module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
333         return Status();
334       } else
335         return Status("unable to obtain valid module file");
336     } else
337       return Status("no cache path");
338   } else
339     return Status("unable to resolve module");
340 }
341 
342 Status PlatformDarwin::GetSharedModule(
343     const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
344     const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
345     bool *did_create_ptr) {
346   Status error;
347   module_sp.reset();
348 
349   if (IsRemote()) {
350     // If we have a remote platform always, let it try and locate the shared
351     // module first.
352     if (m_remote_platform_sp) {
353       error = m_remote_platform_sp->GetSharedModule(
354           module_spec, process, module_sp, module_search_paths_ptr,
355           old_module_sp_ptr, did_create_ptr);
356     }
357   }
358 
359   if (!module_sp) {
360     // Fall back to the local platform and find the file locally
361     error = Platform::GetSharedModule(module_spec, process, module_sp,
362                                       module_search_paths_ptr,
363                                       old_module_sp_ptr, did_create_ptr);
364 
365     const FileSpec &platform_file = module_spec.GetFileSpec();
366     if (!module_sp && module_search_paths_ptr && platform_file) {
367       // We can try to pull off part of the file path up to the bundle
368       // directory level and try any module search paths...
369       FileSpec bundle_directory;
370       if (Host::GetBundleDirectory(platform_file, bundle_directory)) {
371         if (platform_file == bundle_directory) {
372           ModuleSpec new_module_spec(module_spec);
373           new_module_spec.GetFileSpec() = bundle_directory;
374           if (Host::ResolveExecutableInBundle(new_module_spec.GetFileSpec())) {
375             Status new_error(Platform::GetSharedModule(
376                 new_module_spec, process, module_sp, nullptr, old_module_sp_ptr,
377                 did_create_ptr));
378 
379             if (module_sp)
380               return new_error;
381           }
382         } else {
383           char platform_path[PATH_MAX];
384           char bundle_dir[PATH_MAX];
385           platform_file.GetPath(platform_path, sizeof(platform_path));
386           const size_t bundle_directory_len =
387               bundle_directory.GetPath(bundle_dir, sizeof(bundle_dir));
388           char new_path[PATH_MAX];
389           size_t num_module_search_paths = module_search_paths_ptr->GetSize();
390           for (size_t i = 0; i < num_module_search_paths; ++i) {
391             const size_t search_path_len =
392                 module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(
393                     new_path, sizeof(new_path));
394             if (search_path_len < sizeof(new_path)) {
395               snprintf(new_path + search_path_len,
396                        sizeof(new_path) - search_path_len, "/%s",
397                        platform_path + bundle_directory_len);
398               FileSpec new_file_spec(new_path);
399               if (FileSystem::Instance().Exists(new_file_spec)) {
400                 ModuleSpec new_module_spec(module_spec);
401                 new_module_spec.GetFileSpec() = new_file_spec;
402                 Status new_error(Platform::GetSharedModule(
403                     new_module_spec, process, module_sp, nullptr,
404                     old_module_sp_ptr, did_create_ptr));
405 
406                 if (module_sp) {
407                   module_sp->SetPlatformFileSpec(new_file_spec);
408                   return new_error;
409                 }
410               }
411             }
412           }
413         }
414       }
415     }
416   }
417   if (module_sp)
418     module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
419   return error;
420 }
421 
422 size_t
423 PlatformDarwin::GetSoftwareBreakpointTrapOpcode(Target &target,
424                                                 BreakpointSite *bp_site) {
425   const uint8_t *trap_opcode = nullptr;
426   uint32_t trap_opcode_size = 0;
427   bool bp_is_thumb = false;
428 
429   llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();
430   switch (machine) {
431   case llvm::Triple::aarch64_32:
432   case llvm::Triple::aarch64: {
433     // 'brk #0' or 0xd4200000 in BE byte order
434     static const uint8_t g_arm64_breakpoint_opcode[] = {0x00, 0x00, 0x20, 0xD4};
435     trap_opcode = g_arm64_breakpoint_opcode;
436     trap_opcode_size = sizeof(g_arm64_breakpoint_opcode);
437   } break;
438 
439   case llvm::Triple::thumb:
440     bp_is_thumb = true;
441     LLVM_FALLTHROUGH;
442   case llvm::Triple::arm: {
443     static const uint8_t g_arm_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7};
444     static const uint8_t g_thumb_breakpooint_opcode[] = {0xFE, 0xDE};
445 
446     // Auto detect arm/thumb if it wasn't explicitly specified
447     if (!bp_is_thumb) {
448       lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
449       if (bp_loc_sp)
450         bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass() ==
451                       AddressClass::eCodeAlternateISA;
452     }
453     if (bp_is_thumb) {
454       trap_opcode = g_thumb_breakpooint_opcode;
455       trap_opcode_size = sizeof(g_thumb_breakpooint_opcode);
456       break;
457     }
458     trap_opcode = g_arm_breakpoint_opcode;
459     trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
460   } break;
461 
462   case llvm::Triple::ppc:
463   case llvm::Triple::ppc64: {
464     static const uint8_t g_ppc_breakpoint_opcode[] = {0x7F, 0xC0, 0x00, 0x08};
465     trap_opcode = g_ppc_breakpoint_opcode;
466     trap_opcode_size = sizeof(g_ppc_breakpoint_opcode);
467   } break;
468 
469   default:
470     return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
471   }
472 
473   if (trap_opcode && trap_opcode_size) {
474     if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
475       return trap_opcode_size;
476   }
477   return 0;
478 }
479 
480 bool PlatformDarwin::ModuleIsExcludedForUnconstrainedSearches(
481     lldb_private::Target &target, const lldb::ModuleSP &module_sp) {
482   if (!module_sp)
483     return false;
484 
485   ObjectFile *obj_file = module_sp->GetObjectFile();
486   if (!obj_file)
487     return false;
488 
489   ObjectFile::Type obj_type = obj_file->GetType();
490   return obj_type == ObjectFile::eTypeDynamicLinker;
491 }
492 
493 bool PlatformDarwin::x86GetSupportedArchitectureAtIndex(uint32_t idx,
494                                                         ArchSpec &arch) {
495   ArchSpec host_arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
496   if (host_arch.GetCore() == ArchSpec::eCore_x86_64_x86_64h) {
497     switch (idx) {
498     case 0:
499       arch = host_arch;
500       return true;
501 
502     case 1:
503       arch.SetTriple("x86_64-apple-macosx");
504       return true;
505 
506     case 2:
507       arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
508       return true;
509 
510     default:
511       return false;
512     }
513   } else {
514     if (idx == 0) {
515       arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
516       return arch.IsValid();
517     } else if (idx == 1) {
518       ArchSpec platform_arch(
519           HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
520       ArchSpec platform_arch64(
521           HostInfo::GetArchitecture(HostInfo::eArchKind64));
522       if (platform_arch.IsExactMatch(platform_arch64)) {
523         // This macosx platform supports both 32 and 64 bit. Since we already
524         // returned the 64 bit arch for idx == 0, return the 32 bit arch for
525         // idx == 1
526         arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
527         return arch.IsValid();
528       }
529     }
530   }
531   return false;
532 }
533 
534 // The architecture selection rules for arm processors These cpu subtypes have
535 // distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f
536 // processor.
537 
538 bool PlatformDarwin::ARMGetSupportedArchitectureAtIndex(uint32_t idx,
539                                                         ArchSpec &arch) {
540   ArchSpec system_arch(GetSystemArchitecture());
541 
542 // When lldb is running on a watch or tv, set the arch OS name appropriately.
543 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
544 #define OSNAME "tvos"
545 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
546 #define OSNAME "watchos"
547 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
548 #define OSNAME "bridgeos"
549 #else
550 #define OSNAME "ios"
551 #endif
552 
553   const ArchSpec::Core system_core = system_arch.GetCore();
554   switch (system_core) {
555   default:
556     switch (idx) {
557     case 0:
558       arch.SetTriple("arm64-apple-" OSNAME);
559       return true;
560     case 1:
561       arch.SetTriple("armv7-apple-" OSNAME);
562       return true;
563     case 2:
564       arch.SetTriple("armv7f-apple-" OSNAME);
565       return true;
566     case 3:
567       arch.SetTriple("armv7k-apple-" OSNAME);
568       return true;
569     case 4:
570       arch.SetTriple("armv7s-apple-" OSNAME);
571       return true;
572     case 5:
573       arch.SetTriple("armv7m-apple-" OSNAME);
574       return true;
575     case 6:
576       arch.SetTriple("armv7em-apple-" OSNAME);
577       return true;
578     case 7:
579       arch.SetTriple("armv6m-apple-" OSNAME);
580       return true;
581     case 8:
582       arch.SetTriple("armv6-apple-" OSNAME);
583       return true;
584     case 9:
585       arch.SetTriple("armv5-apple-" OSNAME);
586       return true;
587     case 10:
588       arch.SetTriple("armv4-apple-" OSNAME);
589       return true;
590     case 11:
591       arch.SetTriple("arm-apple-" OSNAME);
592       return true;
593     case 12:
594       arch.SetTriple("thumbv7-apple-" OSNAME);
595       return true;
596     case 13:
597       arch.SetTriple("thumbv7f-apple-" OSNAME);
598       return true;
599     case 14:
600       arch.SetTriple("thumbv7k-apple-" OSNAME);
601       return true;
602     case 15:
603       arch.SetTriple("thumbv7s-apple-" OSNAME);
604       return true;
605     case 16:
606       arch.SetTriple("thumbv7m-apple-" OSNAME);
607       return true;
608     case 17:
609       arch.SetTriple("thumbv7em-apple-" OSNAME);
610       return true;
611     case 18:
612       arch.SetTriple("thumbv6m-apple-" OSNAME);
613       return true;
614     case 19:
615       arch.SetTriple("thumbv6-apple-" OSNAME);
616       return true;
617     case 20:
618       arch.SetTriple("thumbv5-apple-" OSNAME);
619       return true;
620     case 21:
621       arch.SetTriple("thumbv4t-apple-" OSNAME);
622       return true;
623     case 22:
624       arch.SetTriple("thumb-apple-" OSNAME);
625       return true;
626     default:
627       break;
628     }
629     break;
630 
631   case ArchSpec::eCore_arm_arm64:
632     switch (idx) {
633     case 0:
634       arch.SetTriple("arm64-apple-" OSNAME);
635       return true;
636     case 1:
637       arch.SetTriple("armv7s-apple-" OSNAME);
638       return true;
639     case 2:
640       arch.SetTriple("armv7f-apple-" OSNAME);
641       return true;
642     case 3:
643       arch.SetTriple("armv7m-apple-" OSNAME);
644       return true;
645     case 4:
646       arch.SetTriple("armv7em-apple-" OSNAME);
647       return true;
648     case 5:
649       arch.SetTriple("armv7-apple-" OSNAME);
650       return true;
651     case 6:
652       arch.SetTriple("armv6m-apple-" OSNAME);
653       return true;
654     case 7:
655       arch.SetTriple("armv6-apple-" OSNAME);
656       return true;
657     case 8:
658       arch.SetTriple("armv5-apple-" OSNAME);
659       return true;
660     case 9:
661       arch.SetTriple("armv4-apple-" OSNAME);
662       return true;
663     case 10:
664       arch.SetTriple("arm-apple-" OSNAME);
665       return true;
666     case 11:
667       arch.SetTriple("thumbv7-apple-" OSNAME);
668       return true;
669     case 12:
670       arch.SetTriple("thumbv7f-apple-" OSNAME);
671       return true;
672     case 13:
673       arch.SetTriple("thumbv7k-apple-" OSNAME);
674       return true;
675     case 14:
676       arch.SetTriple("thumbv7s-apple-" OSNAME);
677       return true;
678     case 15:
679       arch.SetTriple("thumbv7m-apple-" OSNAME);
680       return true;
681     case 16:
682       arch.SetTriple("thumbv7em-apple-" OSNAME);
683       return true;
684     case 17:
685       arch.SetTriple("thumbv6m-apple-" OSNAME);
686       return true;
687     case 18:
688       arch.SetTriple("thumbv6-apple-" OSNAME);
689       return true;
690     case 19:
691       arch.SetTriple("thumbv5-apple-" OSNAME);
692       return true;
693     case 20:
694       arch.SetTriple("thumbv4t-apple-" OSNAME);
695       return true;
696     case 21:
697       arch.SetTriple("thumb-apple-" OSNAME);
698       return true;
699     default:
700       break;
701     }
702     break;
703 
704   case ArchSpec::eCore_arm_armv7f:
705     switch (idx) {
706     case 0:
707       arch.SetTriple("armv7f-apple-" OSNAME);
708       return true;
709     case 1:
710       arch.SetTriple("armv7-apple-" OSNAME);
711       return true;
712     case 2:
713       arch.SetTriple("armv6m-apple-" OSNAME);
714       return true;
715     case 3:
716       arch.SetTriple("armv6-apple-" OSNAME);
717       return true;
718     case 4:
719       arch.SetTriple("armv5-apple-" OSNAME);
720       return true;
721     case 5:
722       arch.SetTriple("armv4-apple-" OSNAME);
723       return true;
724     case 6:
725       arch.SetTriple("arm-apple-" OSNAME);
726       return true;
727     case 7:
728       arch.SetTriple("thumbv7f-apple-" OSNAME);
729       return true;
730     case 8:
731       arch.SetTriple("thumbv7-apple-" OSNAME);
732       return true;
733     case 9:
734       arch.SetTriple("thumbv6m-apple-" OSNAME);
735       return true;
736     case 10:
737       arch.SetTriple("thumbv6-apple-" OSNAME);
738       return true;
739     case 11:
740       arch.SetTriple("thumbv5-apple-" OSNAME);
741       return true;
742     case 12:
743       arch.SetTriple("thumbv4t-apple-" OSNAME);
744       return true;
745     case 13:
746       arch.SetTriple("thumb-apple-" OSNAME);
747       return true;
748     default:
749       break;
750     }
751     break;
752 
753   case ArchSpec::eCore_arm_armv7k:
754     switch (idx) {
755     case 0:
756       arch.SetTriple("armv7k-apple-" OSNAME);
757       return true;
758     case 1:
759       arch.SetTriple("armv7-apple-" OSNAME);
760       return true;
761     case 2:
762       arch.SetTriple("armv6m-apple-" OSNAME);
763       return true;
764     case 3:
765       arch.SetTriple("armv6-apple-" OSNAME);
766       return true;
767     case 4:
768       arch.SetTriple("armv5-apple-" OSNAME);
769       return true;
770     case 5:
771       arch.SetTriple("armv4-apple-" OSNAME);
772       return true;
773     case 6:
774       arch.SetTriple("arm-apple-" OSNAME);
775       return true;
776     case 7:
777       arch.SetTriple("thumbv7k-apple-" OSNAME);
778       return true;
779     case 8:
780       arch.SetTriple("thumbv7-apple-" OSNAME);
781       return true;
782     case 9:
783       arch.SetTriple("thumbv6m-apple-" OSNAME);
784       return true;
785     case 10:
786       arch.SetTriple("thumbv6-apple-" OSNAME);
787       return true;
788     case 11:
789       arch.SetTriple("thumbv5-apple-" OSNAME);
790       return true;
791     case 12:
792       arch.SetTriple("thumbv4t-apple-" OSNAME);
793       return true;
794     case 13:
795       arch.SetTriple("thumb-apple-" OSNAME);
796       return true;
797     default:
798       break;
799     }
800     break;
801 
802   case ArchSpec::eCore_arm_armv7s:
803     switch (idx) {
804     case 0:
805       arch.SetTriple("armv7s-apple-" OSNAME);
806       return true;
807     case 1:
808       arch.SetTriple("armv7-apple-" OSNAME);
809       return true;
810     case 2:
811       arch.SetTriple("armv6m-apple-" OSNAME);
812       return true;
813     case 3:
814       arch.SetTriple("armv6-apple-" OSNAME);
815       return true;
816     case 4:
817       arch.SetTriple("armv5-apple-" OSNAME);
818       return true;
819     case 5:
820       arch.SetTriple("armv4-apple-" OSNAME);
821       return true;
822     case 6:
823       arch.SetTriple("arm-apple-" OSNAME);
824       return true;
825     case 7:
826       arch.SetTriple("thumbv7s-apple-" OSNAME);
827       return true;
828     case 8:
829       arch.SetTriple("thumbv7-apple-" OSNAME);
830       return true;
831     case 9:
832       arch.SetTriple("thumbv6m-apple-" OSNAME);
833       return true;
834     case 10:
835       arch.SetTriple("thumbv6-apple-" OSNAME);
836       return true;
837     case 11:
838       arch.SetTriple("thumbv5-apple-" OSNAME);
839       return true;
840     case 12:
841       arch.SetTriple("thumbv4t-apple-" OSNAME);
842       return true;
843     case 13:
844       arch.SetTriple("thumb-apple-" OSNAME);
845       return true;
846     default:
847       break;
848     }
849     break;
850 
851   case ArchSpec::eCore_arm_armv7m:
852     switch (idx) {
853     case 0:
854       arch.SetTriple("armv7m-apple-" OSNAME);
855       return true;
856     case 1:
857       arch.SetTriple("armv7-apple-" OSNAME);
858       return true;
859     case 2:
860       arch.SetTriple("armv6m-apple-" OSNAME);
861       return true;
862     case 3:
863       arch.SetTriple("armv6-apple-" OSNAME);
864       return true;
865     case 4:
866       arch.SetTriple("armv5-apple-" OSNAME);
867       return true;
868     case 5:
869       arch.SetTriple("armv4-apple-" OSNAME);
870       return true;
871     case 6:
872       arch.SetTriple("arm-apple-" OSNAME);
873       return true;
874     case 7:
875       arch.SetTriple("thumbv7m-apple-" OSNAME);
876       return true;
877     case 8:
878       arch.SetTriple("thumbv7-apple-" OSNAME);
879       return true;
880     case 9:
881       arch.SetTriple("thumbv6m-apple-" OSNAME);
882       return true;
883     case 10:
884       arch.SetTriple("thumbv6-apple-" OSNAME);
885       return true;
886     case 11:
887       arch.SetTriple("thumbv5-apple-" OSNAME);
888       return true;
889     case 12:
890       arch.SetTriple("thumbv4t-apple-" OSNAME);
891       return true;
892     case 13:
893       arch.SetTriple("thumb-apple-" OSNAME);
894       return true;
895     default:
896       break;
897     }
898     break;
899 
900   case ArchSpec::eCore_arm_armv7em:
901     switch (idx) {
902     case 0:
903       arch.SetTriple("armv7em-apple-" OSNAME);
904       return true;
905     case 1:
906       arch.SetTriple("armv7-apple-" OSNAME);
907       return true;
908     case 2:
909       arch.SetTriple("armv6m-apple-" OSNAME);
910       return true;
911     case 3:
912       arch.SetTriple("armv6-apple-" OSNAME);
913       return true;
914     case 4:
915       arch.SetTriple("armv5-apple-" OSNAME);
916       return true;
917     case 5:
918       arch.SetTriple("armv4-apple-" OSNAME);
919       return true;
920     case 6:
921       arch.SetTriple("arm-apple-" OSNAME);
922       return true;
923     case 7:
924       arch.SetTriple("thumbv7em-apple-" OSNAME);
925       return true;
926     case 8:
927       arch.SetTriple("thumbv7-apple-" OSNAME);
928       return true;
929     case 9:
930       arch.SetTriple("thumbv6m-apple-" OSNAME);
931       return true;
932     case 10:
933       arch.SetTriple("thumbv6-apple-" OSNAME);
934       return true;
935     case 11:
936       arch.SetTriple("thumbv5-apple-" OSNAME);
937       return true;
938     case 12:
939       arch.SetTriple("thumbv4t-apple-" OSNAME);
940       return true;
941     case 13:
942       arch.SetTriple("thumb-apple-" OSNAME);
943       return true;
944     default:
945       break;
946     }
947     break;
948 
949   case ArchSpec::eCore_arm_armv7:
950     switch (idx) {
951     case 0:
952       arch.SetTriple("armv7-apple-" OSNAME);
953       return true;
954     case 1:
955       arch.SetTriple("armv6m-apple-" OSNAME);
956       return true;
957     case 2:
958       arch.SetTriple("armv6-apple-" OSNAME);
959       return true;
960     case 3:
961       arch.SetTriple("armv5-apple-" OSNAME);
962       return true;
963     case 4:
964       arch.SetTriple("armv4-apple-" OSNAME);
965       return true;
966     case 5:
967       arch.SetTriple("arm-apple-" OSNAME);
968       return true;
969     case 6:
970       arch.SetTriple("thumbv7-apple-" OSNAME);
971       return true;
972     case 7:
973       arch.SetTriple("thumbv6m-apple-" OSNAME);
974       return true;
975     case 8:
976       arch.SetTriple("thumbv6-apple-" OSNAME);
977       return true;
978     case 9:
979       arch.SetTriple("thumbv5-apple-" OSNAME);
980       return true;
981     case 10:
982       arch.SetTriple("thumbv4t-apple-" OSNAME);
983       return true;
984     case 11:
985       arch.SetTriple("thumb-apple-" OSNAME);
986       return true;
987     default:
988       break;
989     }
990     break;
991 
992   case ArchSpec::eCore_arm_armv6m:
993     switch (idx) {
994     case 0:
995       arch.SetTriple("armv6m-apple-" OSNAME);
996       return true;
997     case 1:
998       arch.SetTriple("armv6-apple-" OSNAME);
999       return true;
1000     case 2:
1001       arch.SetTriple("armv5-apple-" OSNAME);
1002       return true;
1003     case 3:
1004       arch.SetTriple("armv4-apple-" OSNAME);
1005       return true;
1006     case 4:
1007       arch.SetTriple("arm-apple-" OSNAME);
1008       return true;
1009     case 5:
1010       arch.SetTriple("thumbv6m-apple-" OSNAME);
1011       return true;
1012     case 6:
1013       arch.SetTriple("thumbv6-apple-" OSNAME);
1014       return true;
1015     case 7:
1016       arch.SetTriple("thumbv5-apple-" OSNAME);
1017       return true;
1018     case 8:
1019       arch.SetTriple("thumbv4t-apple-" OSNAME);
1020       return true;
1021     case 9:
1022       arch.SetTriple("thumb-apple-" OSNAME);
1023       return true;
1024     default:
1025       break;
1026     }
1027     break;
1028 
1029   case ArchSpec::eCore_arm_armv6:
1030     switch (idx) {
1031     case 0:
1032       arch.SetTriple("armv6-apple-" OSNAME);
1033       return true;
1034     case 1:
1035       arch.SetTriple("armv5-apple-" OSNAME);
1036       return true;
1037     case 2:
1038       arch.SetTriple("armv4-apple-" OSNAME);
1039       return true;
1040     case 3:
1041       arch.SetTriple("arm-apple-" OSNAME);
1042       return true;
1043     case 4:
1044       arch.SetTriple("thumbv6-apple-" OSNAME);
1045       return true;
1046     case 5:
1047       arch.SetTriple("thumbv5-apple-" OSNAME);
1048       return true;
1049     case 6:
1050       arch.SetTriple("thumbv4t-apple-" OSNAME);
1051       return true;
1052     case 7:
1053       arch.SetTriple("thumb-apple-" OSNAME);
1054       return true;
1055     default:
1056       break;
1057     }
1058     break;
1059 
1060   case ArchSpec::eCore_arm_armv5:
1061     switch (idx) {
1062     case 0:
1063       arch.SetTriple("armv5-apple-" OSNAME);
1064       return true;
1065     case 1:
1066       arch.SetTriple("armv4-apple-" OSNAME);
1067       return true;
1068     case 2:
1069       arch.SetTriple("arm-apple-" OSNAME);
1070       return true;
1071     case 3:
1072       arch.SetTriple("thumbv5-apple-" OSNAME);
1073       return true;
1074     case 4:
1075       arch.SetTriple("thumbv4t-apple-" OSNAME);
1076       return true;
1077     case 5:
1078       arch.SetTriple("thumb-apple-" OSNAME);
1079       return true;
1080     default:
1081       break;
1082     }
1083     break;
1084 
1085   case ArchSpec::eCore_arm_armv4:
1086     switch (idx) {
1087     case 0:
1088       arch.SetTriple("armv4-apple-" OSNAME);
1089       return true;
1090     case 1:
1091       arch.SetTriple("arm-apple-" OSNAME);
1092       return true;
1093     case 2:
1094       arch.SetTriple("thumbv4t-apple-" OSNAME);
1095       return true;
1096     case 3:
1097       arch.SetTriple("thumb-apple-" OSNAME);
1098       return true;
1099     default:
1100       break;
1101     }
1102     break;
1103   }
1104   arch.Clear();
1105   return false;
1106 }
1107 
1108 static FileSpec GetXcodeSelectPath() {
1109   static FileSpec g_xcode_select_filespec;
1110 
1111   if (!g_xcode_select_filespec) {
1112     FileSpec xcode_select_cmd("/usr/bin/xcode-select");
1113     if (FileSystem::Instance().Exists(xcode_select_cmd)) {
1114       int exit_status = -1;
1115       int signo = -1;
1116       std::string command_output;
1117       Status status =
1118           Host::RunShellCommand("/usr/bin/xcode-select --print-path",
1119                                 FileSpec(), // current working directory
1120                                 &exit_status, &signo, &command_output,
1121                                 std::chrono::seconds(2), // short timeout
1122                                 false);                  // don't run in a shell
1123       if (status.Success() && exit_status == 0 && !command_output.empty()) {
1124         size_t first_non_newline = command_output.find_last_not_of("\r\n");
1125         if (first_non_newline != std::string::npos) {
1126           command_output.erase(first_non_newline + 1);
1127         }
1128         g_xcode_select_filespec = FileSpec(command_output);
1129       }
1130     }
1131   }
1132 
1133   return g_xcode_select_filespec;
1134 }
1135 
1136 lldb_private::FileSpec PlatformDarwin::GetXcodeDeveloperDirectory() {
1137   static lldb_private::FileSpec g_developer_directory;
1138   static llvm::once_flag g_once_flag;
1139   llvm::call_once(g_once_flag, []() {
1140     if (FileSpec fspec = GetXcodeContentsDirectory()) {
1141       fspec.AppendPathComponent("Developer");
1142       if (FileSystem::Instance().Exists(fspec))
1143         g_developer_directory = fspec;
1144     }
1145   });
1146   return g_developer_directory;
1147 }
1148 
1149 BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) {
1150   BreakpointSP bp_sp;
1151   static const char *g_bp_names[] = {
1152       "start_wqthread", "_pthread_wqthread", "_pthread_start",
1153   };
1154 
1155   static const char *g_bp_modules[] = {"libsystem_c.dylib",
1156                                        "libSystem.B.dylib"};
1157 
1158   FileSpecList bp_modules;
1159   for (size_t i = 0; i < llvm::array_lengthof(g_bp_modules); i++) {
1160     const char *bp_module = g_bp_modules[i];
1161     bp_modules.EmplaceBack(bp_module);
1162   }
1163 
1164   bool internal = true;
1165   bool hardware = false;
1166   LazyBool skip_prologue = eLazyBoolNo;
1167   bp_sp = target.CreateBreakpoint(&bp_modules, nullptr, g_bp_names,
1168                                   llvm::array_lengthof(g_bp_names),
1169                                   eFunctionNameTypeFull, eLanguageTypeUnknown,
1170                                   0, skip_prologue, internal, hardware);
1171   bp_sp->SetBreakpointKind("thread-creation");
1172 
1173   return bp_sp;
1174 }
1175 
1176 int32_t
1177 PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) {
1178   const FileSpec &shell = launch_info.GetShell();
1179   if (!shell)
1180     return 1;
1181 
1182   std::string shell_string = shell.GetPath();
1183   const char *shell_name = strrchr(shell_string.c_str(), '/');
1184   if (shell_name == nullptr)
1185     shell_name = shell_string.c_str();
1186   else
1187     shell_name++;
1188 
1189   if (strcmp(shell_name, "sh") == 0) {
1190     // /bin/sh re-exec's itself as /bin/bash requiring another resume. But it
1191     // only does this if the COMMAND_MODE environment variable is set to
1192     // "legacy".
1193     if (launch_info.GetEnvironment().lookup("COMMAND_MODE") == "legacy")
1194       return 2;
1195     return 1;
1196   } else if (strcmp(shell_name, "csh") == 0 ||
1197              strcmp(shell_name, "tcsh") == 0 ||
1198              strcmp(shell_name, "zsh") == 0) {
1199     // csh and tcsh always seem to re-exec themselves.
1200     return 2;
1201   } else
1202     return 1;
1203 }
1204 
1205 void PlatformDarwin::CalculateTrapHandlerSymbolNames() {
1206   m_trap_handlers.push_back(ConstString("_sigtramp"));
1207 }
1208 
1209 static FileSpec GetCommandLineToolsLibraryPath() {
1210   static FileSpec g_command_line_tools_filespec;
1211 
1212   if (!g_command_line_tools_filespec) {
1213     FileSpec command_line_tools_path(GetXcodeSelectPath());
1214     command_line_tools_path.AppendPathComponent("Library");
1215     if (FileSystem::Instance().Exists(command_line_tools_path)) {
1216       g_command_line_tools_filespec = command_line_tools_path;
1217     }
1218   }
1219 
1220   return g_command_line_tools_filespec;
1221 }
1222 
1223 bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type,
1224                                         llvm::VersionTuple version) {
1225   switch (sdk_type) {
1226   case SDKType::MacOSX:
1227     return version >= llvm::VersionTuple(10, 10);
1228   case SDKType::iPhoneOS:
1229   case SDKType::iPhoneSimulator:
1230   case SDKType::AppleTVOS:
1231   case SDKType::AppleTVSimulator:
1232     return version >= llvm::VersionTuple(8);
1233   case SDKType::watchOS:
1234   case SDKType::WatchSimulator:
1235     return version >= llvm::VersionTuple(6);
1236   default:
1237     return false;
1238   }
1239 
1240   return false;
1241 }
1242 
1243 bool PlatformDarwin::SDKSupportsModules(SDKType desired_type,
1244                                         const FileSpec &sdk_path) {
1245   ConstString last_path_component = sdk_path.GetLastPathComponent();
1246 
1247   if (last_path_component) {
1248     const llvm::StringRef sdk_name = last_path_component.GetStringRef();
1249 
1250     const std::string sdk_name_lower = sdk_name.lower();
1251     const llvm::StringRef sdk_string = GetSDKNameForType(desired_type);
1252     if (!llvm::StringRef(sdk_name_lower).startswith(sdk_string))
1253       return false;
1254 
1255     auto version_part = sdk_name.drop_front(sdk_string.size());
1256     version_part.consume_back(".sdk");
1257 
1258     llvm::VersionTuple version;
1259     if (version.tryParse(version_part))
1260       return false;
1261     return SDKSupportsModules(desired_type, version);
1262   }
1263 
1264   return false;
1265 }
1266 
1267 FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator(
1268     void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef path) {
1269   SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton);
1270 
1271   FileSpec spec(path);
1272   if (SDKSupportsModules(enumerator_info->sdk_type, spec)) {
1273     enumerator_info->found_path = spec;
1274     return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
1275   }
1276 
1277   return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
1278 }
1279 
1280 FileSpec PlatformDarwin::FindSDKInXcodeForModules(SDKType sdk_type,
1281                                                   const FileSpec &sdks_spec) {
1282   // Look inside Xcode for the required installed iOS SDK version
1283 
1284   if (!FileSystem::Instance().IsDirectory(sdks_spec)) {
1285     return FileSpec();
1286   }
1287 
1288   const bool find_directories = true;
1289   const bool find_files = false;
1290   const bool find_other = true; // include symlinks
1291 
1292   SDKEnumeratorInfo enumerator_info;
1293 
1294   enumerator_info.sdk_type = sdk_type;
1295 
1296   FileSystem::Instance().EnumerateDirectory(
1297       sdks_spec.GetPath(), find_directories, find_files, find_other,
1298       DirectoryEnumerator, &enumerator_info);
1299 
1300   if (FileSystem::Instance().IsDirectory(enumerator_info.found_path))
1301     return enumerator_info.found_path;
1302   else
1303     return FileSpec();
1304 }
1305 
1306 FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) {
1307   FileSpec sdks_spec = GetXcodeContentsDirectory();
1308   sdks_spec.AppendPathComponent("Developer");
1309   sdks_spec.AppendPathComponent("Platforms");
1310 
1311   switch (sdk_type) {
1312   case SDKType::MacOSX:
1313     sdks_spec.AppendPathComponent("MacOSX.platform");
1314     break;
1315   case SDKType::iPhoneSimulator:
1316     sdks_spec.AppendPathComponent("iPhoneSimulator.platform");
1317     break;
1318   case SDKType::iPhoneOS:
1319     sdks_spec.AppendPathComponent("iPhoneOS.platform");
1320     break;
1321   default:
1322     llvm_unreachable("unsupported sdk");
1323   }
1324 
1325   sdks_spec.AppendPathComponent("Developer");
1326   sdks_spec.AppendPathComponent("SDKs");
1327 
1328   if (sdk_type == SDKType::MacOSX) {
1329     llvm::VersionTuple version = HostInfo::GetOSVersion();
1330 
1331     if (!version.empty()) {
1332       if (SDKSupportsModules(SDKType::MacOSX, version)) {
1333         // If the Xcode SDKs are not available then try to use the
1334         // Command Line Tools one which is only for MacOSX.
1335         if (!FileSystem::Instance().Exists(sdks_spec)) {
1336           sdks_spec = GetCommandLineToolsLibraryPath();
1337           sdks_spec.AppendPathComponent("SDKs");
1338         }
1339 
1340         // We slightly prefer the exact SDK for this machine.  See if it is
1341         // there.
1342 
1343         FileSpec native_sdk_spec = sdks_spec;
1344         StreamString native_sdk_name;
1345         native_sdk_name.Printf("MacOSX%u.%u.sdk", version.getMajor(),
1346                                version.getMinor().getValueOr(0));
1347         native_sdk_spec.AppendPathComponent(native_sdk_name.GetString());
1348 
1349         if (FileSystem::Instance().Exists(native_sdk_spec)) {
1350           return native_sdk_spec;
1351         }
1352       }
1353     }
1354   }
1355 
1356   return FindSDKInXcodeForModules(sdk_type, sdks_spec);
1357 }
1358 
1359 std::tuple<llvm::VersionTuple, llvm::StringRef>
1360 PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) {
1361   llvm::StringRef build;
1362   llvm::StringRef version_str;
1363   llvm::StringRef build_str;
1364   std::tie(version_str, build_str) = dir.split(' ');
1365   llvm::VersionTuple version;
1366   if (!version.tryParse(version_str) ||
1367       build_str.empty()) {
1368     if (build_str.consume_front("(")) {
1369       size_t pos = build_str.find(')');
1370       build = build_str.slice(0, pos);
1371     }
1372   }
1373 
1374   return std::make_tuple(version, build);
1375 }
1376 
1377 llvm::Expected<StructuredData::DictionarySP>
1378 PlatformDarwin::FetchExtendedCrashInformation(Process &process) {
1379   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1380 
1381   StructuredData::ArraySP annotations = ExtractCrashInfoAnnotations(process);
1382 
1383   if (!annotations || !annotations->GetSize()) {
1384     LLDB_LOG(log, "Couldn't extract crash information annotations");
1385     return nullptr;
1386   }
1387 
1388   StructuredData::DictionarySP extended_crash_info =
1389       std::make_shared<StructuredData::Dictionary>();
1390 
1391   extended_crash_info->AddItem("crash-info annotations", annotations);
1392 
1393   return extended_crash_info;
1394 }
1395 
1396 StructuredData::ArraySP
1397 PlatformDarwin::ExtractCrashInfoAnnotations(Process &process) {
1398   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1399 
1400   ConstString section_name("__crash_info");
1401   Target &target = process.GetTarget();
1402   StructuredData::ArraySP array_sp = std::make_shared<StructuredData::Array>();
1403 
1404   for (ModuleSP module : target.GetImages().Modules()) {
1405     SectionList *sections = module->GetSectionList();
1406 
1407     std::string module_name = module->GetSpecificationDescription();
1408 
1409     // The DYDL module is skipped since it's always loaded when running the
1410     // binary.
1411     if (module_name == "/usr/lib/dyld")
1412       continue;
1413 
1414     if (!sections) {
1415       LLDB_LOG(log, "Module {0} doesn't have any section!", module_name);
1416       continue;
1417     }
1418 
1419     SectionSP crash_info = sections->FindSectionByName(section_name);
1420     if (!crash_info) {
1421       LLDB_LOG(log, "Module {0} doesn't have section {1}!", module_name,
1422                section_name);
1423       continue;
1424     }
1425 
1426     addr_t load_addr = crash_info->GetLoadBaseAddress(&target);
1427 
1428     if (load_addr == LLDB_INVALID_ADDRESS) {
1429       LLDB_LOG(log, "Module {0} has an invalid '{1}' section load address: {2}",
1430                module_name, section_name, load_addr);
1431       continue;
1432     }
1433 
1434     Status error;
1435     CrashInfoAnnotations annotations;
1436     size_t expected_size = sizeof(CrashInfoAnnotations);
1437     size_t bytes_read = process.ReadMemoryFromInferior(load_addr, &annotations,
1438                                                        expected_size, error);
1439 
1440     if (expected_size != bytes_read || error.Fail()) {
1441       LLDB_LOG(log, "Failed to read {0} section from memory in module {1}: {2}",
1442                section_name, module_name, error);
1443       continue;
1444     }
1445 
1446     // initial support added for version 5
1447     if (annotations.version < 5) {
1448       LLDB_LOG(log,
1449                "Annotation version lower than 5 unsupported! Module {0} has "
1450                "version {1} instead.",
1451                module_name, annotations.version);
1452       continue;
1453     }
1454 
1455     if (!annotations.message) {
1456       LLDB_LOG(log, "No message available for module {0}.", module_name);
1457       continue;
1458     }
1459 
1460     std::string message;
1461     bytes_read =
1462         process.ReadCStringFromMemory(annotations.message, message, error);
1463 
1464     if (message.empty() || bytes_read != message.size() || error.Fail()) {
1465       LLDB_LOG(log, "Failed to read the message from memory in module {0}: {1}",
1466                module_name, error);
1467       continue;
1468     }
1469 
1470     // Remove trailing newline from message
1471     if (message.back() == '\n')
1472       message.pop_back();
1473 
1474     if (!annotations.message2)
1475       LLDB_LOG(log, "No message2 available for module {0}.", module_name);
1476 
1477     std::string message2;
1478     bytes_read =
1479         process.ReadCStringFromMemory(annotations.message2, message2, error);
1480 
1481     if (!message2.empty() && bytes_read == message2.size() && error.Success())
1482       if (message2.back() == '\n')
1483         message2.pop_back();
1484 
1485     StructuredData::DictionarySP entry_sp =
1486         std::make_shared<StructuredData::Dictionary>();
1487 
1488     entry_sp->AddStringItem("image", module->GetFileSpec().GetPath(false));
1489     entry_sp->AddStringItem("uuid", module->GetUUID().GetAsString());
1490     entry_sp->AddStringItem("message", message);
1491     entry_sp->AddStringItem("message2", message2);
1492     entry_sp->AddIntegerItem("abort-cause", annotations.abort_cause);
1493 
1494     array_sp->AddItem(entry_sp);
1495   }
1496 
1497   return array_sp;
1498 }
1499 
1500 void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
1501     Target *target, std::vector<std::string> &options, SDKType sdk_type) {
1502   const std::vector<std::string> apple_arguments = {
1503       "-x",       "objective-c++", "-fobjc-arc",
1504       "-fblocks", "-D_ISO646_H",   "-D__ISO646_H",
1505       "-fgnuc-version=4.2.1"};
1506 
1507   options.insert(options.end(), apple_arguments.begin(), apple_arguments.end());
1508 
1509   StreamString minimum_version_option;
1510   bool use_current_os_version = false;
1511   switch (sdk_type) {
1512   case SDKType::iPhoneOS:
1513 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
1514     use_current_os_version = true;
1515 #else
1516     use_current_os_version = false;
1517 #endif
1518     break;
1519 
1520   case SDKType::iPhoneSimulator:
1521     use_current_os_version = false;
1522     break;
1523 
1524   case SDKType::MacOSX:
1525 #if defined(__i386__) || defined(__x86_64__)
1526     use_current_os_version = true;
1527 #else
1528     use_current_os_version = false;
1529 #endif
1530     break;
1531   default:
1532     break;
1533   }
1534 
1535   llvm::VersionTuple version;
1536   if (use_current_os_version)
1537     version = GetOSVersion();
1538   else if (target) {
1539     // Our OS doesn't match our executable so we need to get the min OS version
1540     // from the object file
1541     ModuleSP exe_module_sp = target->GetExecutableModule();
1542     if (exe_module_sp) {
1543       ObjectFile *object_file = exe_module_sp->GetObjectFile();
1544       if (object_file)
1545         version = object_file->GetMinimumOSVersion();
1546     }
1547   }
1548   // Only add the version-min options if we got a version from somewhere
1549   if (!version.empty()) {
1550     switch (sdk_type) {
1551     case SDKType::iPhoneOS:
1552       minimum_version_option.PutCString("-mios-version-min=");
1553       minimum_version_option.PutCString(version.getAsString());
1554       break;
1555     case SDKType::iPhoneSimulator:
1556       minimum_version_option.PutCString("-mios-simulator-version-min=");
1557       minimum_version_option.PutCString(version.getAsString());
1558       break;
1559     case SDKType::MacOSX:
1560       minimum_version_option.PutCString("-mmacosx-version-min=");
1561       minimum_version_option.PutCString(version.getAsString());
1562       break;
1563     default:
1564       llvm_unreachable("unsupported sdk");
1565     }
1566     options.push_back(std::string(minimum_version_option.GetString()));
1567   }
1568 
1569   FileSpec sysroot_spec;
1570   // Scope for mutex locker below
1571   {
1572     std::lock_guard<std::mutex> guard(m_mutex);
1573     sysroot_spec = GetSDKDirectoryForModules(sdk_type);
1574   }
1575 
1576   if (FileSystem::Instance().IsDirectory(sysroot_spec.GetPath())) {
1577     options.push_back("-isysroot");
1578     options.push_back(sysroot_spec.GetPath());
1579   }
1580 }
1581 
1582 ConstString PlatformDarwin::GetFullNameForDylib(ConstString basename) {
1583   if (basename.IsEmpty())
1584     return basename;
1585 
1586   StreamString stream;
1587   stream.Printf("lib%s.dylib", basename.GetCString());
1588   return ConstString(stream.GetString());
1589 }
1590 
1591 llvm::VersionTuple PlatformDarwin::GetOSVersion(Process *process) {
1592   if (process && strstr(GetPluginName().GetCString(), "-simulator")) {
1593     lldb_private::ProcessInstanceInfo proc_info;
1594     if (Host::GetProcessInfo(process->GetID(), proc_info)) {
1595       const Environment &env = proc_info.GetEnvironment();
1596 
1597       llvm::VersionTuple result;
1598       if (!result.tryParse(env.lookup("SIMULATOR_RUNTIME_VERSION")))
1599         return result;
1600 
1601       std::string dyld_root_path = env.lookup("DYLD_ROOT_PATH");
1602       if (!dyld_root_path.empty()) {
1603         dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist";
1604         ApplePropertyList system_version_plist(dyld_root_path.c_str());
1605         std::string product_version;
1606         if (system_version_plist.GetValueAsString("ProductVersion",
1607                                                   product_version)) {
1608           if (!result.tryParse(product_version))
1609             return result;
1610         }
1611       }
1612     }
1613     // For simulator platforms, do NOT call back through
1614     // Platform::GetOSVersion() as it might call Process::GetHostOSVersion()
1615     // which we don't want as it will be incorrect
1616     return llvm::VersionTuple();
1617   }
1618 
1619   return Platform::GetOSVersion(process);
1620 }
1621 
1622 lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) {
1623   // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled
1624   // in with any executable directories that should be searched.
1625   static std::vector<FileSpec> g_executable_dirs;
1626 
1627   // Find the global list of directories that we will search for executables
1628   // once so we don't keep doing the work over and over.
1629   static llvm::once_flag g_once_flag;
1630   llvm::call_once(g_once_flag, []() {
1631 
1632     // When locating executables, trust the DEVELOPER_DIR first if it is set
1633     FileSpec xcode_contents_dir = GetXcodeContentsDirectory();
1634     if (xcode_contents_dir) {
1635       FileSpec xcode_lldb_resources = xcode_contents_dir;
1636       xcode_lldb_resources.AppendPathComponent("SharedFrameworks");
1637       xcode_lldb_resources.AppendPathComponent("LLDB.framework");
1638       xcode_lldb_resources.AppendPathComponent("Resources");
1639       if (FileSystem::Instance().Exists(xcode_lldb_resources)) {
1640         FileSpec dir;
1641         dir.GetDirectory().SetCString(xcode_lldb_resources.GetPath().c_str());
1642         g_executable_dirs.push_back(dir);
1643       }
1644     }
1645     // Xcode might not be installed so we also check for the Command Line Tools.
1646     FileSpec command_line_tools_dir = GetCommandLineToolsLibraryPath();
1647     if (command_line_tools_dir) {
1648       FileSpec cmd_line_lldb_resources = command_line_tools_dir;
1649       cmd_line_lldb_resources.AppendPathComponent("PrivateFrameworks");
1650       cmd_line_lldb_resources.AppendPathComponent("LLDB.framework");
1651       cmd_line_lldb_resources.AppendPathComponent("Resources");
1652       if (FileSystem::Instance().Exists(cmd_line_lldb_resources)) {
1653         FileSpec dir;
1654         dir.GetDirectory().SetCString(
1655             cmd_line_lldb_resources.GetPath().c_str());
1656         g_executable_dirs.push_back(dir);
1657       }
1658     }
1659   });
1660 
1661   // Now search the global list of executable directories for the executable we
1662   // are looking for
1663   for (const auto &executable_dir : g_executable_dirs) {
1664     FileSpec executable_file;
1665     executable_file.GetDirectory() = executable_dir.GetDirectory();
1666     executable_file.GetFilename().SetCString(basename);
1667     if (FileSystem::Instance().Exists(executable_file))
1668       return executable_file;
1669   }
1670 
1671   return FileSpec();
1672 }
1673 
1674 lldb_private::Status
1675 PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) {
1676   // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr if
1677   // the OS_ACTIVITY_DT_MODE environment variable is set.  (It doesn't require
1678   // any specific value; rather, it just needs to exist). We will set it here
1679   // as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag is not set.  Xcode
1680   // makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell
1681   // LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they
1682   // specifically want it unset.
1683   const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE";
1684   auto &env_vars = launch_info.GetEnvironment();
1685   if (!env_vars.count(disable_env_var)) {
1686     // We want to make sure that OS_ACTIVITY_DT_MODE is set so that we get
1687     // os_log and NSLog messages mirrored to the target process stderr.
1688     env_vars.try_emplace("OS_ACTIVITY_DT_MODE", "enable");
1689   }
1690 
1691   // Let our parent class do the real launching.
1692   return PlatformPOSIX::LaunchProcess(launch_info);
1693 }
1694 
1695 lldb_private::Status PlatformDarwin::FindBundleBinaryInExecSearchPaths(
1696     const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
1697     const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
1698     bool *did_create_ptr) {
1699   const FileSpec &platform_file = module_spec.GetFileSpec();
1700   // See if the file is present in any of the module_search_paths_ptr
1701   // directories.
1702   if (!module_sp && module_search_paths_ptr && platform_file) {
1703     // create a vector of all the file / directory names in platform_file e.g.
1704     // this might be
1705     // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
1706     //
1707     // We'll need to look in the module_search_paths_ptr directories for both
1708     // "UIFoundation" and "UIFoundation.framework" -- most likely the latter
1709     // will be the one we find there.
1710 
1711     FileSpec platform_pull_upart(platform_file);
1712     std::vector<std::string> path_parts;
1713     path_parts.push_back(
1714         platform_pull_upart.GetLastPathComponent().AsCString());
1715     while (platform_pull_upart.RemoveLastPathComponent()) {
1716       ConstString part = platform_pull_upart.GetLastPathComponent();
1717       path_parts.push_back(part.AsCString());
1718     }
1719     const size_t path_parts_size = path_parts.size();
1720 
1721     size_t num_module_search_paths = module_search_paths_ptr->GetSize();
1722     for (size_t i = 0; i < num_module_search_paths; ++i) {
1723       Log *log_verbose = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
1724       LLDB_LOGF(
1725           log_verbose,
1726           "PlatformRemoteDarwinDevice::GetSharedModule searching for binary in "
1727           "search-path %s",
1728           module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str());
1729       // Create a new FileSpec with this module_search_paths_ptr plus just the
1730       // filename ("UIFoundation"), then the parent dir plus filename
1731       // ("UIFoundation.framework/UIFoundation") etc - up to four names (to
1732       // handle "Foo.framework/Contents/MacOS/Foo")
1733 
1734       for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) {
1735         FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));
1736 
1737         // Add the components backwards.  For
1738         // .../PrivateFrameworks/UIFoundation.framework/UIFoundation path_parts
1739         // is
1740         //   [0] UIFoundation
1741         //   [1] UIFoundation.framework
1742         //   [2] PrivateFrameworks
1743         //
1744         // and if 'j' is 2, we want to append path_parts[1] and then
1745         // path_parts[0], aka 'UIFoundation.framework/UIFoundation', to the
1746         // module_search_paths_ptr path.
1747 
1748         for (int k = j; k >= 0; --k) {
1749           path_to_try.AppendPathComponent(path_parts[k]);
1750         }
1751 
1752         if (FileSystem::Instance().Exists(path_to_try)) {
1753           ModuleSpec new_module_spec(module_spec);
1754           new_module_spec.GetFileSpec() = path_to_try;
1755           Status new_error(Platform::GetSharedModule(
1756               new_module_spec, process, module_sp, nullptr, old_module_sp_ptr,
1757               did_create_ptr));
1758 
1759           if (module_sp) {
1760             module_sp->SetPlatformFileSpec(path_to_try);
1761             return new_error;
1762           }
1763         }
1764       }
1765     }
1766   }
1767   return Status();
1768 }
1769 
1770 std::string PlatformDarwin::FindComponentInPath(llvm::StringRef path,
1771                                                 llvm::StringRef component) {
1772   auto begin = llvm::sys::path::begin(path);
1773   auto end = llvm::sys::path::end(path);
1774   for (auto it = begin; it != end; ++it) {
1775     if (it->contains(component)) {
1776       llvm::SmallString<128> buffer;
1777       llvm::sys::path::append(buffer, begin, ++it,
1778                               llvm::sys::path::Style::posix);
1779       return buffer.str().str();
1780     }
1781   }
1782   return {};
1783 }
1784 
1785 std::string
1786 PlatformDarwin::FindXcodeContentsDirectoryInPath(llvm::StringRef path) {
1787   auto begin = llvm::sys::path::begin(path);
1788   auto end = llvm::sys::path::end(path);
1789 
1790   // Iterate over the path components until we find something that ends with
1791   // .app. If the next component is Contents then we've found the Contents
1792   // directory.
1793   for (auto it = begin; it != end; ++it) {
1794     if (it->endswith(".app")) {
1795       auto next = it;
1796       if (++next != end && *next == "Contents") {
1797         llvm::SmallString<128> buffer;
1798         llvm::sys::path::append(buffer, begin, ++next,
1799                                 llvm::sys::path::Style::posix);
1800         return buffer.str().str();
1801       }
1802     }
1803   }
1804 
1805   return {};
1806 }
1807 
1808 llvm::StringRef PlatformDarwin::GetSDKNameForType(SDKType type) {
1809   switch (type) {
1810   case MacOSX:
1811     return "macosx";
1812   case iPhoneSimulator:
1813     return "iphonesimulator";
1814   case iPhoneOS:
1815     return "iphoneos";
1816   case AppleTVSimulator:
1817     return "appletvsimulator";
1818   case AppleTVOS:
1819     return "appletvos";
1820   case WatchSimulator:
1821     return "watchsimulator";
1822   case watchOS:
1823     return "watchos";
1824   case bridgeOS:
1825     return "bridgeos";
1826   case Linux:
1827     return "linux";
1828   case numSDKTypes:
1829   case unknown:
1830     return "";
1831   }
1832   llvm_unreachable("unhandled switch case");
1833 }
1834 
1835 FileSpec PlatformDarwin::GetXcodeSDK(SDKType type) {
1836   std::string xcrun_cmd =
1837       "xcrun --show-sdk-path --sdk " + GetSDKNameForType(type).str();
1838 
1839   int status = 0;
1840   int signo = 0;
1841   std::string output_str;
1842   lldb_private::Status error =
1843       Host::RunShellCommand(xcrun_cmd.c_str(), FileSpec(), &status, &signo,
1844                             &output_str, std::chrono::seconds(15));
1845 
1846   // Check that xcrun return something useful.
1847   if (status != 0 || output_str.empty())
1848     return {};
1849 
1850   // Convert to a StringRef so we can manipulate the string without modifying
1851   // the underlying data.
1852   llvm::StringRef output(output_str);
1853 
1854   // Remove any trailing newline characters.
1855   output = output.rtrim();
1856 
1857   // Strip any leading newline characters and everything before them.
1858   const size_t last_newline = output.rfind('\n');
1859   if (last_newline != llvm::StringRef::npos)
1860     output = output.substr(last_newline + 1);
1861 
1862   // Whatever is left in output should be a valid path.
1863   if (!FileSystem::Instance().Exists(output))
1864     return {};
1865 
1866   // Find the contents dir in the xcrun provided path.
1867   std::string xcode_contents_dir = FindXcodeContentsDirectoryInPath(output);
1868   if (xcode_contents_dir.empty())
1869     return {};
1870 
1871   return FileSpec(xcode_contents_dir);
1872 }
1873 
1874 FileSpec PlatformDarwin::GetXcodeContentsDirectory() {
1875   static FileSpec g_xcode_contents_path;
1876   static std::once_flag g_once_flag;
1877   std::call_once(g_once_flag, [&]() {
1878     // Try the shlib dir first.
1879     if (FileSpec fspec = HostInfo::GetShlibDir()) {
1880       if (FileSystem::Instance().Exists(fspec)) {
1881         std::string xcode_contents_dir =
1882             FindXcodeContentsDirectoryInPath(fspec.GetPath());
1883         if (!xcode_contents_dir.empty()) {
1884           g_xcode_contents_path = FileSpec(xcode_contents_dir);
1885           return;
1886         }
1887       }
1888     }
1889 
1890     if (const char *developer_dir_env_var = getenv("DEVELOPER_DIR")) {
1891       FileSpec fspec(developer_dir_env_var);
1892       if (FileSystem::Instance().Exists(fspec)) {
1893         std::string xcode_contents_dir =
1894             FindXcodeContentsDirectoryInPath(fspec.GetPath());
1895         if (!xcode_contents_dir.empty()) {
1896           g_xcode_contents_path = FileSpec(xcode_contents_dir);
1897           return;
1898         }
1899       }
1900     }
1901 
1902     if (FileSpec fspec = GetXcodeSDK(SDKType::MacOSX)) {
1903       if (FileSystem::Instance().Exists(fspec)) {
1904         std::string xcode_contents_dir =
1905             FindXcodeContentsDirectoryInPath(fspec.GetPath());
1906         if (!xcode_contents_dir.empty()) {
1907           g_xcode_contents_path = FileSpec(xcode_contents_dir);
1908           return;
1909         }
1910       }
1911     }
1912   });
1913   return g_xcode_contents_path;
1914 }
1915 
1916 FileSpec PlatformDarwin::GetCurrentToolchainDirectory() {
1917   if (FileSpec fspec = HostInfo::GetShlibDir())
1918     return FileSpec(FindComponentInPath(fspec.GetPath(), ".xctoolchain"));
1919   return {};
1920 }
1921 
1922 FileSpec PlatformDarwin::GetCurrentCommandLineToolsDirectory() {
1923   if (FileSpec fspec = HostInfo::GetShlibDir())
1924     return FileSpec(FindComponentInPath(fspec.GetPath(), "CommandLineTools"));
1925   return {};
1926 }
1927