xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp (revision 4e1ee0786f11cc571bd0be17d38e46f635c719fc)
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     llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, 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_modules,
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,
345     llvm::SmallVectorImpl<ModuleSP> *old_modules, 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, old_modules,
355           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, old_modules,
363                                       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_modules,
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, old_modules,
404                     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 #elif defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1
550 #define OSNAME "macosx"
551 #else
552 #define OSNAME "ios"
553 #endif
554 
555   const ArchSpec::Core system_core = system_arch.GetCore();
556   switch (system_core) {
557   default:
558     switch (idx) {
559     case 0:
560       arch.SetTriple("arm64-apple-" OSNAME);
561       return true;
562     case 1:
563       arch.SetTriple("armv7-apple-" OSNAME);
564       return true;
565     case 2:
566       arch.SetTriple("armv7f-apple-" OSNAME);
567       return true;
568     case 3:
569       arch.SetTriple("armv7k-apple-" OSNAME);
570       return true;
571     case 4:
572       arch.SetTriple("armv7s-apple-" OSNAME);
573       return true;
574     case 5:
575       arch.SetTriple("armv7m-apple-" OSNAME);
576       return true;
577     case 6:
578       arch.SetTriple("armv7em-apple-" OSNAME);
579       return true;
580     case 7:
581       arch.SetTriple("armv6m-apple-" OSNAME);
582       return true;
583     case 8:
584       arch.SetTriple("armv6-apple-" OSNAME);
585       return true;
586     case 9:
587       arch.SetTriple("armv5-apple-" OSNAME);
588       return true;
589     case 10:
590       arch.SetTriple("armv4-apple-" OSNAME);
591       return true;
592     case 11:
593       arch.SetTriple("arm-apple-" OSNAME);
594       return true;
595     case 12:
596       arch.SetTriple("thumbv7-apple-" OSNAME);
597       return true;
598     case 13:
599       arch.SetTriple("thumbv7f-apple-" OSNAME);
600       return true;
601     case 14:
602       arch.SetTriple("thumbv7k-apple-" OSNAME);
603       return true;
604     case 15:
605       arch.SetTriple("thumbv7s-apple-" OSNAME);
606       return true;
607     case 16:
608       arch.SetTriple("thumbv7m-apple-" OSNAME);
609       return true;
610     case 17:
611       arch.SetTriple("thumbv7em-apple-" OSNAME);
612       return true;
613     case 18:
614       arch.SetTriple("thumbv6m-apple-" OSNAME);
615       return true;
616     case 19:
617       arch.SetTriple("thumbv6-apple-" OSNAME);
618       return true;
619     case 20:
620       arch.SetTriple("thumbv5-apple-" OSNAME);
621       return true;
622     case 21:
623       arch.SetTriple("thumbv4t-apple-" OSNAME);
624       return true;
625     case 22:
626       arch.SetTriple("thumb-apple-" OSNAME);
627       return true;
628     default:
629       break;
630     }
631     break;
632 
633   case ArchSpec::eCore_arm_arm64:
634     switch (idx) {
635     case 0:
636       arch.SetTriple("arm64-apple-" OSNAME);
637       return true;
638     case 1:
639       arch.SetTriple("armv7s-apple-" OSNAME);
640       return true;
641     case 2:
642       arch.SetTriple("armv7f-apple-" OSNAME);
643       return true;
644     case 3:
645       arch.SetTriple("armv7m-apple-" OSNAME);
646       return true;
647     case 4:
648       arch.SetTriple("armv7em-apple-" OSNAME);
649       return true;
650     case 5:
651       arch.SetTriple("armv7-apple-" OSNAME);
652       return true;
653     case 6:
654       arch.SetTriple("armv6m-apple-" OSNAME);
655       return true;
656     case 7:
657       arch.SetTriple("armv6-apple-" OSNAME);
658       return true;
659     case 8:
660       arch.SetTriple("armv5-apple-" OSNAME);
661       return true;
662     case 9:
663       arch.SetTriple("armv4-apple-" OSNAME);
664       return true;
665     case 10:
666       arch.SetTriple("arm-apple-" OSNAME);
667       return true;
668     case 11:
669       arch.SetTriple("thumbv7-apple-" OSNAME);
670       return true;
671     case 12:
672       arch.SetTriple("thumbv7f-apple-" OSNAME);
673       return true;
674     case 13:
675       arch.SetTriple("thumbv7k-apple-" OSNAME);
676       return true;
677     case 14:
678       arch.SetTriple("thumbv7s-apple-" OSNAME);
679       return true;
680     case 15:
681       arch.SetTriple("thumbv7m-apple-" OSNAME);
682       return true;
683     case 16:
684       arch.SetTriple("thumbv7em-apple-" OSNAME);
685       return true;
686     case 17:
687       arch.SetTriple("thumbv6m-apple-" OSNAME);
688       return true;
689     case 18:
690       arch.SetTriple("thumbv6-apple-" OSNAME);
691       return true;
692     case 19:
693       arch.SetTriple("thumbv5-apple-" OSNAME);
694       return true;
695     case 20:
696       arch.SetTriple("thumbv4t-apple-" OSNAME);
697       return true;
698     case 21:
699       arch.SetTriple("thumb-apple-" OSNAME);
700       return true;
701     default:
702       break;
703     }
704     break;
705 
706   case ArchSpec::eCore_arm_armv7f:
707     switch (idx) {
708     case 0:
709       arch.SetTriple("armv7f-apple-" OSNAME);
710       return true;
711     case 1:
712       arch.SetTriple("armv7-apple-" OSNAME);
713       return true;
714     case 2:
715       arch.SetTriple("armv6m-apple-" OSNAME);
716       return true;
717     case 3:
718       arch.SetTriple("armv6-apple-" OSNAME);
719       return true;
720     case 4:
721       arch.SetTriple("armv5-apple-" OSNAME);
722       return true;
723     case 5:
724       arch.SetTriple("armv4-apple-" OSNAME);
725       return true;
726     case 6:
727       arch.SetTriple("arm-apple-" OSNAME);
728       return true;
729     case 7:
730       arch.SetTriple("thumbv7f-apple-" OSNAME);
731       return true;
732     case 8:
733       arch.SetTriple("thumbv7-apple-" OSNAME);
734       return true;
735     case 9:
736       arch.SetTriple("thumbv6m-apple-" OSNAME);
737       return true;
738     case 10:
739       arch.SetTriple("thumbv6-apple-" OSNAME);
740       return true;
741     case 11:
742       arch.SetTriple("thumbv5-apple-" OSNAME);
743       return true;
744     case 12:
745       arch.SetTriple("thumbv4t-apple-" OSNAME);
746       return true;
747     case 13:
748       arch.SetTriple("thumb-apple-" OSNAME);
749       return true;
750     default:
751       break;
752     }
753     break;
754 
755   case ArchSpec::eCore_arm_armv7k:
756     switch (idx) {
757     case 0:
758       arch.SetTriple("armv7k-apple-" OSNAME);
759       return true;
760     case 1:
761       arch.SetTriple("armv7-apple-" OSNAME);
762       return true;
763     case 2:
764       arch.SetTriple("armv6m-apple-" OSNAME);
765       return true;
766     case 3:
767       arch.SetTriple("armv6-apple-" OSNAME);
768       return true;
769     case 4:
770       arch.SetTriple("armv5-apple-" OSNAME);
771       return true;
772     case 5:
773       arch.SetTriple("armv4-apple-" OSNAME);
774       return true;
775     case 6:
776       arch.SetTriple("arm-apple-" OSNAME);
777       return true;
778     case 7:
779       arch.SetTriple("thumbv7k-apple-" OSNAME);
780       return true;
781     case 8:
782       arch.SetTriple("thumbv7-apple-" OSNAME);
783       return true;
784     case 9:
785       arch.SetTriple("thumbv6m-apple-" OSNAME);
786       return true;
787     case 10:
788       arch.SetTriple("thumbv6-apple-" OSNAME);
789       return true;
790     case 11:
791       arch.SetTriple("thumbv5-apple-" OSNAME);
792       return true;
793     case 12:
794       arch.SetTriple("thumbv4t-apple-" OSNAME);
795       return true;
796     case 13:
797       arch.SetTriple("thumb-apple-" OSNAME);
798       return true;
799     default:
800       break;
801     }
802     break;
803 
804   case ArchSpec::eCore_arm_armv7s:
805     switch (idx) {
806     case 0:
807       arch.SetTriple("armv7s-apple-" OSNAME);
808       return true;
809     case 1:
810       arch.SetTriple("armv7-apple-" OSNAME);
811       return true;
812     case 2:
813       arch.SetTriple("armv6m-apple-" OSNAME);
814       return true;
815     case 3:
816       arch.SetTriple("armv6-apple-" OSNAME);
817       return true;
818     case 4:
819       arch.SetTriple("armv5-apple-" OSNAME);
820       return true;
821     case 5:
822       arch.SetTriple("armv4-apple-" OSNAME);
823       return true;
824     case 6:
825       arch.SetTriple("arm-apple-" OSNAME);
826       return true;
827     case 7:
828       arch.SetTriple("thumbv7s-apple-" OSNAME);
829       return true;
830     case 8:
831       arch.SetTriple("thumbv7-apple-" OSNAME);
832       return true;
833     case 9:
834       arch.SetTriple("thumbv6m-apple-" OSNAME);
835       return true;
836     case 10:
837       arch.SetTriple("thumbv6-apple-" OSNAME);
838       return true;
839     case 11:
840       arch.SetTriple("thumbv5-apple-" OSNAME);
841       return true;
842     case 12:
843       arch.SetTriple("thumbv4t-apple-" OSNAME);
844       return true;
845     case 13:
846       arch.SetTriple("thumb-apple-" OSNAME);
847       return true;
848     default:
849       break;
850     }
851     break;
852 
853   case ArchSpec::eCore_arm_armv7m:
854     switch (idx) {
855     case 0:
856       arch.SetTriple("armv7m-apple-" OSNAME);
857       return true;
858     case 1:
859       arch.SetTriple("armv7-apple-" OSNAME);
860       return true;
861     case 2:
862       arch.SetTriple("armv6m-apple-" OSNAME);
863       return true;
864     case 3:
865       arch.SetTriple("armv6-apple-" OSNAME);
866       return true;
867     case 4:
868       arch.SetTriple("armv5-apple-" OSNAME);
869       return true;
870     case 5:
871       arch.SetTriple("armv4-apple-" OSNAME);
872       return true;
873     case 6:
874       arch.SetTriple("arm-apple-" OSNAME);
875       return true;
876     case 7:
877       arch.SetTriple("thumbv7m-apple-" OSNAME);
878       return true;
879     case 8:
880       arch.SetTriple("thumbv7-apple-" OSNAME);
881       return true;
882     case 9:
883       arch.SetTriple("thumbv6m-apple-" OSNAME);
884       return true;
885     case 10:
886       arch.SetTriple("thumbv6-apple-" OSNAME);
887       return true;
888     case 11:
889       arch.SetTriple("thumbv5-apple-" OSNAME);
890       return true;
891     case 12:
892       arch.SetTriple("thumbv4t-apple-" OSNAME);
893       return true;
894     case 13:
895       arch.SetTriple("thumb-apple-" OSNAME);
896       return true;
897     default:
898       break;
899     }
900     break;
901 
902   case ArchSpec::eCore_arm_armv7em:
903     switch (idx) {
904     case 0:
905       arch.SetTriple("armv7em-apple-" OSNAME);
906       return true;
907     case 1:
908       arch.SetTriple("armv7-apple-" OSNAME);
909       return true;
910     case 2:
911       arch.SetTriple("armv6m-apple-" OSNAME);
912       return true;
913     case 3:
914       arch.SetTriple("armv6-apple-" OSNAME);
915       return true;
916     case 4:
917       arch.SetTriple("armv5-apple-" OSNAME);
918       return true;
919     case 5:
920       arch.SetTriple("armv4-apple-" OSNAME);
921       return true;
922     case 6:
923       arch.SetTriple("arm-apple-" OSNAME);
924       return true;
925     case 7:
926       arch.SetTriple("thumbv7em-apple-" OSNAME);
927       return true;
928     case 8:
929       arch.SetTriple("thumbv7-apple-" OSNAME);
930       return true;
931     case 9:
932       arch.SetTriple("thumbv6m-apple-" OSNAME);
933       return true;
934     case 10:
935       arch.SetTriple("thumbv6-apple-" OSNAME);
936       return true;
937     case 11:
938       arch.SetTriple("thumbv5-apple-" OSNAME);
939       return true;
940     case 12:
941       arch.SetTriple("thumbv4t-apple-" OSNAME);
942       return true;
943     case 13:
944       arch.SetTriple("thumb-apple-" OSNAME);
945       return true;
946     default:
947       break;
948     }
949     break;
950 
951   case ArchSpec::eCore_arm_armv7:
952     switch (idx) {
953     case 0:
954       arch.SetTriple("armv7-apple-" OSNAME);
955       return true;
956     case 1:
957       arch.SetTriple("armv6m-apple-" OSNAME);
958       return true;
959     case 2:
960       arch.SetTriple("armv6-apple-" OSNAME);
961       return true;
962     case 3:
963       arch.SetTriple("armv5-apple-" OSNAME);
964       return true;
965     case 4:
966       arch.SetTriple("armv4-apple-" OSNAME);
967       return true;
968     case 5:
969       arch.SetTriple("arm-apple-" OSNAME);
970       return true;
971     case 6:
972       arch.SetTriple("thumbv7-apple-" OSNAME);
973       return true;
974     case 7:
975       arch.SetTriple("thumbv6m-apple-" OSNAME);
976       return true;
977     case 8:
978       arch.SetTriple("thumbv6-apple-" OSNAME);
979       return true;
980     case 9:
981       arch.SetTriple("thumbv5-apple-" OSNAME);
982       return true;
983     case 10:
984       arch.SetTriple("thumbv4t-apple-" OSNAME);
985       return true;
986     case 11:
987       arch.SetTriple("thumb-apple-" OSNAME);
988       return true;
989     default:
990       break;
991     }
992     break;
993 
994   case ArchSpec::eCore_arm_armv6m:
995     switch (idx) {
996     case 0:
997       arch.SetTriple("armv6m-apple-" OSNAME);
998       return true;
999     case 1:
1000       arch.SetTriple("armv6-apple-" OSNAME);
1001       return true;
1002     case 2:
1003       arch.SetTriple("armv5-apple-" OSNAME);
1004       return true;
1005     case 3:
1006       arch.SetTriple("armv4-apple-" OSNAME);
1007       return true;
1008     case 4:
1009       arch.SetTriple("arm-apple-" OSNAME);
1010       return true;
1011     case 5:
1012       arch.SetTriple("thumbv6m-apple-" OSNAME);
1013       return true;
1014     case 6:
1015       arch.SetTriple("thumbv6-apple-" OSNAME);
1016       return true;
1017     case 7:
1018       arch.SetTriple("thumbv5-apple-" OSNAME);
1019       return true;
1020     case 8:
1021       arch.SetTriple("thumbv4t-apple-" OSNAME);
1022       return true;
1023     case 9:
1024       arch.SetTriple("thumb-apple-" OSNAME);
1025       return true;
1026     default:
1027       break;
1028     }
1029     break;
1030 
1031   case ArchSpec::eCore_arm_armv6:
1032     switch (idx) {
1033     case 0:
1034       arch.SetTriple("armv6-apple-" OSNAME);
1035       return true;
1036     case 1:
1037       arch.SetTriple("armv5-apple-" OSNAME);
1038       return true;
1039     case 2:
1040       arch.SetTriple("armv4-apple-" OSNAME);
1041       return true;
1042     case 3:
1043       arch.SetTriple("arm-apple-" OSNAME);
1044       return true;
1045     case 4:
1046       arch.SetTriple("thumbv6-apple-" OSNAME);
1047       return true;
1048     case 5:
1049       arch.SetTriple("thumbv5-apple-" OSNAME);
1050       return true;
1051     case 6:
1052       arch.SetTriple("thumbv4t-apple-" OSNAME);
1053       return true;
1054     case 7:
1055       arch.SetTriple("thumb-apple-" OSNAME);
1056       return true;
1057     default:
1058       break;
1059     }
1060     break;
1061 
1062   case ArchSpec::eCore_arm_armv5:
1063     switch (idx) {
1064     case 0:
1065       arch.SetTriple("armv5-apple-" OSNAME);
1066       return true;
1067     case 1:
1068       arch.SetTriple("armv4-apple-" OSNAME);
1069       return true;
1070     case 2:
1071       arch.SetTriple("arm-apple-" OSNAME);
1072       return true;
1073     case 3:
1074       arch.SetTriple("thumbv5-apple-" OSNAME);
1075       return true;
1076     case 4:
1077       arch.SetTriple("thumbv4t-apple-" OSNAME);
1078       return true;
1079     case 5:
1080       arch.SetTriple("thumb-apple-" OSNAME);
1081       return true;
1082     default:
1083       break;
1084     }
1085     break;
1086 
1087   case ArchSpec::eCore_arm_armv4:
1088     switch (idx) {
1089     case 0:
1090       arch.SetTriple("armv4-apple-" OSNAME);
1091       return true;
1092     case 1:
1093       arch.SetTriple("arm-apple-" OSNAME);
1094       return true;
1095     case 2:
1096       arch.SetTriple("thumbv4t-apple-" OSNAME);
1097       return true;
1098     case 3:
1099       arch.SetTriple("thumb-apple-" OSNAME);
1100       return true;
1101     default:
1102       break;
1103     }
1104     break;
1105   }
1106   arch.Clear();
1107   return false;
1108 }
1109 
1110 static FileSpec GetXcodeSelectPath() {
1111   static FileSpec g_xcode_select_filespec;
1112 
1113   if (!g_xcode_select_filespec) {
1114     FileSpec xcode_select_cmd("/usr/bin/xcode-select");
1115     if (FileSystem::Instance().Exists(xcode_select_cmd)) {
1116       int exit_status = -1;
1117       int signo = -1;
1118       std::string command_output;
1119       Status status =
1120           Host::RunShellCommand("/usr/bin/xcode-select --print-path",
1121                                 FileSpec(), // current working directory
1122                                 &exit_status, &signo, &command_output,
1123                                 std::chrono::seconds(2), // short timeout
1124                                 false);                  // don't run in a shell
1125       if (status.Success() && exit_status == 0 && !command_output.empty()) {
1126         size_t first_non_newline = command_output.find_last_not_of("\r\n");
1127         if (first_non_newline != std::string::npos) {
1128           command_output.erase(first_non_newline + 1);
1129         }
1130         g_xcode_select_filespec = FileSpec(command_output);
1131       }
1132     }
1133   }
1134 
1135   return g_xcode_select_filespec;
1136 }
1137 
1138 BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) {
1139   BreakpointSP bp_sp;
1140   static const char *g_bp_names[] = {
1141       "start_wqthread", "_pthread_wqthread", "_pthread_start",
1142   };
1143 
1144   static const char *g_bp_modules[] = {"libsystem_c.dylib",
1145                                        "libSystem.B.dylib"};
1146 
1147   FileSpecList bp_modules;
1148   for (size_t i = 0; i < llvm::array_lengthof(g_bp_modules); i++) {
1149     const char *bp_module = g_bp_modules[i];
1150     bp_modules.EmplaceBack(bp_module);
1151   }
1152 
1153   bool internal = true;
1154   bool hardware = false;
1155   LazyBool skip_prologue = eLazyBoolNo;
1156   bp_sp = target.CreateBreakpoint(&bp_modules, nullptr, g_bp_names,
1157                                   llvm::array_lengthof(g_bp_names),
1158                                   eFunctionNameTypeFull, eLanguageTypeUnknown,
1159                                   0, skip_prologue, internal, hardware);
1160   bp_sp->SetBreakpointKind("thread-creation");
1161 
1162   return bp_sp;
1163 }
1164 
1165 int32_t
1166 PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) {
1167   const FileSpec &shell = launch_info.GetShell();
1168   if (!shell)
1169     return 1;
1170 
1171   std::string shell_string = shell.GetPath();
1172   const char *shell_name = strrchr(shell_string.c_str(), '/');
1173   if (shell_name == nullptr)
1174     shell_name = shell_string.c_str();
1175   else
1176     shell_name++;
1177 
1178   if (strcmp(shell_name, "sh") == 0) {
1179     // /bin/sh re-exec's itself as /bin/bash requiring another resume. But it
1180     // only does this if the COMMAND_MODE environment variable is set to
1181     // "legacy".
1182     if (launch_info.GetEnvironment().lookup("COMMAND_MODE") == "legacy")
1183       return 2;
1184     return 1;
1185   } else if (strcmp(shell_name, "csh") == 0 ||
1186              strcmp(shell_name, "tcsh") == 0 ||
1187              strcmp(shell_name, "zsh") == 0) {
1188     // csh and tcsh always seem to re-exec themselves.
1189     return 2;
1190   } else
1191     return 1;
1192 }
1193 
1194 void PlatformDarwin::CalculateTrapHandlerSymbolNames() {
1195   m_trap_handlers.push_back(ConstString("_sigtramp"));
1196 }
1197 
1198 static FileSpec GetCommandLineToolsLibraryPath() {
1199   static FileSpec g_command_line_tools_filespec;
1200 
1201   if (!g_command_line_tools_filespec) {
1202     FileSpec command_line_tools_path(GetXcodeSelectPath());
1203     command_line_tools_path.AppendPathComponent("Library");
1204     if (FileSystem::Instance().Exists(command_line_tools_path)) {
1205       g_command_line_tools_filespec = command_line_tools_path;
1206     }
1207   }
1208 
1209   return g_command_line_tools_filespec;
1210 }
1211 
1212 FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator(
1213     void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef path) {
1214   SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton);
1215 
1216   FileSpec spec(path);
1217   if (XcodeSDK::SDKSupportsModules(enumerator_info->sdk_type, spec)) {
1218     enumerator_info->found_path = spec;
1219     return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
1220   }
1221 
1222   return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
1223 }
1224 
1225 FileSpec PlatformDarwin::FindSDKInXcodeForModules(XcodeSDK::Type sdk_type,
1226                                                   const FileSpec &sdks_spec) {
1227   // Look inside Xcode for the required installed iOS SDK version
1228 
1229   if (!FileSystem::Instance().IsDirectory(sdks_spec)) {
1230     return FileSpec();
1231   }
1232 
1233   const bool find_directories = true;
1234   const bool find_files = false;
1235   const bool find_other = true; // include symlinks
1236 
1237   SDKEnumeratorInfo enumerator_info;
1238 
1239   enumerator_info.sdk_type = sdk_type;
1240 
1241   FileSystem::Instance().EnumerateDirectory(
1242       sdks_spec.GetPath(), find_directories, find_files, find_other,
1243       DirectoryEnumerator, &enumerator_info);
1244 
1245   if (FileSystem::Instance().IsDirectory(enumerator_info.found_path))
1246     return enumerator_info.found_path;
1247   else
1248     return FileSpec();
1249 }
1250 
1251 FileSpec PlatformDarwin::GetSDKDirectoryForModules(XcodeSDK::Type sdk_type) {
1252   FileSpec sdks_spec = HostInfo::GetXcodeContentsDirectory();
1253   sdks_spec.AppendPathComponent("Developer");
1254   sdks_spec.AppendPathComponent("Platforms");
1255 
1256   switch (sdk_type) {
1257   case XcodeSDK::Type::MacOSX:
1258     sdks_spec.AppendPathComponent("MacOSX.platform");
1259     break;
1260   case XcodeSDK::Type::iPhoneSimulator:
1261     sdks_spec.AppendPathComponent("iPhoneSimulator.platform");
1262     break;
1263   case XcodeSDK::Type::iPhoneOS:
1264     sdks_spec.AppendPathComponent("iPhoneOS.platform");
1265     break;
1266   default:
1267     llvm_unreachable("unsupported sdk");
1268   }
1269 
1270   sdks_spec.AppendPathComponent("Developer");
1271   sdks_spec.AppendPathComponent("SDKs");
1272 
1273   if (sdk_type == XcodeSDK::Type::MacOSX) {
1274     llvm::VersionTuple version = HostInfo::GetOSVersion();
1275 
1276     if (!version.empty()) {
1277       if (XcodeSDK::SDKSupportsModules(XcodeSDK::Type::MacOSX, version)) {
1278         // If the Xcode SDKs are not available then try to use the
1279         // Command Line Tools one which is only for MacOSX.
1280         if (!FileSystem::Instance().Exists(sdks_spec)) {
1281           sdks_spec = GetCommandLineToolsLibraryPath();
1282           sdks_spec.AppendPathComponent("SDKs");
1283         }
1284 
1285         // We slightly prefer the exact SDK for this machine.  See if it is
1286         // there.
1287 
1288         FileSpec native_sdk_spec = sdks_spec;
1289         StreamString native_sdk_name;
1290         native_sdk_name.Printf("MacOSX%u.%u.sdk", version.getMajor(),
1291                                version.getMinor().getValueOr(0));
1292         native_sdk_spec.AppendPathComponent(native_sdk_name.GetString());
1293 
1294         if (FileSystem::Instance().Exists(native_sdk_spec)) {
1295           return native_sdk_spec;
1296         }
1297       }
1298     }
1299   }
1300 
1301   return FindSDKInXcodeForModules(sdk_type, sdks_spec);
1302 }
1303 
1304 std::tuple<llvm::VersionTuple, llvm::StringRef>
1305 PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) {
1306   llvm::StringRef build;
1307   llvm::StringRef version_str;
1308   llvm::StringRef build_str;
1309   std::tie(version_str, build_str) = dir.split(' ');
1310   llvm::VersionTuple version;
1311   if (!version.tryParse(version_str) ||
1312       build_str.empty()) {
1313     if (build_str.consume_front("(")) {
1314       size_t pos = build_str.find(')');
1315       build = build_str.slice(0, pos);
1316     }
1317   }
1318 
1319   return std::make_tuple(version, build);
1320 }
1321 
1322 llvm::Expected<StructuredData::DictionarySP>
1323 PlatformDarwin::FetchExtendedCrashInformation(Process &process) {
1324   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1325 
1326   StructuredData::ArraySP annotations = ExtractCrashInfoAnnotations(process);
1327 
1328   if (!annotations || !annotations->GetSize()) {
1329     LLDB_LOG(log, "Couldn't extract crash information annotations");
1330     return nullptr;
1331   }
1332 
1333   StructuredData::DictionarySP extended_crash_info =
1334       std::make_shared<StructuredData::Dictionary>();
1335 
1336   extended_crash_info->AddItem("crash-info annotations", annotations);
1337 
1338   return extended_crash_info;
1339 }
1340 
1341 StructuredData::ArraySP
1342 PlatformDarwin::ExtractCrashInfoAnnotations(Process &process) {
1343   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1344 
1345   ConstString section_name("__crash_info");
1346   Target &target = process.GetTarget();
1347   StructuredData::ArraySP array_sp = std::make_shared<StructuredData::Array>();
1348 
1349   for (ModuleSP module : target.GetImages().Modules()) {
1350     SectionList *sections = module->GetSectionList();
1351 
1352     std::string module_name = module->GetSpecificationDescription();
1353 
1354     // The DYDL module is skipped since it's always loaded when running the
1355     // binary.
1356     if (module_name == "/usr/lib/dyld")
1357       continue;
1358 
1359     if (!sections) {
1360       LLDB_LOG(log, "Module {0} doesn't have any section!", module_name);
1361       continue;
1362     }
1363 
1364     SectionSP crash_info = sections->FindSectionByName(section_name);
1365     if (!crash_info) {
1366       LLDB_LOG(log, "Module {0} doesn't have section {1}!", module_name,
1367                section_name);
1368       continue;
1369     }
1370 
1371     addr_t load_addr = crash_info->GetLoadBaseAddress(&target);
1372 
1373     if (load_addr == LLDB_INVALID_ADDRESS) {
1374       LLDB_LOG(log, "Module {0} has an invalid '{1}' section load address: {2}",
1375                module_name, section_name, load_addr);
1376       continue;
1377     }
1378 
1379     Status error;
1380     CrashInfoAnnotations annotations;
1381     size_t expected_size = sizeof(CrashInfoAnnotations);
1382     size_t bytes_read = process.ReadMemoryFromInferior(load_addr, &annotations,
1383                                                        expected_size, error);
1384 
1385     if (expected_size != bytes_read || error.Fail()) {
1386       LLDB_LOG(log, "Failed to read {0} section from memory in module {1}: {2}",
1387                section_name, module_name, error);
1388       continue;
1389     }
1390 
1391     // initial support added for version 5
1392     if (annotations.version < 5) {
1393       LLDB_LOG(log,
1394                "Annotation version lower than 5 unsupported! Module {0} has "
1395                "version {1} instead.",
1396                module_name, annotations.version);
1397       continue;
1398     }
1399 
1400     if (!annotations.message) {
1401       LLDB_LOG(log, "No message available for module {0}.", module_name);
1402       continue;
1403     }
1404 
1405     std::string message;
1406     bytes_read =
1407         process.ReadCStringFromMemory(annotations.message, message, error);
1408 
1409     if (message.empty() || bytes_read != message.size() || error.Fail()) {
1410       LLDB_LOG(log, "Failed to read the message from memory in module {0}: {1}",
1411                module_name, error);
1412       continue;
1413     }
1414 
1415     // Remove trailing newline from message
1416     if (message.back() == '\n')
1417       message.pop_back();
1418 
1419     if (!annotations.message2)
1420       LLDB_LOG(log, "No message2 available for module {0}.", module_name);
1421 
1422     std::string message2;
1423     bytes_read =
1424         process.ReadCStringFromMemory(annotations.message2, message2, error);
1425 
1426     if (!message2.empty() && bytes_read == message2.size() && error.Success())
1427       if (message2.back() == '\n')
1428         message2.pop_back();
1429 
1430     StructuredData::DictionarySP entry_sp =
1431         std::make_shared<StructuredData::Dictionary>();
1432 
1433     entry_sp->AddStringItem("image", module->GetFileSpec().GetPath(false));
1434     entry_sp->AddStringItem("uuid", module->GetUUID().GetAsString());
1435     entry_sp->AddStringItem("message", message);
1436     entry_sp->AddStringItem("message2", message2);
1437     entry_sp->AddIntegerItem("abort-cause", annotations.abort_cause);
1438 
1439     array_sp->AddItem(entry_sp);
1440   }
1441 
1442   return array_sp;
1443 }
1444 
1445 void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
1446     Target *target, std::vector<std::string> &options, XcodeSDK::Type sdk_type) {
1447   const std::vector<std::string> apple_arguments = {
1448       "-x",       "objective-c++", "-fobjc-arc",
1449       "-fblocks", "-D_ISO646_H",   "-D__ISO646_H",
1450       "-fgnuc-version=4.2.1"};
1451 
1452   options.insert(options.end(), apple_arguments.begin(), apple_arguments.end());
1453 
1454   StreamString minimum_version_option;
1455   bool use_current_os_version = false;
1456   switch (sdk_type) {
1457   case XcodeSDK::Type::iPhoneOS:
1458 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
1459     use_current_os_version = true;
1460 #else
1461     use_current_os_version = false;
1462 #endif
1463     break;
1464 
1465   case XcodeSDK::Type::iPhoneSimulator:
1466     use_current_os_version = false;
1467     break;
1468 
1469   case XcodeSDK::Type::MacOSX:
1470 #if defined(__i386__) || defined(__x86_64__)
1471     use_current_os_version = true;
1472 #else
1473     use_current_os_version = false;
1474 #endif
1475     break;
1476   default:
1477     break;
1478   }
1479 
1480   llvm::VersionTuple version;
1481   if (use_current_os_version)
1482     version = GetOSVersion();
1483   else if (target) {
1484     // Our OS doesn't match our executable so we need to get the min OS version
1485     // from the object file
1486     ModuleSP exe_module_sp = target->GetExecutableModule();
1487     if (exe_module_sp) {
1488       ObjectFile *object_file = exe_module_sp->GetObjectFile();
1489       if (object_file)
1490         version = object_file->GetMinimumOSVersion();
1491     }
1492   }
1493   // Only add the version-min options if we got a version from somewhere
1494   if (!version.empty()) {
1495     switch (sdk_type) {
1496     case XcodeSDK::Type::iPhoneOS:
1497       minimum_version_option.PutCString("-mios-version-min=");
1498       minimum_version_option.PutCString(version.getAsString());
1499       break;
1500     case XcodeSDK::Type::iPhoneSimulator:
1501       minimum_version_option.PutCString("-mios-simulator-version-min=");
1502       minimum_version_option.PutCString(version.getAsString());
1503       break;
1504     case XcodeSDK::Type::MacOSX:
1505       minimum_version_option.PutCString("-mmacosx-version-min=");
1506       minimum_version_option.PutCString(version.getAsString());
1507       break;
1508     default:
1509       llvm_unreachable("unsupported sdk");
1510     }
1511     options.push_back(std::string(minimum_version_option.GetString()));
1512   }
1513 
1514   FileSpec sysroot_spec;
1515   // Scope for mutex locker below
1516   {
1517     std::lock_guard<std::mutex> guard(m_mutex);
1518     sysroot_spec = GetSDKDirectoryForModules(sdk_type);
1519   }
1520 
1521   if (FileSystem::Instance().IsDirectory(sysroot_spec.GetPath())) {
1522     options.push_back("-isysroot");
1523     options.push_back(sysroot_spec.GetPath());
1524   }
1525 }
1526 
1527 ConstString PlatformDarwin::GetFullNameForDylib(ConstString basename) {
1528   if (basename.IsEmpty())
1529     return basename;
1530 
1531   StreamString stream;
1532   stream.Printf("lib%s.dylib", basename.GetCString());
1533   return ConstString(stream.GetString());
1534 }
1535 
1536 llvm::VersionTuple PlatformDarwin::GetOSVersion(Process *process) {
1537   if (process && strstr(GetPluginName().GetCString(), "-simulator")) {
1538     lldb_private::ProcessInstanceInfo proc_info;
1539     if (Host::GetProcessInfo(process->GetID(), proc_info)) {
1540       const Environment &env = proc_info.GetEnvironment();
1541 
1542       llvm::VersionTuple result;
1543       if (!result.tryParse(env.lookup("SIMULATOR_RUNTIME_VERSION")))
1544         return result;
1545 
1546       std::string dyld_root_path = env.lookup("DYLD_ROOT_PATH");
1547       if (!dyld_root_path.empty()) {
1548         dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist";
1549         ApplePropertyList system_version_plist(dyld_root_path.c_str());
1550         std::string product_version;
1551         if (system_version_plist.GetValueAsString("ProductVersion",
1552                                                   product_version)) {
1553           if (!result.tryParse(product_version))
1554             return result;
1555         }
1556       }
1557     }
1558     // For simulator platforms, do NOT call back through
1559     // Platform::GetOSVersion() as it might call Process::GetHostOSVersion()
1560     // which we don't want as it will be incorrect
1561     return llvm::VersionTuple();
1562   }
1563 
1564   return Platform::GetOSVersion(process);
1565 }
1566 
1567 lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) {
1568   // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled
1569   // in with any executable directories that should be searched.
1570   static std::vector<FileSpec> g_executable_dirs;
1571 
1572   // Find the global list of directories that we will search for executables
1573   // once so we don't keep doing the work over and over.
1574   static llvm::once_flag g_once_flag;
1575   llvm::call_once(g_once_flag, []() {
1576 
1577     // When locating executables, trust the DEVELOPER_DIR first if it is set
1578     FileSpec xcode_contents_dir = HostInfo::GetXcodeContentsDirectory();
1579     if (xcode_contents_dir) {
1580       FileSpec xcode_lldb_resources = xcode_contents_dir;
1581       xcode_lldb_resources.AppendPathComponent("SharedFrameworks");
1582       xcode_lldb_resources.AppendPathComponent("LLDB.framework");
1583       xcode_lldb_resources.AppendPathComponent("Resources");
1584       if (FileSystem::Instance().Exists(xcode_lldb_resources)) {
1585         FileSpec dir;
1586         dir.GetDirectory().SetCString(xcode_lldb_resources.GetPath().c_str());
1587         g_executable_dirs.push_back(dir);
1588       }
1589     }
1590     // Xcode might not be installed so we also check for the Command Line Tools.
1591     FileSpec command_line_tools_dir = GetCommandLineToolsLibraryPath();
1592     if (command_line_tools_dir) {
1593       FileSpec cmd_line_lldb_resources = command_line_tools_dir;
1594       cmd_line_lldb_resources.AppendPathComponent("PrivateFrameworks");
1595       cmd_line_lldb_resources.AppendPathComponent("LLDB.framework");
1596       cmd_line_lldb_resources.AppendPathComponent("Resources");
1597       if (FileSystem::Instance().Exists(cmd_line_lldb_resources)) {
1598         FileSpec dir;
1599         dir.GetDirectory().SetCString(
1600             cmd_line_lldb_resources.GetPath().c_str());
1601         g_executable_dirs.push_back(dir);
1602       }
1603     }
1604   });
1605 
1606   // Now search the global list of executable directories for the executable we
1607   // are looking for
1608   for (const auto &executable_dir : g_executable_dirs) {
1609     FileSpec executable_file;
1610     executable_file.GetDirectory() = executable_dir.GetDirectory();
1611     executable_file.GetFilename().SetCString(basename);
1612     if (FileSystem::Instance().Exists(executable_file))
1613       return executable_file;
1614   }
1615 
1616   return FileSpec();
1617 }
1618 
1619 lldb_private::Status
1620 PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) {
1621   // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr if
1622   // the OS_ACTIVITY_DT_MODE environment variable is set.  (It doesn't require
1623   // any specific value; rather, it just needs to exist). We will set it here
1624   // as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag is not set.  Xcode
1625   // makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell
1626   // LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they
1627   // specifically want it unset.
1628   const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE";
1629   auto &env_vars = launch_info.GetEnvironment();
1630   if (!env_vars.count(disable_env_var)) {
1631     // We want to make sure that OS_ACTIVITY_DT_MODE is set so that we get
1632     // os_log and NSLog messages mirrored to the target process stderr.
1633     env_vars.try_emplace("OS_ACTIVITY_DT_MODE", "enable");
1634   }
1635 
1636   // Let our parent class do the real launching.
1637   return PlatformPOSIX::LaunchProcess(launch_info);
1638 }
1639 
1640 lldb_private::Status PlatformDarwin::FindBundleBinaryInExecSearchPaths(
1641     const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
1642     const FileSpecList *module_search_paths_ptr,
1643     llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) {
1644   const FileSpec &platform_file = module_spec.GetFileSpec();
1645   // See if the file is present in any of the module_search_paths_ptr
1646   // directories.
1647   if (!module_sp && module_search_paths_ptr && platform_file) {
1648     // create a vector of all the file / directory names in platform_file e.g.
1649     // this might be
1650     // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
1651     //
1652     // We'll need to look in the module_search_paths_ptr directories for both
1653     // "UIFoundation" and "UIFoundation.framework" -- most likely the latter
1654     // will be the one we find there.
1655 
1656     FileSpec platform_pull_upart(platform_file);
1657     std::vector<std::string> path_parts;
1658     path_parts.push_back(
1659         platform_pull_upart.GetLastPathComponent().AsCString());
1660     while (platform_pull_upart.RemoveLastPathComponent()) {
1661       ConstString part = platform_pull_upart.GetLastPathComponent();
1662       path_parts.push_back(part.AsCString());
1663     }
1664     const size_t path_parts_size = path_parts.size();
1665 
1666     size_t num_module_search_paths = module_search_paths_ptr->GetSize();
1667     for (size_t i = 0; i < num_module_search_paths; ++i) {
1668       Log *log_verbose = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
1669       LLDB_LOGF(
1670           log_verbose,
1671           "PlatformRemoteDarwinDevice::GetSharedModule searching for binary in "
1672           "search-path %s",
1673           module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str());
1674       // Create a new FileSpec with this module_search_paths_ptr plus just the
1675       // filename ("UIFoundation"), then the parent dir plus filename
1676       // ("UIFoundation.framework/UIFoundation") etc - up to four names (to
1677       // handle "Foo.framework/Contents/MacOS/Foo")
1678 
1679       for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) {
1680         FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));
1681 
1682         // Add the components backwards.  For
1683         // .../PrivateFrameworks/UIFoundation.framework/UIFoundation path_parts
1684         // is
1685         //   [0] UIFoundation
1686         //   [1] UIFoundation.framework
1687         //   [2] PrivateFrameworks
1688         //
1689         // and if 'j' is 2, we want to append path_parts[1] and then
1690         // path_parts[0], aka 'UIFoundation.framework/UIFoundation', to the
1691         // module_search_paths_ptr path.
1692 
1693         for (int k = j; k >= 0; --k) {
1694           path_to_try.AppendPathComponent(path_parts[k]);
1695         }
1696 
1697         if (FileSystem::Instance().Exists(path_to_try)) {
1698           ModuleSpec new_module_spec(module_spec);
1699           new_module_spec.GetFileSpec() = path_to_try;
1700           Status new_error(
1701               Platform::GetSharedModule(new_module_spec, process, module_sp,
1702                                         nullptr, old_modules, did_create_ptr));
1703 
1704           if (module_sp) {
1705             module_sp->SetPlatformFileSpec(path_to_try);
1706             return new_error;
1707           }
1708         }
1709       }
1710     }
1711   }
1712   return Status();
1713 }
1714 
1715 std::string PlatformDarwin::FindComponentInPath(llvm::StringRef path,
1716                                                 llvm::StringRef component) {
1717   auto begin = llvm::sys::path::begin(path);
1718   auto end = llvm::sys::path::end(path);
1719   for (auto it = begin; it != end; ++it) {
1720     if (it->contains(component)) {
1721       llvm::SmallString<128> buffer;
1722       llvm::sys::path::append(buffer, begin, ++it,
1723                               llvm::sys::path::Style::posix);
1724       return buffer.str().str();
1725     }
1726   }
1727   return {};
1728 }
1729 
1730 FileSpec PlatformDarwin::GetCurrentToolchainDirectory() {
1731   if (FileSpec fspec = HostInfo::GetShlibDir())
1732     return FileSpec(FindComponentInPath(fspec.GetPath(), ".xctoolchain"));
1733   return {};
1734 }
1735 
1736 FileSpec PlatformDarwin::GetCurrentCommandLineToolsDirectory() {
1737   if (FileSpec fspec = HostInfo::GetShlibDir())
1738     return FileSpec(FindComponentInPath(fspec.GetPath(), "CommandLineTools"));
1739   return {};
1740 }
1741