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