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