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