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/Core/Timer.h"
28 #include "lldb/Host/Host.h"
29 #include "lldb/Host/HostInfo.h"
30 #include "lldb/Host/Symbols.h"
31 #include "lldb/Host/XML.h"
32 #include "lldb/Interpreter/CommandInterpreter.h"
33 #include "lldb/Symbol/ObjectFile.h"
34 #include "lldb/Symbol/SymbolFile.h"
35 #include "lldb/Symbol/SymbolVendor.h"
36 #include "lldb/Target/Platform.h"
37 #include "lldb/Target/Process.h"
38 #include "lldb/Target/Target.h"
39 #include "lldb/Utility/DataBufferLLVM.h"
40 #include "lldb/Utility/Log.h"
41 #include "lldb/Utility/Status.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 const char *PlatformDarwin::GetDeveloperDirectory() {
1136   std::lock_guard<std::mutex> guard(m_mutex);
1137   if (m_developer_directory.empty()) {
1138     bool developer_dir_path_valid = false;
1139     char developer_dir_path[PATH_MAX];
1140     FileSpec temp_file_spec;
1141     if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, temp_file_spec)) {
1142       if (temp_file_spec.GetPath(developer_dir_path,
1143                                  sizeof(developer_dir_path))) {
1144         char *shared_frameworks =
1145             strstr(developer_dir_path, "/SharedFrameworks/LLDB.framework");
1146         if (shared_frameworks) {
1147           ::snprintf(shared_frameworks,
1148                      sizeof(developer_dir_path) -
1149                          (shared_frameworks - developer_dir_path),
1150                      "/Developer");
1151           developer_dir_path_valid = true;
1152         } else {
1153           char *lib_priv_frameworks = strstr(
1154               developer_dir_path, "/Library/PrivateFrameworks/LLDB.framework");
1155           if (lib_priv_frameworks) {
1156             *lib_priv_frameworks = '\0';
1157             developer_dir_path_valid = true;
1158           }
1159         }
1160       }
1161     }
1162 
1163     if (!developer_dir_path_valid) {
1164       std::string xcode_dir_path;
1165       const char *xcode_select_prefix_dir = getenv("XCODE_SELECT_PREFIX_DIR");
1166       if (xcode_select_prefix_dir)
1167         xcode_dir_path.append(xcode_select_prefix_dir);
1168       xcode_dir_path.append("/usr/share/xcode-select/xcode_dir_path");
1169       temp_file_spec.SetFile(xcode_dir_path, false);
1170       auto dir_buffer =
1171           DataBufferLLVM::CreateFromPath(temp_file_spec.GetPath(), true);
1172       if (dir_buffer && dir_buffer->GetByteSize() > 0) {
1173         llvm::StringRef path_ref(dir_buffer->GetChars());
1174         // Trim tailing newlines and make sure there is enough room for a null
1175         // terminator.
1176         path_ref =
1177             path_ref.rtrim("\r\n").take_front(sizeof(developer_dir_path) - 1);
1178         ::memcpy(developer_dir_path, path_ref.data(), path_ref.size());
1179         developer_dir_path[path_ref.size()] = '\0';
1180         developer_dir_path_valid = true;
1181       }
1182     }
1183 
1184     if (!developer_dir_path_valid) {
1185       FileSpec xcode_select_cmd("/usr/bin/xcode-select", false);
1186       if (xcode_select_cmd.Exists()) {
1187         int exit_status = -1;
1188         int signo = -1;
1189         std::string command_output;
1190         Status error =
1191             Host::RunShellCommand("/usr/bin/xcode-select --print-path",
1192                                   NULL, // current working directory
1193                                   &exit_status, &signo, &command_output,
1194                                   2,      // short timeout
1195                                   false); // don't run in a shell
1196         if (error.Success() && exit_status == 0 && !command_output.empty()) {
1197           const char *cmd_output_ptr = command_output.c_str();
1198           developer_dir_path[sizeof(developer_dir_path) - 1] = '\0';
1199           size_t i;
1200           for (i = 0; i < sizeof(developer_dir_path) - 1; i++) {
1201             if (cmd_output_ptr[i] == '\r' || cmd_output_ptr[i] == '\n' ||
1202                 cmd_output_ptr[i] == '\0')
1203               break;
1204             developer_dir_path[i] = cmd_output_ptr[i];
1205           }
1206           developer_dir_path[i] = '\0';
1207 
1208           FileSpec devel_dir(developer_dir_path, false);
1209           if (llvm::sys::fs::is_directory(devel_dir.GetPath())) {
1210             developer_dir_path_valid = true;
1211           }
1212         }
1213       }
1214     }
1215 
1216     if (developer_dir_path_valid) {
1217       temp_file_spec.SetFile(developer_dir_path, false);
1218       if (temp_file_spec.Exists()) {
1219         m_developer_directory.assign(developer_dir_path);
1220         return m_developer_directory.c_str();
1221       }
1222     }
1223     // Assign a single NULL character so we know we tried to find the device
1224     // support directory and we don't keep trying to find it over and over.
1225     m_developer_directory.assign(1, '\0');
1226   }
1227 
1228   // We should have put a single NULL character into m_developer_directory
1229   // or it should have a valid path if the code gets here
1230   assert(m_developer_directory.empty() == false);
1231   if (m_developer_directory[0])
1232     return m_developer_directory.c_str();
1233   return NULL;
1234 }
1235 
1236 BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) {
1237   BreakpointSP bp_sp;
1238   static const char *g_bp_names[] = {
1239       "start_wqthread", "_pthread_wqthread", "_pthread_start",
1240   };
1241 
1242   static const char *g_bp_modules[] = {"libsystem_c.dylib",
1243                                        "libSystem.B.dylib"};
1244 
1245   FileSpecList bp_modules;
1246   for (size_t i = 0; i < llvm::array_lengthof(g_bp_modules); i++) {
1247     const char *bp_module = g_bp_modules[i];
1248     bp_modules.Append(FileSpec(bp_module, false));
1249   }
1250 
1251   bool internal = true;
1252   bool hardware = false;
1253   LazyBool skip_prologue = eLazyBoolNo;
1254   bp_sp = target.CreateBreakpoint(&bp_modules, NULL, g_bp_names,
1255                                   llvm::array_lengthof(g_bp_names),
1256                                   eFunctionNameTypeFull, eLanguageTypeUnknown,
1257                                   0, skip_prologue, internal, hardware);
1258   bp_sp->SetBreakpointKind("thread-creation");
1259 
1260   return bp_sp;
1261 }
1262 
1263 int32_t
1264 PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) {
1265   const FileSpec &shell = launch_info.GetShell();
1266   if (!shell)
1267     return 1;
1268 
1269   std::string shell_string = shell.GetPath();
1270   const char *shell_name = strrchr(shell_string.c_str(), '/');
1271   if (shell_name == NULL)
1272     shell_name = shell_string.c_str();
1273   else
1274     shell_name++;
1275 
1276   if (strcmp(shell_name, "sh") == 0) {
1277     // /bin/sh re-exec's itself as /bin/bash requiring another resume.
1278     // But it only does this if the COMMAND_MODE environment variable
1279     // is set to "legacy".
1280     const char **envp =
1281         launch_info.GetEnvironmentEntries().GetConstArgumentVector();
1282     if (envp != NULL) {
1283       for (int i = 0; envp[i] != NULL; i++) {
1284         if (strcmp(envp[i], "COMMAND_MODE=legacy") == 0)
1285           return 2;
1286       }
1287     }
1288     return 1;
1289   } else if (strcmp(shell_name, "csh") == 0 ||
1290              strcmp(shell_name, "tcsh") == 0 ||
1291              strcmp(shell_name, "zsh") == 0) {
1292     // csh and tcsh always seem to re-exec themselves.
1293     return 2;
1294   } else
1295     return 1;
1296 }
1297 
1298 void PlatformDarwin::CalculateTrapHandlerSymbolNames() {
1299   m_trap_handlers.push_back(ConstString("_sigtramp"));
1300 }
1301 
1302 static const char *const sdk_strings[] = {
1303     "MacOSX", "iPhoneSimulator", "iPhoneOS",
1304 };
1305 
1306 static FileSpec CheckPathForXcode(const FileSpec &fspec) {
1307   if (fspec.Exists()) {
1308     const char substr[] = ".app/Contents/";
1309 
1310     std::string path_to_shlib = fspec.GetPath();
1311     size_t pos = path_to_shlib.rfind(substr);
1312     if (pos != std::string::npos) {
1313       path_to_shlib.erase(pos + strlen(substr));
1314       FileSpec ret(path_to_shlib, false);
1315 
1316       FileSpec xcode_binary_path = ret;
1317       xcode_binary_path.AppendPathComponent("MacOS");
1318       xcode_binary_path.AppendPathComponent("Xcode");
1319 
1320       if (xcode_binary_path.Exists()) {
1321         return ret;
1322       }
1323     }
1324   }
1325   return FileSpec();
1326 }
1327 
1328 static FileSpec GetXcodeContentsPath() {
1329   static FileSpec g_xcode_filespec;
1330   static llvm::once_flag g_once_flag;
1331   llvm::call_once(g_once_flag, []() {
1332 
1333     FileSpec fspec;
1334 
1335     // First get the program file spec. If lldb.so or LLDB.framework is running
1336     // in a program and that program is Xcode, the path returned with be the
1337     // path
1338     // to Xcode.app/Contents/MacOS/Xcode, so this will be the correct Xcode to
1339     // use.
1340     fspec = HostInfo::GetProgramFileSpec();
1341 
1342     if (fspec) {
1343       // Ignore the current binary if it is python.
1344       std::string basename_lower = fspec.GetFilename().GetCString();
1345       std::transform(basename_lower.begin(), basename_lower.end(),
1346                      basename_lower.begin(), tolower);
1347       if (basename_lower != "python") {
1348         g_xcode_filespec = CheckPathForXcode(fspec);
1349       }
1350     }
1351 
1352     // Next check DEVELOPER_DIR environment variable
1353     if (!g_xcode_filespec) {
1354       const char *developer_dir_env_var = getenv("DEVELOPER_DIR");
1355       if (developer_dir_env_var && developer_dir_env_var[0]) {
1356         g_xcode_filespec =
1357             CheckPathForXcode(FileSpec(developer_dir_env_var, true));
1358       }
1359 
1360       // Fall back to using "xcrun" to find the selected Xcode
1361       if (!g_xcode_filespec) {
1362         int status = 0;
1363         int signo = 0;
1364         std::string output;
1365         const char *command = "/usr/bin/xcode-select -p";
1366         lldb_private::Status error = Host::RunShellCommand(
1367             command, // shell command to run
1368             NULL,    // current working directory
1369             &status, // Put the exit status of the process in here
1370             &signo,  // Put the signal that caused the process to exit in here
1371             &output, // Get the output from the command and place it in this
1372                      // string
1373             3);      // Timeout in seconds to wait for shell program to finish
1374         if (status == 0 && !output.empty()) {
1375           size_t first_non_newline = output.find_last_not_of("\r\n");
1376           if (first_non_newline != std::string::npos) {
1377             output.erase(first_non_newline + 1);
1378           }
1379           output.append("/..");
1380 
1381           g_xcode_filespec = CheckPathForXcode(FileSpec(output, false));
1382         }
1383       }
1384     }
1385   });
1386 
1387   return g_xcode_filespec;
1388 }
1389 
1390 bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type, uint32_t major,
1391                                         uint32_t minor, uint32_t micro) {
1392   switch (sdk_type) {
1393   case SDKType::MacOSX:
1394     if (major > 10 || (major == 10 && minor >= 10))
1395       return true;
1396     break;
1397   case SDKType::iPhoneOS:
1398   case SDKType::iPhoneSimulator:
1399     if (major >= 8)
1400       return true;
1401     break;
1402   }
1403 
1404   return false;
1405 }
1406 
1407 bool PlatformDarwin::SDKSupportsModules(SDKType desired_type,
1408                                         const FileSpec &sdk_path) {
1409   ConstString last_path_component = sdk_path.GetLastPathComponent();
1410 
1411   if (last_path_component) {
1412     const llvm::StringRef sdk_name = last_path_component.GetStringRef();
1413 
1414     llvm::StringRef version_part;
1415 
1416     if (sdk_name.startswith(sdk_strings[(int)desired_type])) {
1417       version_part =
1418           sdk_name.drop_front(strlen(sdk_strings[(int)desired_type]));
1419     } else {
1420       return false;
1421     }
1422 
1423     const size_t major_dot_offset = version_part.find('.');
1424     if (major_dot_offset == llvm::StringRef::npos)
1425       return false;
1426 
1427     const llvm::StringRef major_version =
1428         version_part.slice(0, major_dot_offset);
1429     const llvm::StringRef minor_part =
1430         version_part.drop_front(major_dot_offset + 1);
1431 
1432     const size_t minor_dot_offset = minor_part.find('.');
1433     if (minor_dot_offset == llvm::StringRef::npos)
1434       return false;
1435 
1436     const llvm::StringRef minor_version = minor_part.slice(0, minor_dot_offset);
1437 
1438     unsigned int major = 0;
1439     unsigned int minor = 0;
1440     unsigned int micro = 0;
1441 
1442     if (major_version.getAsInteger(10, major))
1443       return false;
1444 
1445     if (minor_version.getAsInteger(10, minor))
1446       return false;
1447 
1448     return SDKSupportsModules(desired_type, major, minor, micro);
1449   }
1450 
1451   return false;
1452 }
1453 
1454 FileSpec::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator(
1455     void *baton, llvm::sys::fs::file_type file_type, const FileSpec &spec) {
1456   SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton);
1457 
1458   if (SDKSupportsModules(enumerator_info->sdk_type, spec)) {
1459     enumerator_info->found_path = spec;
1460     return FileSpec::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
1461   }
1462 
1463   return FileSpec::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
1464 }
1465 
1466 FileSpec PlatformDarwin::FindSDKInXcodeForModules(SDKType sdk_type,
1467                                                   const FileSpec &sdks_spec) {
1468   // Look inside Xcode for the required installed iOS SDK version
1469 
1470   if (!llvm::sys::fs::is_directory(sdks_spec.GetPath())) {
1471     return FileSpec();
1472   }
1473 
1474   const bool find_directories = true;
1475   const bool find_files = false;
1476   const bool find_other = true; // include symlinks
1477 
1478   SDKEnumeratorInfo enumerator_info;
1479 
1480   enumerator_info.sdk_type = sdk_type;
1481 
1482   FileSpec::EnumerateDirectory(sdks_spec.GetPath(), find_directories,
1483                                find_files, find_other, DirectoryEnumerator,
1484                                &enumerator_info);
1485 
1486   if (llvm::sys::fs::is_directory(enumerator_info.found_path.GetPath()))
1487     return enumerator_info.found_path;
1488   else
1489     return FileSpec();
1490 }
1491 
1492 FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) {
1493   switch (sdk_type) {
1494   case SDKType::MacOSX:
1495   case SDKType::iPhoneSimulator:
1496   case SDKType::iPhoneOS:
1497     break;
1498   }
1499 
1500   FileSpec sdks_spec = GetXcodeContentsPath();
1501   sdks_spec.AppendPathComponent("Developer");
1502   sdks_spec.AppendPathComponent("Platforms");
1503 
1504   switch (sdk_type) {
1505   case SDKType::MacOSX:
1506     sdks_spec.AppendPathComponent("MacOSX.platform");
1507     break;
1508   case SDKType::iPhoneSimulator:
1509     sdks_spec.AppendPathComponent("iPhoneSimulator.platform");
1510     break;
1511   case SDKType::iPhoneOS:
1512     sdks_spec.AppendPathComponent("iPhoneOS.platform");
1513     break;
1514   }
1515 
1516   sdks_spec.AppendPathComponent("Developer");
1517   sdks_spec.AppendPathComponent("SDKs");
1518 
1519   if (sdk_type == SDKType::MacOSX) {
1520     uint32_t major = 0;
1521     uint32_t minor = 0;
1522     uint32_t micro = 0;
1523 
1524     if (HostInfo::GetOSVersion(major, minor, micro)) {
1525       if (SDKSupportsModules(SDKType::MacOSX, major, minor, micro)) {
1526         // We slightly prefer the exact SDK for this machine.  See if it is
1527         // there.
1528 
1529         FileSpec native_sdk_spec = sdks_spec;
1530         StreamString native_sdk_name;
1531         native_sdk_name.Printf("MacOSX%u.%u.sdk", major, minor);
1532         native_sdk_spec.AppendPathComponent(native_sdk_name.GetString());
1533 
1534         if (native_sdk_spec.Exists()) {
1535           return native_sdk_spec;
1536         }
1537       }
1538     }
1539   }
1540 
1541   return FindSDKInXcodeForModules(sdk_type, sdks_spec);
1542 }
1543 
1544 std::tuple<uint32_t, uint32_t, uint32_t, llvm::StringRef>
1545 PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) {
1546   uint32_t major, minor, update;
1547   llvm::StringRef build;
1548   llvm::StringRef version_str;
1549   llvm::StringRef build_str;
1550   std::tie(version_str, build_str) = dir.split(' ');
1551   if (Args::StringToVersion(version_str, major, minor, update) ||
1552       build_str.empty()) {
1553     if (build_str.consume_front("(")) {
1554       size_t pos = build_str.find(')');
1555       build = build_str.slice(0, pos);
1556     }
1557   }
1558 
1559   return std::make_tuple(major, minor, update, build);
1560 }
1561 
1562 void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
1563     Target *target, std::vector<std::string> &options, SDKType sdk_type) {
1564   const std::vector<std::string> apple_arguments = {
1565       "-x",       "objective-c++", "-fobjc-arc",
1566       "-fblocks", "-D_ISO646_H",   "-D__ISO646_H"};
1567 
1568   options.insert(options.end(), apple_arguments.begin(), apple_arguments.end());
1569 
1570   StreamString minimum_version_option;
1571   uint32_t versions[3] = {0, 0, 0};
1572   bool use_current_os_version = false;
1573   switch (sdk_type) {
1574   case SDKType::iPhoneOS:
1575 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
1576     use_current_os_version = true;
1577 #else
1578     use_current_os_version = false;
1579 #endif
1580     break;
1581 
1582   case SDKType::iPhoneSimulator:
1583     use_current_os_version = false;
1584     break;
1585 
1586   case SDKType::MacOSX:
1587 #if defined(__i386__) || defined(__x86_64__)
1588     use_current_os_version = true;
1589 #else
1590     use_current_os_version = false;
1591 #endif
1592     break;
1593   }
1594 
1595   bool versions_valid = false;
1596   if (use_current_os_version)
1597     versions_valid = GetOSVersion(versions[0], versions[1], versions[2]);
1598   else if (target) {
1599     // Our OS doesn't match our executable so we need to get the min OS version
1600     // from the object file
1601     ModuleSP exe_module_sp = target->GetExecutableModule();
1602     if (exe_module_sp) {
1603       ObjectFile *object_file = exe_module_sp->GetObjectFile();
1604       if (object_file)
1605         versions_valid = object_file->GetMinimumOSVersion(versions, 3) > 0;
1606     }
1607   }
1608   // Only add the version-min options if we got a version from somewhere
1609   if (versions_valid && versions[0] != UINT32_MAX) {
1610     // Make any invalid versions be zero if needed
1611     if (versions[1] == UINT32_MAX)
1612       versions[1] = 0;
1613     if (versions[2] == UINT32_MAX)
1614       versions[2] = 0;
1615 
1616     switch (sdk_type) {
1617     case SDKType::iPhoneOS:
1618       minimum_version_option.PutCString("-mios-version-min=");
1619       minimum_version_option.PutCString(
1620           clang::VersionTuple(versions[0], versions[1], versions[2])
1621               .getAsString());
1622       break;
1623     case SDKType::iPhoneSimulator:
1624       minimum_version_option.PutCString("-mios-simulator-version-min=");
1625       minimum_version_option.PutCString(
1626           clang::VersionTuple(versions[0], versions[1], versions[2])
1627               .getAsString());
1628       break;
1629     case SDKType::MacOSX:
1630       minimum_version_option.PutCString("-mmacosx-version-min=");
1631       minimum_version_option.PutCString(
1632           clang::VersionTuple(versions[0], versions[1], versions[2])
1633               .getAsString());
1634     }
1635     options.push_back(minimum_version_option.GetString());
1636   }
1637 
1638   FileSpec sysroot_spec;
1639   // Scope for mutex locker below
1640   {
1641     std::lock_guard<std::mutex> guard(m_mutex);
1642     sysroot_spec = GetSDKDirectoryForModules(sdk_type);
1643   }
1644 
1645   if (llvm::sys::fs::is_directory(sysroot_spec.GetPath())) {
1646     options.push_back("-isysroot");
1647     options.push_back(sysroot_spec.GetPath());
1648   }
1649 }
1650 
1651 ConstString PlatformDarwin::GetFullNameForDylib(ConstString basename) {
1652   if (basename.IsEmpty())
1653     return basename;
1654 
1655   StreamString stream;
1656   stream.Printf("lib%s.dylib", basename.GetCString());
1657   return ConstString(stream.GetString());
1658 }
1659 
1660 bool PlatformDarwin::GetOSVersion(uint32_t &major, uint32_t &minor,
1661                                   uint32_t &update, Process *process) {
1662   if (process && strstr(GetPluginName().GetCString(), "-simulator")) {
1663     lldb_private::ProcessInstanceInfo proc_info;
1664     if (Host::GetProcessInfo(process->GetID(), proc_info)) {
1665       Args &env = proc_info.GetEnvironmentEntries();
1666       const size_t n = env.GetArgumentCount();
1667       const llvm::StringRef k_runtime_version("SIMULATOR_RUNTIME_VERSION=");
1668       const llvm::StringRef k_dyld_root_path("DYLD_ROOT_PATH=");
1669       std::string dyld_root_path;
1670 
1671       for (size_t i = 0; i < n; ++i) {
1672         const char *env_cstr = env.GetArgumentAtIndex(i);
1673         if (env_cstr) {
1674           llvm::StringRef env_str(env_cstr);
1675           if (env_str.consume_front(k_runtime_version)) {
1676             if (Args::StringToVersion(env_str, major, minor, update))
1677               return true;
1678           } else if (env_str.consume_front(k_dyld_root_path)) {
1679             dyld_root_path = env_str;
1680           }
1681         }
1682       }
1683 
1684       if (!dyld_root_path.empty()) {
1685         dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist";
1686         ApplePropertyList system_version_plist(dyld_root_path.c_str());
1687         std::string product_version;
1688         if (system_version_plist.GetValueAsString("ProductVersion",
1689                                                   product_version)) {
1690           return Args::StringToVersion(product_version, major, minor, update);
1691         }
1692       }
1693     }
1694     // For simulator platforms, do NOT call back through
1695     // Platform::GetOSVersion()
1696     // as it might call Process::GetHostOSVersion() which we don't want as it
1697     // will be
1698     // incorrect
1699     return false;
1700   }
1701 
1702   return Platform::GetOSVersion(major, minor, update, process);
1703 }
1704 
1705 lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) {
1706   // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled
1707   // in with
1708   // any executable directories that should be searched.
1709   static std::vector<FileSpec> g_executable_dirs;
1710 
1711   // Find the global list of directories that we will search for
1712   // executables once so we don't keep doing the work over and over.
1713   static llvm::once_flag g_once_flag;
1714   llvm::call_once(g_once_flag, []() {
1715 
1716     // When locating executables, trust the DEVELOPER_DIR first if it is set
1717     FileSpec xcode_contents_dir = GetXcodeContentsPath();
1718     if (xcode_contents_dir) {
1719       FileSpec xcode_lldb_resources = xcode_contents_dir;
1720       xcode_lldb_resources.AppendPathComponent("SharedFrameworks");
1721       xcode_lldb_resources.AppendPathComponent("LLDB.framework");
1722       xcode_lldb_resources.AppendPathComponent("Resources");
1723       if (xcode_lldb_resources.Exists()) {
1724         FileSpec dir;
1725         dir.GetDirectory().SetCString(xcode_lldb_resources.GetPath().c_str());
1726         g_executable_dirs.push_back(dir);
1727       }
1728     }
1729   });
1730 
1731   // Now search the global list of executable directories for the executable we
1732   // are looking for
1733   for (const auto &executable_dir : g_executable_dirs) {
1734     FileSpec executable_file;
1735     executable_file.GetDirectory() = executable_dir.GetDirectory();
1736     executable_file.GetFilename().SetCString(basename);
1737     if (executable_file.Exists())
1738       return executable_file;
1739   }
1740 
1741   return FileSpec();
1742 }
1743 
1744 lldb_private::Status
1745 PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) {
1746   // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr
1747   // if the OS_ACTIVITY_DT_MODE environment variable is set.  (It doesn't
1748   // require any specific value; rather, it just needs to exist).
1749   // We will set it here as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag
1750   // is not set.  Xcode makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell
1751   // LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they
1752   // specifically want it unset.
1753   const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE";
1754   auto &env_vars = launch_info.GetEnvironmentEntries();
1755   if (!env_vars.ContainsEnvironmentVariable(llvm::StringRef(disable_env_var))) {
1756     // We want to make sure that OS_ACTIVITY_DT_MODE is set so that
1757     // we get os_log and NSLog messages mirrored to the target process
1758     // stderr.
1759     if (!env_vars.ContainsEnvironmentVariable(
1760             llvm::StringRef("OS_ACTIVITY_DT_MODE")))
1761       env_vars.AppendArgument(llvm::StringRef("OS_ACTIVITY_DT_MODE=enable"));
1762   }
1763 
1764   // Let our parent class do the real launching.
1765   return PlatformPOSIX::LaunchProcess(launch_info);
1766 }
1767 
1768 lldb_private::Status
1769 PlatformDarwin::FindBundleBinaryInExecSearchPaths (const ModuleSpec &module_spec, Process *process,
1770                                                    ModuleSP &module_sp,
1771                                                    const FileSpecList *module_search_paths_ptr,
1772                                                    ModuleSP *old_module_sp_ptr, bool *did_create_ptr)
1773 {
1774   const FileSpec &platform_file = module_spec.GetFileSpec();
1775   // See if the file is present in any of the module_search_paths_ptr directories.
1776   if (!module_sp && module_search_paths_ptr && platform_file) {
1777     // create a vector of all the file / directory names in platform_file
1778     // e.g. this might be
1779     // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
1780     //
1781     // We'll need to look in the module_search_paths_ptr directories for
1782     // both "UIFoundation" and "UIFoundation.framework" -- most likely the
1783     // latter will be the one we find there.
1784 
1785     FileSpec platform_pull_apart(platform_file);
1786     std::vector<std::string> path_parts;
1787     ConstString unix_root_dir("/");
1788     while (true) {
1789       ConstString part = platform_pull_apart.GetLastPathComponent();
1790       platform_pull_apart.RemoveLastPathComponent();
1791       if (part.IsEmpty() || part == unix_root_dir)
1792         break;
1793       path_parts.push_back(part.AsCString());
1794     }
1795     const size_t path_parts_size = path_parts.size();
1796 
1797     size_t num_module_search_paths = module_search_paths_ptr->GetSize();
1798     for (size_t i = 0; i < num_module_search_paths; ++i) {
1799       Log *log_verbose = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
1800       if (log_verbose)
1801           log_verbose->Printf ("PlatformRemoteDarwinDevice::GetSharedModule searching for binary in search-path %s", module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str());
1802       // Create a new FileSpec with this module_search_paths_ptr
1803       // plus just the filename ("UIFoundation"), then the parent
1804       // dir plus filename ("UIFoundation.framework/UIFoundation")
1805       // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo")
1806 
1807       for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) {
1808         FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));
1809 
1810         // Add the components backwards.  For
1811         // .../PrivateFrameworks/UIFoundation.framework/UIFoundation
1812         // path_parts is
1813         //   [0] UIFoundation
1814         //   [1] UIFoundation.framework
1815         //   [2] PrivateFrameworks
1816         //
1817         // and if 'j' is 2, we want to append path_parts[1] and then
1818         // path_parts[0], aka
1819         // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr
1820         // path.
1821 
1822         for (int k = j; k >= 0; --k) {
1823           path_to_try.AppendPathComponent(path_parts[k]);
1824         }
1825 
1826         if (path_to_try.Exists()) {
1827           ModuleSpec new_module_spec(module_spec);
1828           new_module_spec.GetFileSpec() = path_to_try;
1829           Status new_error(Platform::GetSharedModule(
1830               new_module_spec, process, module_sp, NULL, old_module_sp_ptr,
1831               did_create_ptr));
1832 
1833           if (module_sp) {
1834             module_sp->SetPlatformFileSpec(path_to_try);
1835             return new_error;
1836           }
1837         }
1838       }
1839     }
1840   }
1841   return Status();
1842 }
1843