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