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