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   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 = std::make_shared<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 = std::make_shared<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 = std::make_shared<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   return obj_type == ObjectFile::eTypeDynamicLinker;
493 }
494 
495 bool PlatformDarwin::x86GetSupportedArchitectureAtIndex(uint32_t idx,
496                                                         ArchSpec &arch) {
497   ArchSpec host_arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
498   if (host_arch.GetCore() == ArchSpec::eCore_x86_64_x86_64h) {
499     switch (idx) {
500     case 0:
501       arch = host_arch;
502       return true;
503 
504     case 1:
505       arch.SetTriple("x86_64-apple-macosx");
506       return true;
507 
508     case 2:
509       arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
510       return true;
511 
512     default:
513       return false;
514     }
515   } else {
516     if (idx == 0) {
517       arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
518       return arch.IsValid();
519     } else if (idx == 1) {
520       ArchSpec platform_arch(
521           HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
522       ArchSpec platform_arch64(
523           HostInfo::GetArchitecture(HostInfo::eArchKind64));
524       if (platform_arch.IsExactMatch(platform_arch64)) {
525         // This macosx platform supports both 32 and 64 bit. Since we already
526         // returned the 64 bit arch for idx == 0, return the 32 bit arch for
527         // idx == 1
528         arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
529         return arch.IsValid();
530       }
531     }
532   }
533   return false;
534 }
535 
536 // The architecture selection rules for arm processors These cpu subtypes have
537 // distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f
538 // processor.
539 
540 bool PlatformDarwin::ARMGetSupportedArchitectureAtIndex(uint32_t idx,
541                                                         ArchSpec &arch) {
542   ArchSpec system_arch(GetSystemArchitecture());
543 
544 // When lldb is running on a watch or tv, set the arch OS name appropriately.
545 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
546 #define OSNAME "tvos"
547 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
548 #define OSNAME "watchos"
549 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
550 #define OSNAME "bridgeos"
551 #else
552 #define OSNAME "ios"
553 #endif
554 
555   const ArchSpec::Core system_core = system_arch.GetCore();
556   switch (system_core) {
557   default:
558     switch (idx) {
559     case 0:
560       arch.SetTriple("arm64-apple-" OSNAME);
561       return true;
562     case 1:
563       arch.SetTriple("armv7-apple-" OSNAME);
564       return true;
565     case 2:
566       arch.SetTriple("armv7f-apple-" OSNAME);
567       return true;
568     case 3:
569       arch.SetTriple("armv7k-apple-" OSNAME);
570       return true;
571     case 4:
572       arch.SetTriple("armv7s-apple-" OSNAME);
573       return true;
574     case 5:
575       arch.SetTriple("armv7m-apple-" OSNAME);
576       return true;
577     case 6:
578       arch.SetTriple("armv7em-apple-" OSNAME);
579       return true;
580     case 7:
581       arch.SetTriple("armv6m-apple-" OSNAME);
582       return true;
583     case 8:
584       arch.SetTriple("armv6-apple-" OSNAME);
585       return true;
586     case 9:
587       arch.SetTriple("armv5-apple-" OSNAME);
588       return true;
589     case 10:
590       arch.SetTriple("armv4-apple-" OSNAME);
591       return true;
592     case 11:
593       arch.SetTriple("arm-apple-" OSNAME);
594       return true;
595     case 12:
596       arch.SetTriple("thumbv7-apple-" OSNAME);
597       return true;
598     case 13:
599       arch.SetTriple("thumbv7f-apple-" OSNAME);
600       return true;
601     case 14:
602       arch.SetTriple("thumbv7k-apple-" OSNAME);
603       return true;
604     case 15:
605       arch.SetTriple("thumbv7s-apple-" OSNAME);
606       return true;
607     case 16:
608       arch.SetTriple("thumbv7m-apple-" OSNAME);
609       return true;
610     case 17:
611       arch.SetTriple("thumbv7em-apple-" OSNAME);
612       return true;
613     case 18:
614       arch.SetTriple("thumbv6m-apple-" OSNAME);
615       return true;
616     case 19:
617       arch.SetTriple("thumbv6-apple-" OSNAME);
618       return true;
619     case 20:
620       arch.SetTriple("thumbv5-apple-" OSNAME);
621       return true;
622     case 21:
623       arch.SetTriple("thumbv4t-apple-" OSNAME);
624       return true;
625     case 22:
626       arch.SetTriple("thumb-apple-" OSNAME);
627       return true;
628     default:
629       break;
630     }
631     break;
632 
633   case ArchSpec::eCore_arm_arm64:
634     switch (idx) {
635     case 0:
636       arch.SetTriple("arm64-apple-" OSNAME);
637       return true;
638     case 1:
639       arch.SetTriple("armv7s-apple-" OSNAME);
640       return true;
641     case 2:
642       arch.SetTriple("armv7f-apple-" OSNAME);
643       return true;
644     case 3:
645       arch.SetTriple("armv7m-apple-" OSNAME);
646       return true;
647     case 4:
648       arch.SetTriple("armv7em-apple-" OSNAME);
649       return true;
650     case 5:
651       arch.SetTriple("armv7-apple-" OSNAME);
652       return true;
653     case 6:
654       arch.SetTriple("armv6m-apple-" OSNAME);
655       return true;
656     case 7:
657       arch.SetTriple("armv6-apple-" OSNAME);
658       return true;
659     case 8:
660       arch.SetTriple("armv5-apple-" OSNAME);
661       return true;
662     case 9:
663       arch.SetTriple("armv4-apple-" OSNAME);
664       return true;
665     case 10:
666       arch.SetTriple("arm-apple-" OSNAME);
667       return true;
668     case 11:
669       arch.SetTriple("thumbv7-apple-" OSNAME);
670       return true;
671     case 12:
672       arch.SetTriple("thumbv7f-apple-" OSNAME);
673       return true;
674     case 13:
675       arch.SetTriple("thumbv7k-apple-" OSNAME);
676       return true;
677     case 14:
678       arch.SetTriple("thumbv7s-apple-" OSNAME);
679       return true;
680     case 15:
681       arch.SetTriple("thumbv7m-apple-" OSNAME);
682       return true;
683     case 16:
684       arch.SetTriple("thumbv7em-apple-" OSNAME);
685       return true;
686     case 17:
687       arch.SetTriple("thumbv6m-apple-" OSNAME);
688       return true;
689     case 18:
690       arch.SetTriple("thumbv6-apple-" OSNAME);
691       return true;
692     case 19:
693       arch.SetTriple("thumbv5-apple-" OSNAME);
694       return true;
695     case 20:
696       arch.SetTriple("thumbv4t-apple-" OSNAME);
697       return true;
698     case 21:
699       arch.SetTriple("thumb-apple-" OSNAME);
700       return true;
701     default:
702       break;
703     }
704     break;
705 
706   case ArchSpec::eCore_arm_armv7f:
707     switch (idx) {
708     case 0:
709       arch.SetTriple("armv7f-apple-" OSNAME);
710       return true;
711     case 1:
712       arch.SetTriple("armv7-apple-" OSNAME);
713       return true;
714     case 2:
715       arch.SetTriple("armv6m-apple-" OSNAME);
716       return true;
717     case 3:
718       arch.SetTriple("armv6-apple-" OSNAME);
719       return true;
720     case 4:
721       arch.SetTriple("armv5-apple-" OSNAME);
722       return true;
723     case 5:
724       arch.SetTriple("armv4-apple-" OSNAME);
725       return true;
726     case 6:
727       arch.SetTriple("arm-apple-" OSNAME);
728       return true;
729     case 7:
730       arch.SetTriple("thumbv7f-apple-" OSNAME);
731       return true;
732     case 8:
733       arch.SetTriple("thumbv7-apple-" OSNAME);
734       return true;
735     case 9:
736       arch.SetTriple("thumbv6m-apple-" OSNAME);
737       return true;
738     case 10:
739       arch.SetTriple("thumbv6-apple-" OSNAME);
740       return true;
741     case 11:
742       arch.SetTriple("thumbv5-apple-" OSNAME);
743       return true;
744     case 12:
745       arch.SetTriple("thumbv4t-apple-" OSNAME);
746       return true;
747     case 13:
748       arch.SetTriple("thumb-apple-" OSNAME);
749       return true;
750     default:
751       break;
752     }
753     break;
754 
755   case ArchSpec::eCore_arm_armv7k:
756     switch (idx) {
757     case 0:
758       arch.SetTriple("armv7k-apple-" OSNAME);
759       return true;
760     case 1:
761       arch.SetTriple("armv7-apple-" OSNAME);
762       return true;
763     case 2:
764       arch.SetTriple("armv6m-apple-" OSNAME);
765       return true;
766     case 3:
767       arch.SetTriple("armv6-apple-" OSNAME);
768       return true;
769     case 4:
770       arch.SetTriple("armv5-apple-" OSNAME);
771       return true;
772     case 5:
773       arch.SetTriple("armv4-apple-" OSNAME);
774       return true;
775     case 6:
776       arch.SetTriple("arm-apple-" OSNAME);
777       return true;
778     case 7:
779       arch.SetTriple("thumbv7k-apple-" OSNAME);
780       return true;
781     case 8:
782       arch.SetTriple("thumbv7-apple-" OSNAME);
783       return true;
784     case 9:
785       arch.SetTriple("thumbv6m-apple-" OSNAME);
786       return true;
787     case 10:
788       arch.SetTriple("thumbv6-apple-" OSNAME);
789       return true;
790     case 11:
791       arch.SetTriple("thumbv5-apple-" OSNAME);
792       return true;
793     case 12:
794       arch.SetTriple("thumbv4t-apple-" OSNAME);
795       return true;
796     case 13:
797       arch.SetTriple("thumb-apple-" OSNAME);
798       return true;
799     default:
800       break;
801     }
802     break;
803 
804   case ArchSpec::eCore_arm_armv7s:
805     switch (idx) {
806     case 0:
807       arch.SetTriple("armv7s-apple-" OSNAME);
808       return true;
809     case 1:
810       arch.SetTriple("armv7-apple-" OSNAME);
811       return true;
812     case 2:
813       arch.SetTriple("armv6m-apple-" OSNAME);
814       return true;
815     case 3:
816       arch.SetTriple("armv6-apple-" OSNAME);
817       return true;
818     case 4:
819       arch.SetTriple("armv5-apple-" OSNAME);
820       return true;
821     case 5:
822       arch.SetTriple("armv4-apple-" OSNAME);
823       return true;
824     case 6:
825       arch.SetTriple("arm-apple-" OSNAME);
826       return true;
827     case 7:
828       arch.SetTriple("thumbv7s-apple-" OSNAME);
829       return true;
830     case 8:
831       arch.SetTriple("thumbv7-apple-" OSNAME);
832       return true;
833     case 9:
834       arch.SetTriple("thumbv6m-apple-" OSNAME);
835       return true;
836     case 10:
837       arch.SetTriple("thumbv6-apple-" OSNAME);
838       return true;
839     case 11:
840       arch.SetTriple("thumbv5-apple-" OSNAME);
841       return true;
842     case 12:
843       arch.SetTriple("thumbv4t-apple-" OSNAME);
844       return true;
845     case 13:
846       arch.SetTriple("thumb-apple-" OSNAME);
847       return true;
848     default:
849       break;
850     }
851     break;
852 
853   case ArchSpec::eCore_arm_armv7m:
854     switch (idx) {
855     case 0:
856       arch.SetTriple("armv7m-apple-" OSNAME);
857       return true;
858     case 1:
859       arch.SetTriple("armv7-apple-" OSNAME);
860       return true;
861     case 2:
862       arch.SetTriple("armv6m-apple-" OSNAME);
863       return true;
864     case 3:
865       arch.SetTriple("armv6-apple-" OSNAME);
866       return true;
867     case 4:
868       arch.SetTriple("armv5-apple-" OSNAME);
869       return true;
870     case 5:
871       arch.SetTriple("armv4-apple-" OSNAME);
872       return true;
873     case 6:
874       arch.SetTriple("arm-apple-" OSNAME);
875       return true;
876     case 7:
877       arch.SetTriple("thumbv7m-apple-" OSNAME);
878       return true;
879     case 8:
880       arch.SetTriple("thumbv7-apple-" OSNAME);
881       return true;
882     case 9:
883       arch.SetTriple("thumbv6m-apple-" OSNAME);
884       return true;
885     case 10:
886       arch.SetTriple("thumbv6-apple-" OSNAME);
887       return true;
888     case 11:
889       arch.SetTriple("thumbv5-apple-" OSNAME);
890       return true;
891     case 12:
892       arch.SetTriple("thumbv4t-apple-" OSNAME);
893       return true;
894     case 13:
895       arch.SetTriple("thumb-apple-" OSNAME);
896       return true;
897     default:
898       break;
899     }
900     break;
901 
902   case ArchSpec::eCore_arm_armv7em:
903     switch (idx) {
904     case 0:
905       arch.SetTriple("armv7em-apple-" OSNAME);
906       return true;
907     case 1:
908       arch.SetTriple("armv7-apple-" OSNAME);
909       return true;
910     case 2:
911       arch.SetTriple("armv6m-apple-" OSNAME);
912       return true;
913     case 3:
914       arch.SetTriple("armv6-apple-" OSNAME);
915       return true;
916     case 4:
917       arch.SetTriple("armv5-apple-" OSNAME);
918       return true;
919     case 5:
920       arch.SetTriple("armv4-apple-" OSNAME);
921       return true;
922     case 6:
923       arch.SetTriple("arm-apple-" OSNAME);
924       return true;
925     case 7:
926       arch.SetTriple("thumbv7em-apple-" OSNAME);
927       return true;
928     case 8:
929       arch.SetTriple("thumbv7-apple-" OSNAME);
930       return true;
931     case 9:
932       arch.SetTriple("thumbv6m-apple-" OSNAME);
933       return true;
934     case 10:
935       arch.SetTriple("thumbv6-apple-" OSNAME);
936       return true;
937     case 11:
938       arch.SetTriple("thumbv5-apple-" OSNAME);
939       return true;
940     case 12:
941       arch.SetTriple("thumbv4t-apple-" OSNAME);
942       return true;
943     case 13:
944       arch.SetTriple("thumb-apple-" OSNAME);
945       return true;
946     default:
947       break;
948     }
949     break;
950 
951   case ArchSpec::eCore_arm_armv7:
952     switch (idx) {
953     case 0:
954       arch.SetTriple("armv7-apple-" OSNAME);
955       return true;
956     case 1:
957       arch.SetTriple("armv6m-apple-" OSNAME);
958       return true;
959     case 2:
960       arch.SetTriple("armv6-apple-" OSNAME);
961       return true;
962     case 3:
963       arch.SetTriple("armv5-apple-" OSNAME);
964       return true;
965     case 4:
966       arch.SetTriple("armv4-apple-" OSNAME);
967       return true;
968     case 5:
969       arch.SetTriple("arm-apple-" OSNAME);
970       return true;
971     case 6:
972       arch.SetTriple("thumbv7-apple-" OSNAME);
973       return true;
974     case 7:
975       arch.SetTriple("thumbv6m-apple-" OSNAME);
976       return true;
977     case 8:
978       arch.SetTriple("thumbv6-apple-" OSNAME);
979       return true;
980     case 9:
981       arch.SetTriple("thumbv5-apple-" OSNAME);
982       return true;
983     case 10:
984       arch.SetTriple("thumbv4t-apple-" OSNAME);
985       return true;
986     case 11:
987       arch.SetTriple("thumb-apple-" OSNAME);
988       return true;
989     default:
990       break;
991     }
992     break;
993 
994   case ArchSpec::eCore_arm_armv6m:
995     switch (idx) {
996     case 0:
997       arch.SetTriple("armv6m-apple-" OSNAME);
998       return true;
999     case 1:
1000       arch.SetTriple("armv6-apple-" OSNAME);
1001       return true;
1002     case 2:
1003       arch.SetTriple("armv5-apple-" OSNAME);
1004       return true;
1005     case 3:
1006       arch.SetTriple("armv4-apple-" OSNAME);
1007       return true;
1008     case 4:
1009       arch.SetTriple("arm-apple-" OSNAME);
1010       return true;
1011     case 5:
1012       arch.SetTriple("thumbv6m-apple-" OSNAME);
1013       return true;
1014     case 6:
1015       arch.SetTriple("thumbv6-apple-" OSNAME);
1016       return true;
1017     case 7:
1018       arch.SetTriple("thumbv5-apple-" OSNAME);
1019       return true;
1020     case 8:
1021       arch.SetTriple("thumbv4t-apple-" OSNAME);
1022       return true;
1023     case 9:
1024       arch.SetTriple("thumb-apple-" OSNAME);
1025       return true;
1026     default:
1027       break;
1028     }
1029     break;
1030 
1031   case ArchSpec::eCore_arm_armv6:
1032     switch (idx) {
1033     case 0:
1034       arch.SetTriple("armv6-apple-" OSNAME);
1035       return true;
1036     case 1:
1037       arch.SetTriple("armv5-apple-" OSNAME);
1038       return true;
1039     case 2:
1040       arch.SetTriple("armv4-apple-" OSNAME);
1041       return true;
1042     case 3:
1043       arch.SetTriple("arm-apple-" OSNAME);
1044       return true;
1045     case 4:
1046       arch.SetTriple("thumbv6-apple-" OSNAME);
1047       return true;
1048     case 5:
1049       arch.SetTriple("thumbv5-apple-" OSNAME);
1050       return true;
1051     case 6:
1052       arch.SetTriple("thumbv4t-apple-" OSNAME);
1053       return true;
1054     case 7:
1055       arch.SetTriple("thumb-apple-" OSNAME);
1056       return true;
1057     default:
1058       break;
1059     }
1060     break;
1061 
1062   case ArchSpec::eCore_arm_armv5:
1063     switch (idx) {
1064     case 0:
1065       arch.SetTriple("armv5-apple-" OSNAME);
1066       return true;
1067     case 1:
1068       arch.SetTriple("armv4-apple-" OSNAME);
1069       return true;
1070     case 2:
1071       arch.SetTriple("arm-apple-" OSNAME);
1072       return true;
1073     case 3:
1074       arch.SetTriple("thumbv5-apple-" OSNAME);
1075       return true;
1076     case 4:
1077       arch.SetTriple("thumbv4t-apple-" OSNAME);
1078       return true;
1079     case 5:
1080       arch.SetTriple("thumb-apple-" OSNAME);
1081       return true;
1082     default:
1083       break;
1084     }
1085     break;
1086 
1087   case ArchSpec::eCore_arm_armv4:
1088     switch (idx) {
1089     case 0:
1090       arch.SetTriple("armv4-apple-" OSNAME);
1091       return true;
1092     case 1:
1093       arch.SetTriple("arm-apple-" OSNAME);
1094       return true;
1095     case 2:
1096       arch.SetTriple("thumbv4t-apple-" OSNAME);
1097       return true;
1098     case 3:
1099       arch.SetTriple("thumb-apple-" OSNAME);
1100       return true;
1101     default:
1102       break;
1103     }
1104     break;
1105   }
1106   arch.Clear();
1107   return false;
1108 }
1109 
1110 // Return a directory path like /Applications/Xcode.app/Contents/Developer
1111 const char *PlatformDarwin::GetDeveloperDirectory() {
1112   std::lock_guard<std::mutex> guard(m_mutex);
1113   if (m_developer_directory.empty()) {
1114     bool developer_dir_path_valid = false;
1115     char developer_dir_path[PATH_MAX];
1116 
1117     // Get the lldb framework's file path, and if it exists, truncate some
1118     // components to only the developer directory path.
1119     FileSpec temp_file_spec = HostInfo::GetShlibDir();
1120     if (temp_file_spec) {
1121       if (temp_file_spec.GetPath(developer_dir_path,
1122                                  sizeof(developer_dir_path))) {
1123         // e.g.
1124         // /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework
1125         char *shared_frameworks =
1126             strstr(developer_dir_path, "/SharedFrameworks/LLDB.framework");
1127         if (shared_frameworks) {
1128           shared_frameworks[0] = '\0';  // truncate developer_dir_path at this point
1129           strncat (developer_dir_path, "/Developer", sizeof (developer_dir_path) - 1); // add /Developer on
1130           developer_dir_path_valid = true;
1131         } else {
1132           // e.g.
1133           // /Applications/Xcode.app/Contents/Developer/Toolchains/iOS11.2.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework
1134           char *developer_toolchains =
1135             strstr(developer_dir_path, "/Contents/Developer/Toolchains/");
1136           if (developer_toolchains) {
1137             developer_toolchains += sizeof ("/Contents/Developer") - 1;
1138             developer_toolchains[0] = '\0'; // truncate developer_dir_path at this point
1139             developer_dir_path_valid = true;
1140           }
1141         }
1142       }
1143     }
1144 
1145     if (!developer_dir_path_valid) {
1146       std::string xcode_dir_path;
1147       const char *xcode_select_prefix_dir = getenv("XCODE_SELECT_PREFIX_DIR");
1148       if (xcode_select_prefix_dir)
1149         xcode_dir_path.append(xcode_select_prefix_dir);
1150       xcode_dir_path.append("/usr/share/xcode-select/xcode_dir_path");
1151       temp_file_spec.SetFile(xcode_dir_path, FileSpec::Style::native);
1152       auto dir_buffer =
1153           FileSystem::Instance().CreateDataBuffer(temp_file_spec.GetPath());
1154       if (dir_buffer && dir_buffer->GetByteSize() > 0) {
1155         llvm::StringRef path_ref(dir_buffer->GetChars());
1156         // Trim tailing newlines and make sure there is enough room for a null
1157         // terminator.
1158         path_ref =
1159             path_ref.rtrim("\r\n").take_front(sizeof(developer_dir_path) - 1);
1160         ::memcpy(developer_dir_path, path_ref.data(), path_ref.size());
1161         developer_dir_path[path_ref.size()] = '\0';
1162         developer_dir_path_valid = true;
1163       }
1164     }
1165 
1166     if (!developer_dir_path_valid) {
1167       FileSpec xcode_select_cmd("/usr/bin/xcode-select");
1168       if (FileSystem::Instance().Exists(xcode_select_cmd)) {
1169         int exit_status = -1;
1170         int signo = -1;
1171         std::string command_output;
1172         Status error =
1173             Host::RunShellCommand("/usr/bin/xcode-select --print-path",
1174                                   NULL, // current working directory
1175                                   &exit_status, &signo, &command_output,
1176                                   std::chrono::seconds(2), // short timeout
1177                                   false); // don't run in a shell
1178         if (error.Success() && exit_status == 0 && !command_output.empty()) {
1179           const char *cmd_output_ptr = command_output.c_str();
1180           developer_dir_path[sizeof(developer_dir_path) - 1] = '\0';
1181           size_t i;
1182           for (i = 0; i < sizeof(developer_dir_path) - 1; i++) {
1183             if (cmd_output_ptr[i] == '\r' || cmd_output_ptr[i] == '\n' ||
1184                 cmd_output_ptr[i] == '\0')
1185               break;
1186             developer_dir_path[i] = cmd_output_ptr[i];
1187           }
1188           developer_dir_path[i] = '\0';
1189 
1190           FileSpec devel_dir(developer_dir_path);
1191           if (FileSystem::Instance().IsDirectory(devel_dir)) {
1192             developer_dir_path_valid = true;
1193           }
1194         }
1195       }
1196     }
1197 
1198     if (developer_dir_path_valid) {
1199       temp_file_spec.SetFile(developer_dir_path, FileSpec::Style::native);
1200       if (FileSystem::Instance().Exists(temp_file_spec)) {
1201         m_developer_directory.assign(developer_dir_path);
1202         return m_developer_directory.c_str();
1203       }
1204     }
1205     // Assign a single NULL character so we know we tried to find the device
1206     // support directory and we don't keep trying to find it over and over.
1207     m_developer_directory.assign(1, '\0');
1208   }
1209 
1210   // We should have put a single NULL character into m_developer_directory or
1211   // it should have a valid path if the code gets here
1212   assert(m_developer_directory.empty() == false);
1213   if (m_developer_directory[0])
1214     return m_developer_directory.c_str();
1215   return NULL;
1216 }
1217 
1218 BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) {
1219   BreakpointSP bp_sp;
1220   static const char *g_bp_names[] = {
1221       "start_wqthread", "_pthread_wqthread", "_pthread_start",
1222   };
1223 
1224   static const char *g_bp_modules[] = {"libsystem_c.dylib",
1225                                        "libSystem.B.dylib"};
1226 
1227   FileSpecList bp_modules;
1228   for (size_t i = 0; i < llvm::array_lengthof(g_bp_modules); i++) {
1229     const char *bp_module = g_bp_modules[i];
1230     bp_modules.Append(FileSpec(bp_module));
1231   }
1232 
1233   bool internal = true;
1234   bool hardware = false;
1235   LazyBool skip_prologue = eLazyBoolNo;
1236   bp_sp = target.CreateBreakpoint(&bp_modules, NULL, g_bp_names,
1237                                   llvm::array_lengthof(g_bp_names),
1238                                   eFunctionNameTypeFull, eLanguageTypeUnknown,
1239                                   0, skip_prologue, internal, hardware);
1240   bp_sp->SetBreakpointKind("thread-creation");
1241 
1242   return bp_sp;
1243 }
1244 
1245 int32_t
1246 PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) {
1247   const FileSpec &shell = launch_info.GetShell();
1248   if (!shell)
1249     return 1;
1250 
1251   std::string shell_string = shell.GetPath();
1252   const char *shell_name = strrchr(shell_string.c_str(), '/');
1253   if (shell_name == NULL)
1254     shell_name = shell_string.c_str();
1255   else
1256     shell_name++;
1257 
1258   if (strcmp(shell_name, "sh") == 0) {
1259     // /bin/sh re-exec's itself as /bin/bash requiring another resume. But it
1260     // only does this if the COMMAND_MODE environment variable is set to
1261     // "legacy".
1262     if (launch_info.GetEnvironment().lookup("COMMAND_MODE") == "legacy")
1263       return 2;
1264     return 1;
1265   } else if (strcmp(shell_name, "csh") == 0 ||
1266              strcmp(shell_name, "tcsh") == 0 ||
1267              strcmp(shell_name, "zsh") == 0) {
1268     // csh and tcsh always seem to re-exec themselves.
1269     return 2;
1270   } else
1271     return 1;
1272 }
1273 
1274 void PlatformDarwin::CalculateTrapHandlerSymbolNames() {
1275   m_trap_handlers.push_back(ConstString("_sigtramp"));
1276 }
1277 
1278 static const char *const sdk_strings[] = {
1279     "MacOSX", "iPhoneSimulator", "iPhoneOS",
1280 };
1281 
1282 static FileSpec CheckPathForXcode(const FileSpec &fspec) {
1283   if (FileSystem::Instance().Exists(fspec)) {
1284     const char substr[] = ".app/Contents";
1285 
1286     std::string path_to_shlib = fspec.GetPath();
1287     size_t pos = path_to_shlib.rfind(substr);
1288     if (pos != std::string::npos) {
1289       path_to_shlib.erase(pos + strlen(substr));
1290       FileSpec ret(path_to_shlib);
1291 
1292       FileSpec xcode_binary_path = ret;
1293       xcode_binary_path.AppendPathComponent("MacOS");
1294       xcode_binary_path.AppendPathComponent("Xcode");
1295 
1296       if (FileSystem::Instance().Exists(xcode_binary_path)) {
1297         return ret;
1298       }
1299     }
1300   }
1301   return FileSpec();
1302 }
1303 
1304 static FileSpec GetXcodeContentsPath() {
1305   static FileSpec g_xcode_filespec;
1306   static llvm::once_flag g_once_flag;
1307   llvm::call_once(g_once_flag, []() {
1308 
1309     FileSpec fspec;
1310 
1311     // First get the program file spec. If lldb.so or LLDB.framework is running
1312     // in a program and that program is Xcode, the path returned with be the
1313     // path to Xcode.app/Contents/MacOS/Xcode, so this will be the correct
1314     // Xcode to use.
1315     fspec = HostInfo::GetProgramFileSpec();
1316 
1317     if (fspec) {
1318       // Ignore the current binary if it is python.
1319       std::string basename_lower = fspec.GetFilename().GetCString();
1320       std::transform(basename_lower.begin(), basename_lower.end(),
1321                      basename_lower.begin(), tolower);
1322       if (basename_lower != "python") {
1323         g_xcode_filespec = CheckPathForXcode(fspec);
1324       }
1325     }
1326 
1327     // Next check DEVELOPER_DIR environment variable
1328     if (!g_xcode_filespec) {
1329       const char *developer_dir_env_var = getenv("DEVELOPER_DIR");
1330       if (developer_dir_env_var && developer_dir_env_var[0]) {
1331         FileSpec developer_dir_spec = FileSpec(developer_dir_env_var);
1332         FileSystem::Instance().Resolve(developer_dir_spec);
1333         g_xcode_filespec = CheckPathForXcode(developer_dir_spec);
1334       }
1335 
1336       // Fall back to using "xcrun" to find the selected Xcode
1337       if (!g_xcode_filespec) {
1338         int status = 0;
1339         int signo = 0;
1340         std::string output;
1341         const char *command = "/usr/bin/xcode-select -p";
1342         lldb_private::Status error = Host::RunShellCommand(
1343             command, // shell command to run
1344             NULL,    // current working directory
1345             &status, // Put the exit status of the process in here
1346             &signo,  // Put the signal that caused the process to exit in here
1347             &output, // Get the output from the command and place it in this
1348                      // string
1349             std::chrono::seconds(3));
1350         if (status == 0 && !output.empty()) {
1351           size_t first_non_newline = output.find_last_not_of("\r\n");
1352           if (first_non_newline != std::string::npos) {
1353             output.erase(first_non_newline + 1);
1354           }
1355           output.append("/..");
1356 
1357           g_xcode_filespec = CheckPathForXcode(FileSpec(output));
1358         }
1359       }
1360     }
1361   });
1362 
1363   return g_xcode_filespec;
1364 }
1365 
1366 bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type,
1367                                         llvm::VersionTuple version) {
1368   switch (sdk_type) {
1369   case SDKType::MacOSX:
1370     return version >= llvm::VersionTuple(10, 10);
1371   case SDKType::iPhoneOS:
1372   case SDKType::iPhoneSimulator:
1373     return version >= llvm::VersionTuple(8);
1374   }
1375 
1376   return false;
1377 }
1378 
1379 bool PlatformDarwin::SDKSupportsModules(SDKType desired_type,
1380                                         const FileSpec &sdk_path) {
1381   ConstString last_path_component = sdk_path.GetLastPathComponent();
1382 
1383   if (last_path_component) {
1384     const llvm::StringRef sdk_name = last_path_component.GetStringRef();
1385 
1386     if (!sdk_name.startswith(sdk_strings[desired_type]))
1387       return false;
1388     auto version_part =
1389         sdk_name.drop_front(strlen(sdk_strings[desired_type]));
1390     version_part.consume_back(".sdk");
1391 
1392     llvm::VersionTuple version;
1393     if (version.tryParse(version_part))
1394       return false;
1395     return SDKSupportsModules(desired_type, version);
1396   }
1397 
1398   return false;
1399 }
1400 
1401 FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator(
1402     void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef path) {
1403   SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton);
1404 
1405   FileSpec spec(path);
1406   if (SDKSupportsModules(enumerator_info->sdk_type, spec)) {
1407     enumerator_info->found_path = spec;
1408     return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
1409   }
1410 
1411   return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
1412 }
1413 
1414 FileSpec PlatformDarwin::FindSDKInXcodeForModules(SDKType sdk_type,
1415                                                   const FileSpec &sdks_spec) {
1416   // Look inside Xcode for the required installed iOS SDK version
1417 
1418   if (!FileSystem::Instance().IsDirectory(sdks_spec)) {
1419     return FileSpec();
1420   }
1421 
1422   const bool find_directories = true;
1423   const bool find_files = false;
1424   const bool find_other = true; // include symlinks
1425 
1426   SDKEnumeratorInfo enumerator_info;
1427 
1428   enumerator_info.sdk_type = sdk_type;
1429 
1430   FileSystem::Instance().EnumerateDirectory(
1431       sdks_spec.GetPath(), find_directories, find_files, find_other,
1432       DirectoryEnumerator, &enumerator_info);
1433 
1434   if (FileSystem::Instance().IsDirectory(enumerator_info.found_path))
1435     return enumerator_info.found_path;
1436   else
1437     return FileSpec();
1438 }
1439 
1440 FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) {
1441   switch (sdk_type) {
1442   case SDKType::MacOSX:
1443   case SDKType::iPhoneSimulator:
1444   case SDKType::iPhoneOS:
1445     break;
1446   }
1447 
1448   FileSpec sdks_spec = GetXcodeContentsPath();
1449   sdks_spec.AppendPathComponent("Developer");
1450   sdks_spec.AppendPathComponent("Platforms");
1451 
1452   switch (sdk_type) {
1453   case SDKType::MacOSX:
1454     sdks_spec.AppendPathComponent("MacOSX.platform");
1455     break;
1456   case SDKType::iPhoneSimulator:
1457     sdks_spec.AppendPathComponent("iPhoneSimulator.platform");
1458     break;
1459   case SDKType::iPhoneOS:
1460     sdks_spec.AppendPathComponent("iPhoneOS.platform");
1461     break;
1462   }
1463 
1464   sdks_spec.AppendPathComponent("Developer");
1465   sdks_spec.AppendPathComponent("SDKs");
1466 
1467   if (sdk_type == SDKType::MacOSX) {
1468     llvm::VersionTuple version = HostInfo::GetOSVersion();
1469 
1470     if (!version.empty()) {
1471       if (SDKSupportsModules(SDKType::MacOSX, version)) {
1472         // We slightly prefer the exact SDK for this machine.  See if it is
1473         // there.
1474 
1475         FileSpec native_sdk_spec = sdks_spec;
1476         StreamString native_sdk_name;
1477         native_sdk_name.Printf("MacOSX%u.%u.sdk", version.getMajor(),
1478                                version.getMinor().getValueOr(0));
1479         native_sdk_spec.AppendPathComponent(native_sdk_name.GetString());
1480 
1481         if (FileSystem::Instance().Exists(native_sdk_spec)) {
1482           return native_sdk_spec;
1483         }
1484       }
1485     }
1486   }
1487 
1488   return FindSDKInXcodeForModules(sdk_type, sdks_spec);
1489 }
1490 
1491 std::tuple<llvm::VersionTuple, llvm::StringRef>
1492 PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) {
1493   llvm::StringRef build;
1494   llvm::StringRef version_str;
1495   llvm::StringRef build_str;
1496   std::tie(version_str, build_str) = dir.split(' ');
1497   llvm::VersionTuple version;
1498   if (!version.tryParse(version_str) ||
1499       build_str.empty()) {
1500     if (build_str.consume_front("(")) {
1501       size_t pos = build_str.find(')');
1502       build = build_str.slice(0, pos);
1503     }
1504   }
1505 
1506   return std::make_tuple(version, build);
1507 }
1508 
1509 void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
1510     Target *target, std::vector<std::string> &options, SDKType sdk_type) {
1511   const std::vector<std::string> apple_arguments = {
1512       "-x",       "objective-c++", "-fobjc-arc",
1513       "-fblocks", "-D_ISO646_H",   "-D__ISO646_H"};
1514 
1515   options.insert(options.end(), apple_arguments.begin(), apple_arguments.end());
1516 
1517   StreamString minimum_version_option;
1518   bool use_current_os_version = false;
1519   switch (sdk_type) {
1520   case SDKType::iPhoneOS:
1521 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
1522     use_current_os_version = true;
1523 #else
1524     use_current_os_version = false;
1525 #endif
1526     break;
1527 
1528   case SDKType::iPhoneSimulator:
1529     use_current_os_version = false;
1530     break;
1531 
1532   case SDKType::MacOSX:
1533 #if defined(__i386__) || defined(__x86_64__)
1534     use_current_os_version = true;
1535 #else
1536     use_current_os_version = false;
1537 #endif
1538     break;
1539   }
1540 
1541   llvm::VersionTuple version;
1542   if (use_current_os_version)
1543     version = GetOSVersion();
1544   else if (target) {
1545     // Our OS doesn't match our executable so we need to get the min OS version
1546     // from the object file
1547     ModuleSP exe_module_sp = target->GetExecutableModule();
1548     if (exe_module_sp) {
1549       ObjectFile *object_file = exe_module_sp->GetObjectFile();
1550       if (object_file)
1551         version = object_file->GetMinimumOSVersion();
1552     }
1553   }
1554   // Only add the version-min options if we got a version from somewhere
1555   if (!version.empty()) {
1556     switch (sdk_type) {
1557     case SDKType::iPhoneOS:
1558       minimum_version_option.PutCString("-mios-version-min=");
1559       minimum_version_option.PutCString(version.getAsString());
1560       break;
1561     case SDKType::iPhoneSimulator:
1562       minimum_version_option.PutCString("-mios-simulator-version-min=");
1563       minimum_version_option.PutCString(version.getAsString());
1564       break;
1565     case SDKType::MacOSX:
1566       minimum_version_option.PutCString("-mmacosx-version-min=");
1567       minimum_version_option.PutCString(version.getAsString());
1568     }
1569     options.push_back(minimum_version_option.GetString());
1570   }
1571 
1572   FileSpec sysroot_spec;
1573   // Scope for mutex locker below
1574   {
1575     std::lock_guard<std::mutex> guard(m_mutex);
1576     sysroot_spec = GetSDKDirectoryForModules(sdk_type);
1577   }
1578 
1579   if (FileSystem::Instance().IsDirectory(sysroot_spec.GetPath())) {
1580     options.push_back("-isysroot");
1581     options.push_back(sysroot_spec.GetPath());
1582   }
1583 }
1584 
1585 ConstString PlatformDarwin::GetFullNameForDylib(ConstString basename) {
1586   if (basename.IsEmpty())
1587     return basename;
1588 
1589   StreamString stream;
1590   stream.Printf("lib%s.dylib", basename.GetCString());
1591   return ConstString(stream.GetString());
1592 }
1593 
1594 llvm::VersionTuple PlatformDarwin::GetOSVersion(Process *process) {
1595   if (process && strstr(GetPluginName().GetCString(), "-simulator")) {
1596     lldb_private::ProcessInstanceInfo proc_info;
1597     if (Host::GetProcessInfo(process->GetID(), proc_info)) {
1598       const Environment &env = proc_info.GetEnvironment();
1599 
1600       llvm::VersionTuple result;
1601       if (!result.tryParse(env.lookup("SIMULATOR_RUNTIME_VERSION")))
1602         return result;
1603 
1604       std::string dyld_root_path = env.lookup("DYLD_ROOT_PATH");
1605       if (!dyld_root_path.empty()) {
1606         dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist";
1607         ApplePropertyList system_version_plist(dyld_root_path.c_str());
1608         std::string product_version;
1609         if (system_version_plist.GetValueAsString("ProductVersion",
1610                                                   product_version)) {
1611           if (!result.tryParse(product_version))
1612             return result;
1613         }
1614       }
1615     }
1616     // For simulator platforms, do NOT call back through
1617     // Platform::GetOSVersion() as it might call Process::GetHostOSVersion()
1618     // which we don't want as it will be incorrect
1619     return llvm::VersionTuple();
1620   }
1621 
1622   return Platform::GetOSVersion(process);
1623 }
1624 
1625 lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) {
1626   // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled
1627   // in with
1628   // any executable directories that should be searched.
1629   static std::vector<FileSpec> g_executable_dirs;
1630 
1631   // Find the global list of directories that we will search for executables
1632   // once so we don't keep doing the work over and over.
1633   static llvm::once_flag g_once_flag;
1634   llvm::call_once(g_once_flag, []() {
1635 
1636     // When locating executables, trust the DEVELOPER_DIR first if it is set
1637     FileSpec xcode_contents_dir = GetXcodeContentsPath();
1638     if (xcode_contents_dir) {
1639       FileSpec xcode_lldb_resources = xcode_contents_dir;
1640       xcode_lldb_resources.AppendPathComponent("SharedFrameworks");
1641       xcode_lldb_resources.AppendPathComponent("LLDB.framework");
1642       xcode_lldb_resources.AppendPathComponent("Resources");
1643       if (FileSystem::Instance().Exists(xcode_lldb_resources)) {
1644         FileSpec dir;
1645         dir.GetDirectory().SetCString(xcode_lldb_resources.GetPath().c_str());
1646         g_executable_dirs.push_back(dir);
1647       }
1648     }
1649   });
1650 
1651   // Now search the global list of executable directories for the executable we
1652   // are looking for
1653   for (const auto &executable_dir : g_executable_dirs) {
1654     FileSpec executable_file;
1655     executable_file.GetDirectory() = executable_dir.GetDirectory();
1656     executable_file.GetFilename().SetCString(basename);
1657     if (FileSystem::Instance().Exists(executable_file))
1658       return executable_file;
1659   }
1660 
1661   return FileSpec();
1662 }
1663 
1664 lldb_private::Status
1665 PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) {
1666   // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr if
1667   // the OS_ACTIVITY_DT_MODE environment variable is set.  (It doesn't require
1668   // any specific value; rather, it just needs to exist). We will set it here
1669   // as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag is not set.  Xcode
1670   // makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell
1671   // LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they
1672   // specifically want it unset.
1673   const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE";
1674   auto &env_vars = launch_info.GetEnvironment();
1675   if (!env_vars.count(disable_env_var)) {
1676     // We want to make sure that OS_ACTIVITY_DT_MODE is set so that we get
1677     // os_log and NSLog messages mirrored to the target process stderr.
1678     env_vars.try_emplace("OS_ACTIVITY_DT_MODE", "enable");
1679   }
1680 
1681   // Let our parent class do the real launching.
1682   return PlatformPOSIX::LaunchProcess(launch_info);
1683 }
1684 
1685 lldb_private::Status
1686 PlatformDarwin::FindBundleBinaryInExecSearchPaths (const ModuleSpec &module_spec, Process *process,
1687                                                    ModuleSP &module_sp,
1688                                                    const FileSpecList *module_search_paths_ptr,
1689                                                    ModuleSP *old_module_sp_ptr, bool *did_create_ptr)
1690 {
1691   const FileSpec &platform_file = module_spec.GetFileSpec();
1692   // See if the file is present in any of the module_search_paths_ptr
1693   // directories.
1694   if (!module_sp && module_search_paths_ptr && platform_file) {
1695     // create a vector of all the file / directory names in platform_file e.g.
1696     // this might be
1697     // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
1698     //
1699     // We'll need to look in the module_search_paths_ptr directories for both
1700     // "UIFoundation" and "UIFoundation.framework" -- most likely the latter
1701     // will be the one we find there.
1702 
1703     FileSpec platform_pull_upart(platform_file);
1704     std::vector<std::string> path_parts;
1705     path_parts.push_back(
1706         platform_pull_upart.GetLastPathComponent().AsCString());
1707     while (platform_pull_upart.RemoveLastPathComponent()) {
1708       ConstString part = platform_pull_upart.GetLastPathComponent();
1709       path_parts.push_back(part.AsCString());
1710     }
1711     const size_t path_parts_size = path_parts.size();
1712 
1713     size_t num_module_search_paths = module_search_paths_ptr->GetSize();
1714     for (size_t i = 0; i < num_module_search_paths; ++i) {
1715       Log *log_verbose = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
1716       if (log_verbose)
1717           log_verbose->Printf ("PlatformRemoteDarwinDevice::GetSharedModule searching for binary in search-path %s", module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str());
1718       // Create a new FileSpec with this module_search_paths_ptr plus just the
1719       // filename ("UIFoundation"), then the parent dir plus filename
1720       // ("UIFoundation.framework/UIFoundation") etc - up to four names (to
1721       // handle "Foo.framework/Contents/MacOS/Foo")
1722 
1723       for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) {
1724         FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));
1725 
1726         // Add the components backwards.  For
1727         // .../PrivateFrameworks/UIFoundation.framework/UIFoundation path_parts
1728         // is
1729         //   [0] UIFoundation
1730         //   [1] UIFoundation.framework
1731         //   [2] PrivateFrameworks
1732         //
1733         // and if 'j' is 2, we want to append path_parts[1] and then
1734         // path_parts[0], aka 'UIFoundation.framework/UIFoundation', to the
1735         // module_search_paths_ptr path.
1736 
1737         for (int k = j; k >= 0; --k) {
1738           path_to_try.AppendPathComponent(path_parts[k]);
1739         }
1740 
1741         if (FileSystem::Instance().Exists(path_to_try)) {
1742           ModuleSpec new_module_spec(module_spec);
1743           new_module_spec.GetFileSpec() = path_to_try;
1744           Status new_error(Platform::GetSharedModule(
1745               new_module_spec, process, module_sp, NULL, old_module_sp_ptr,
1746               did_create_ptr));
1747 
1748           if (module_sp) {
1749             module_sp->SetPlatformFileSpec(path_to_try);
1750             return new_error;
1751           }
1752         }
1753       }
1754     }
1755   }
1756   return Status();
1757 }
1758