brintos

brintos / llvm-project-archived public Read only

0
0
Text · 89.3 KiB · 28c817c Raw
2448 lines · cpp
1//===- Driver.cpp ---------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "Driver.h"10#include "Config.h"11#include "ICF.h"12#include "InputFiles.h"13#include "LTO.h"14#include "MarkLive.h"15#include "ObjC.h"16#include "OutputSection.h"17#include "OutputSegment.h"18#include "SectionPriorities.h"19#include "SymbolTable.h"20#include "Symbols.h"21#include "SyntheticSections.h"22#include "Target.h"23#include "UnwindInfoSection.h"24#include "Writer.h"25 26#include "lld/Common/Args.h"27#include "lld/Common/CommonLinkerContext.h"28#include "lld/Common/ErrorHandler.h"29#include "lld/Common/LLVM.h"30#include "lld/Common/Memory.h"31#include "lld/Common/Reproduce.h"32#include "lld/Common/Version.h"33#include "llvm/ADT/DenseSet.h"34#include "llvm/ADT/StringExtras.h"35#include "llvm/ADT/StringRef.h"36#include "llvm/BinaryFormat/MachO.h"37#include "llvm/BinaryFormat/Magic.h"38#include "llvm/CGData/CodeGenDataWriter.h"39#include "llvm/Config/llvm-config.h"40#include "llvm/LTO/LTO.h"41#include "llvm/Object/Archive.h"42#include "llvm/Option/ArgList.h"43#include "llvm/Support/CommandLine.h"44#include "llvm/Support/Debug.h"45#include "llvm/Support/FileSystem.h"46#include "llvm/Support/Parallel.h"47#include "llvm/Support/Path.h"48#include "llvm/Support/Process.h"49#include "llvm/Support/TarWriter.h"50#include "llvm/Support/TargetSelect.h"51#include "llvm/Support/Threading.h"52#include "llvm/Support/TimeProfiler.h"53#include "llvm/TargetParser/Host.h"54#include "llvm/TextAPI/Architecture.h"55#include "llvm/TextAPI/PackedVersion.h"56 57#if !_WIN3258#include <sys/mman.h>59#endif60 61using namespace llvm;62using namespace llvm::MachO;63using namespace llvm::object;64using namespace llvm::opt;65using namespace llvm::sys;66using namespace lld;67using namespace lld::macho;68 69std::unique_ptr<Configuration> macho::config;70std::unique_ptr<DependencyTracker> macho::depTracker;71 72static HeaderFileType getOutputType(const InputArgList &args) {73  // TODO: -r, -dylinker, -preload...74  Arg *outputArg = args.getLastArg(OPT_bundle, OPT_dylib, OPT_execute);75  if (outputArg == nullptr)76    return MH_EXECUTE;77 78  switch (outputArg->getOption().getID()) {79  case OPT_bundle:80    return MH_BUNDLE;81  case OPT_dylib:82    return MH_DYLIB;83  case OPT_execute:84    return MH_EXECUTE;85  default:86    llvm_unreachable("internal error");87  }88}89 90static DenseMap<CachedHashStringRef, StringRef> resolvedLibraries;91static std::optional<StringRef> findLibrary(StringRef name) {92  CachedHashStringRef key(name);93  auto entry = resolvedLibraries.find(key);94  if (entry != resolvedLibraries.end())95    return entry->second;96 97  auto doFind = [&] {98    // Special case for Csu support files required for Mac OS X 10.7 and older99    // (crt1.o)100    if (name.ends_with(".o"))101      return findPathCombination(name, config->librarySearchPaths, {""});102    if (config->searchDylibsFirst) {103      if (std::optional<StringRef> path =104              findPathCombination("lib" + name, config->librarySearchPaths,105                                  {".tbd", ".dylib", ".so"}))106        return path;107      return findPathCombination("lib" + name, config->librarySearchPaths,108                                 {".a"});109    }110    return findPathCombination("lib" + name, config->librarySearchPaths,111                               {".tbd", ".dylib", ".so", ".a"});112  };113 114  std::optional<StringRef> path = doFind();115  if (path)116    resolvedLibraries[key] = *path;117 118  return path;119}120 121static DenseMap<CachedHashStringRef, StringRef> resolvedFrameworks;122static std::optional<StringRef> findFramework(StringRef name) {123  CachedHashStringRef key(name);124  auto entry = resolvedFrameworks.find(key);125  if (entry != resolvedFrameworks.end())126    return entry->second;127 128  SmallString<260> symlink;129  StringRef suffix;130  std::tie(name, suffix) = name.split(",");131  for (StringRef dir : config->frameworkSearchPaths) {132    symlink = dir;133    path::append(symlink, name + ".framework", name);134 135    if (!suffix.empty()) {136      // NOTE: we must resolve the symlink before trying the suffixes, because137      // there are no symlinks for the suffixed paths.138      SmallString<260> location;139      if (!fs::real_path(symlink, location)) {140        // only append suffix if realpath() succeeds141        Twine suffixed = location + suffix;142        if (fs::exists(suffixed))143          return resolvedFrameworks[key] = saver().save(suffixed.str());144      }145      // Suffix lookup failed, fall through to the no-suffix case.146    }147 148    if (std::optional<StringRef> path = resolveDylibPath(symlink.str()))149      return resolvedFrameworks[key] = *path;150  }151  return {};152}153 154static bool warnIfNotDirectory(StringRef option, StringRef path) {155  if (!fs::exists(path)) {156    warn("directory not found for option -" + option + path);157    return false;158  } else if (!fs::is_directory(path)) {159    warn("option -" + option + path + " references a non-directory path");160    return false;161  }162  return true;163}164 165static std::vector<StringRef>166getSearchPaths(unsigned optionCode, InputArgList &args,167               const std::vector<StringRef> &roots,168               const SmallVector<StringRef, 2> &systemPaths) {169  std::vector<StringRef> paths;170  StringRef optionLetter{optionCode == OPT_F ? "F" : "L"};171  for (StringRef path : args::getStrings(args, optionCode)) {172    // NOTE: only absolute paths are re-rooted to syslibroot(s)173    bool found = false;174    if (path::is_absolute(path, path::Style::posix)) {175      for (StringRef root : roots) {176        SmallString<261> buffer(root);177        path::append(buffer, path);178        // Do not warn about paths that are computed via the syslib roots179        if (fs::is_directory(buffer)) {180          paths.push_back(saver().save(buffer.str()));181          found = true;182        }183      }184    }185    if (!found && warnIfNotDirectory(optionLetter, path))186      paths.push_back(path);187  }188 189  // `-Z` suppresses the standard "system" search paths.190  if (args.hasArg(OPT_Z))191    return paths;192 193  for (const StringRef &path : systemPaths) {194    for (const StringRef &root : roots) {195      SmallString<261> buffer(root);196      path::append(buffer, path);197      if (fs::is_directory(buffer))198        paths.push_back(saver().save(buffer.str()));199    }200  }201  return paths;202}203 204static std::vector<StringRef> getSystemLibraryRoots(InputArgList &args) {205  std::vector<StringRef> roots;206  for (const Arg *arg : args.filtered(OPT_syslibroot))207    roots.push_back(arg->getValue());208  // NOTE: the final `-syslibroot` being `/` will ignore all roots209  if (!roots.empty() && roots.back() == "/")210    roots.clear();211  // NOTE: roots can never be empty - add an empty root to simplify the library212  // and framework search path computation.213  if (roots.empty())214    roots.emplace_back("");215  return roots;216}217 218static std::vector<StringRef>219getLibrarySearchPaths(InputArgList &args, const std::vector<StringRef> &roots) {220  return getSearchPaths(OPT_L, args, roots, {"/usr/lib", "/usr/local/lib"});221}222 223static std::vector<StringRef>224getFrameworkSearchPaths(InputArgList &args,225                        const std::vector<StringRef> &roots) {226  return getSearchPaths(OPT_F, args, roots,227                        {"/Library/Frameworks", "/System/Library/Frameworks"});228}229 230static llvm::CachePruningPolicy getLTOCachePolicy(InputArgList &args) {231  SmallString<128> ltoPolicy;232  auto add = [&ltoPolicy](Twine val) {233    if (!ltoPolicy.empty())234      ltoPolicy += ":";235    val.toVector(ltoPolicy);236  };237  for (const Arg *arg :238       args.filtered(OPT_thinlto_cache_policy_eq, OPT_prune_interval_lto,239                     OPT_prune_after_lto, OPT_max_relative_cache_size_lto)) {240    switch (arg->getOption().getID()) {241    case OPT_thinlto_cache_policy_eq:242      add(arg->getValue());243      break;244    case OPT_prune_interval_lto:245      if (!strcmp("-1", arg->getValue()))246        add("prune_interval=87600h"); // 10 years247      else248        add(Twine("prune_interval=") + arg->getValue() + "s");249      break;250    case OPT_prune_after_lto:251      add(Twine("prune_after=") + arg->getValue() + "s");252      break;253    case OPT_max_relative_cache_size_lto:254      add(Twine("cache_size=") + arg->getValue() + "%");255      break;256    }257  }258  return CHECK(parseCachePruningPolicy(ltoPolicy), "invalid LTO cache policy");259}260 261// What caused a given library to be loaded. Only relevant for archives.262// Note that this does not tell us *how* we should load the library, i.e.263// whether we should do it lazily or eagerly (AKA force loading). The "how" is264// decided within addFile().265enum class LoadType {266  CommandLine,      // Library was passed as a regular CLI argument267  CommandLineForce, // Library was passed via `-force_load`268  LCLinkerOption,   // Library was passed via LC_LINKER_OPTIONS269};270 271struct ArchiveFileInfo {272  ArchiveFile *file;273  bool isCommandLineLoad;274};275 276static DenseMap<StringRef, ArchiveFileInfo> loadedArchives;277 278static void saveThinArchiveToRepro(ArchiveFile const *file) {279  assert(tar && file->getArchive().isThin());280 281  Error e = Error::success();282  for (const object::Archive::Child &c : file->getArchive().children(e)) {283    MemoryBufferRef mb = CHECK(c.getMemoryBufferRef(),284                               toString(file) + ": failed to get buffer");285    tar->append(relativeToRoot(CHECK(c.getFullName(), file)), mb.getBuffer());286  }287  if (e)288    error(toString(file) +289          ": Archive::children failed: " + toString(std::move(e)));290}291 292struct DeferredFile {293  StringRef path;294  bool isLazy;295  MemoryBufferRef buffer;296};297using DeferredFiles = std::vector<DeferredFile>;298 299#if LLVM_ENABLE_THREADS300class SerialBackgroundWorkQueue {301  std::deque<std::function<void()>> queue;302  std::thread *running;303  std::mutex mutex;304 305public:306  std::atomic_bool stopAllWork = false;307  void queueWork(std::function<void()> work) {308    mutex.lock();309    if (running && queue.empty()) {310      mutex.unlock();311      running->join();312      mutex.lock();313      delete running;314      running = nullptr;315    }316 317    if (work) {318      queue.emplace_back(std::move(work));319      if (!running)320        running = new std::thread([&]() {321          while (!stopAllWork) {322            mutex.lock();323            if (queue.empty()) {324              mutex.unlock();325              break;326            }327            auto work = std::move(queue.front());328            mutex.unlock();329            work();330            mutex.lock();331            queue.pop_front();332            mutex.unlock();333          }334        });335    }336    mutex.unlock();337  }338};339 340static SerialBackgroundWorkQueue pageInQueue;341 342// Most input files have been mapped but not yet paged in.343// This code forces the page-ins on multiple threads so344// the process is not stalled waiting on disk buffer i/o.345void multiThreadedPageInBackground(DeferredFiles &deferred) {346  static const size_t pageSize = Process::getPageSizeEstimate();347  static const size_t largeArchive = 10 * 1024 * 1024;348#ifndef NDEBUG349  using namespace std::chrono;350  static std::atomic_uint64_t totalBytes = 0;351  std::atomic_int numDeferedFilesAdvised = 0;352  auto t0 = high_resolution_clock::now();353#endif354 355  auto preloadDeferredFile = [&](const DeferredFile &deferredFile) {356    const StringRef &buff = deferredFile.buffer.getBuffer();357    if (buff.size() > largeArchive)358      return;359 360#ifndef NDEBUG361    totalBytes += buff.size();362    numDeferedFilesAdvised += 1;363#endif364#if _WIN32365    // Reference all file's mmap'd pages to load them into memory.366    for (const char *page = buff.data(), *end = page + buff.size();367         page < end && !pageInQueue.stopAllWork; page += pageSize) {368      [[maybe_unused]] volatile char t = *page;369      (void)t;370    }371#else372#define DEBUG_TYPE "lld-madvise"373    auto aligned =374        llvm::alignDown(reinterpret_cast<uintptr_t>(buff.data()), pageSize);375    if (madvise((void *)aligned, buff.size(), MADV_WILLNEED) < 0)376      LLVM_DEBUG(llvm::dbgs() << "madvise error: " << strerror(errno) << "\n");377#undef DEBUG_TYPE378#endif379  };380 381  { // Create scope for waiting for the taskGroup382    std::atomic_size_t index = 0;383    llvm::parallel::TaskGroup taskGroup;384    for (int w = 0; w < config->readWorkers; w++)385      taskGroup.spawn([&index, &preloadDeferredFile, &deferred]() {386        while (!pageInQueue.stopAllWork) {387          size_t localIndex = index.fetch_add(1);388          if (localIndex >= deferred.size())389            break;390          preloadDeferredFile(deferred[localIndex]);391        }392      });393  }394 395#ifndef NDEBUG396  auto dt = high_resolution_clock::now() - t0;397  if (Process::GetEnv("LLD_MULTI_THREAD_PAGE"))398    llvm::dbgs() << "multiThreadedPageIn " << totalBytes << "/"399                 << numDeferedFilesAdvised << "/" << deferred.size() << "/"400                 << duration_cast<milliseconds>(dt).count() / 1000. << "\n";401#endif402}403 404static void multiThreadedPageIn(const DeferredFiles &deferred) {405  pageInQueue.queueWork([=]() {406    DeferredFiles files = deferred;407    multiThreadedPageInBackground(files);408  });409}410#endif411 412static InputFile *processFile(std::optional<MemoryBufferRef> buffer,413                              DeferredFiles *archiveContents, StringRef path,414                              LoadType loadType, bool isLazy = false,415                              bool isExplicit = true,416                              bool isBundleLoader = false,417                              bool isForceHidden = false) {418  if (!buffer)419    return nullptr;420  MemoryBufferRef mbref = *buffer;421  InputFile *newFile = nullptr;422 423  file_magic magic = identify_magic(mbref.getBuffer());424  switch (magic) {425  case file_magic::archive: {426    bool isCommandLineLoad = loadType != LoadType::LCLinkerOption;427    // Avoid loading archives twice. If the archives are being force-loaded,428    // loading them twice would create duplicate symbol errors. In the429    // non-force-loading case, this is just a minor performance optimization.430    // We don't take a reference to cachedFile here because the431    // loadArchiveMember() call below may recursively call addFile() and432    // invalidate this reference.433    auto entry = loadedArchives.find(path);434 435    ArchiveFile *file;436    if (entry == loadedArchives.end()) {437      // No cached archive, we need to create a new one438      std::unique_ptr<object::Archive> archive = CHECK(439          object::Archive::create(mbref), path + ": failed to parse archive");440 441      file = make<ArchiveFile>(std::move(archive), isForceHidden);442 443      if (tar && file->getArchive().isThin())444        saveThinArchiveToRepro(file);445    } else {446      file = entry->second.file;447      // Command-line loads take precedence. If file is previously loaded via448      // command line, or is loaded via LC_LINKER_OPTION and being loaded via449      // LC_LINKER_OPTION again, using the cached archive is enough.450      if (entry->second.isCommandLineLoad || !isCommandLineLoad)451        return file;452    }453 454    bool isLCLinkerForceLoad = loadType == LoadType::LCLinkerOption &&455                               config->forceLoadSwift &&456                               path::filename(path).starts_with("libswift");457    if ((isCommandLineLoad && config->allLoad) ||458        loadType == LoadType::CommandLineForce || isLCLinkerForceLoad) {459      if (readFile(path)) {460        Error e = Error::success();461        for (const object::Archive::Child &c : file->getArchive().children(e)) {462          StringRef reason;463          switch (loadType) {464            case LoadType::LCLinkerOption:465              reason = "LC_LINKER_OPTION";466              break;467            case LoadType::CommandLineForce:468              reason = "-force_load";469              break;470            case LoadType::CommandLine:471              reason = "-all_load";472              break;473          }474          if (Error e = file->fetch(c, reason)) {475            if (config->warnThinArchiveMissingMembers)476              warn(toString(file) + ": " + reason +477                   " failed to load archive member: " + toString(std::move(e)));478            else479              llvm::consumeError(std::move(e));480          }481        }482        if (e)483          error(toString(file) +484                ": Archive::children failed: " + toString(std::move(e)));485      }486    } else if (isCommandLineLoad && config->forceLoadObjC) {487      if (file->getArchive().hasSymbolTable()) {488        for (const object::Archive::Symbol &sym : file->getArchive().symbols())489          if (sym.getName().starts_with(objc::symbol_names::klass))490            file->fetch(sym);491      }492 493      // TODO: no need to look for ObjC sections for a given archive member if494      // we already found that it contains an ObjC symbol.495      if (readFile(path)) {496        Error e = Error::success();497        for (const object::Archive::Child &c : file->getArchive().children(e)) {498          Expected<MemoryBufferRef> mb = c.getMemoryBufferRef();499          if (!mb) {500            // We used to create broken repro tarballs that only included those501            // object files from thin archives that ended up being used.502            if (config->warnThinArchiveMissingMembers)503              warn(toString(file) + ": -ObjC failed to open archive member: " +504                   toString(mb.takeError()));505            else506              llvm::consumeError(mb.takeError());507            continue;508          }509 510          if (config->readWorkers && archiveContents)511            archiveContents->push_back({path, isLazy, *mb});512          if (!hasObjCSection(*mb))513            continue;514          if (Error e = file->fetch(c, "-ObjC"))515            error(toString(file) + ": -ObjC failed to load archive member: " +516                  toString(std::move(e)));517        }518        if (e)519          error(toString(file) +520                ": Archive::children failed: " + toString(std::move(e)));521      }522    }523    if (!archiveContents || archiveContents->empty())524      file->addLazySymbols();525    loadedArchives[path] = ArchiveFileInfo{file, isCommandLineLoad};526    newFile = file;527    break;528  }529  case file_magic::macho_object:530    newFile = make<ObjFile>(mbref, getModTime(path), "", isLazy);531    break;532  case file_magic::macho_dynamically_linked_shared_lib:533  case file_magic::macho_dynamically_linked_shared_lib_stub:534  case file_magic::tapi_file:535    if (DylibFile *dylibFile =536            loadDylib(mbref, nullptr, /*isBundleLoader=*/false, isExplicit))537      newFile = dylibFile;538    break;539  case file_magic::bitcode:540    newFile = make<BitcodeFile>(mbref, "", 0, isLazy);541    break;542  case file_magic::macho_executable:543  case file_magic::macho_bundle:544    // We only allow executable and bundle type here if it is used545    // as a bundle loader.546    if (!isBundleLoader)547      error(path + ": unhandled file type");548    if (DylibFile *dylibFile = loadDylib(mbref, nullptr, isBundleLoader))549      newFile = dylibFile;550    break;551  default:552    error(path + ": unhandled file type");553  }554  if (newFile && !isa<DylibFile>(newFile)) {555    if ((isa<ObjFile>(newFile) || isa<BitcodeFile>(newFile)) && newFile->lazy &&556        config->forceLoadObjC) {557      for (Symbol *sym : newFile->symbols)558        if (sym && sym->getName().starts_with(objc::symbol_names::klass)) {559          extract(*newFile, "-ObjC");560          break;561        }562      if (newFile->lazy && hasObjCSection(mbref))563        extract(*newFile, "-ObjC");564    }565 566    // printArchiveMemberLoad() prints both .a and .o names, so no need to567    // print the .a name here. Similarly skip lazy files.568    if (config->printEachFile && magic != file_magic::archive && !isLazy)569      message(toString(newFile));570    inputFiles.insert(newFile);571  }572  return newFile;573}574 575static InputFile *addFile(StringRef path, LoadType loadType,576                          bool isLazy = false, bool isExplicit = true,577                          bool isBundleLoader = false,578                          bool isForceHidden = false) {579  return processFile(readFile(path), nullptr, path, loadType, isLazy,580                     isExplicit, isBundleLoader, isForceHidden);581}582 583static void deferFile(StringRef path, bool isLazy, DeferredFiles &deferred) {584  std::optional<MemoryBufferRef> buffer = readFile(path);585  if (!buffer)586    return;587  if (config->readWorkers)588    deferred.push_back({path, isLazy, *buffer});589  else590    processFile(buffer, nullptr, path, LoadType::CommandLine, isLazy);591}592 593static std::vector<StringRef> missingAutolinkWarnings;594static void addLibrary(StringRef name, bool isNeeded, bool isWeak,595                       bool isReexport, bool isHidden, bool isExplicit,596                       LoadType loadType) {597  if (std::optional<StringRef> path = findLibrary(name)) {598    if (auto *dylibFile = dyn_cast_or_null<DylibFile>(599            addFile(*path, loadType, /*isLazy=*/false, isExplicit,600                    /*isBundleLoader=*/false, isHidden))) {601      if (isNeeded)602        dylibFile->forceNeeded = true;603      if (isWeak)604        dylibFile->forceWeakImport = true;605      if (isReexport) {606        config->hasReexports = true;607        dylibFile->reexport = true;608      }609    }610    return;611  }612  if (loadType == LoadType::LCLinkerOption) {613    missingAutolinkWarnings.push_back(614        saver().save("auto-linked library not found for -l" + name));615    return;616  }617  error("library not found for -l" + name);618}619 620static DenseSet<StringRef> loadedObjectFrameworks;621static void addFramework(StringRef name, bool isNeeded, bool isWeak,622                         bool isReexport, bool isExplicit, LoadType loadType) {623  if (std::optional<StringRef> path = findFramework(name)) {624    if (loadedObjectFrameworks.contains(*path))625      return;626 627    InputFile *file =628        addFile(*path, loadType, /*isLazy=*/false, isExplicit, false);629    if (auto *dylibFile = dyn_cast_or_null<DylibFile>(file)) {630      if (isNeeded)631        dylibFile->forceNeeded = true;632      if (isWeak)633        dylibFile->forceWeakImport = true;634      if (isReexport) {635        config->hasReexports = true;636        dylibFile->reexport = true;637      }638    } else if (isa_and_nonnull<ObjFile>(file) ||639               isa_and_nonnull<BitcodeFile>(file)) {640      // Cache frameworks containing object or bitcode files to avoid duplicate641      // symbols. Frameworks containing static archives are cached separately642      // in addFile() to share caching with libraries, and frameworks643      // containing dylibs should allow overwriting of attributes such as644      // forceNeeded by subsequent loads645      loadedObjectFrameworks.insert(*path);646    }647    return;648  }649  if (loadType == LoadType::LCLinkerOption) {650    missingAutolinkWarnings.push_back(651        saver().save("auto-linked framework not found for -framework " + name));652    return;653  }654  error("framework not found for -framework " + name);655}656 657// Parses LC_LINKER_OPTION contents, which can add additional command line658// flags. This directly parses the flags instead of using the standard argument659// parser to improve performance.660void macho::parseLCLinkerOption(661    llvm::SmallVectorImpl<StringRef> &LCLinkerOptions, InputFile *f,662    unsigned argc, StringRef data) {663  if (config->ignoreAutoLink)664    return;665 666  SmallVector<StringRef, 4> argv;667  size_t offset = 0;668  for (unsigned i = 0; i < argc && offset < data.size(); ++i) {669    argv.push_back(data.data() + offset);670    offset += strlen(data.data() + offset) + 1;671  }672  if (argv.size() != argc || offset > data.size())673    fatal(toString(f) + ": invalid LC_LINKER_OPTION");674 675  unsigned i = 0;676  StringRef arg = argv[i];677  if (arg.consume_front("-l")) {678    if (config->ignoreAutoLinkOptions.contains(arg))679      return;680  } else if (arg == "-framework") {681    StringRef name = argv[++i];682    if (config->ignoreAutoLinkOptions.contains(name))683      return;684  } else {685    error(arg + " is not allowed in LC_LINKER_OPTION");686  }687 688  LCLinkerOptions.append(argv);689}690 691void macho::resolveLCLinkerOptions() {692  while (!unprocessedLCLinkerOptions.empty()) {693    SmallVector<StringRef> LCLinkerOptions(unprocessedLCLinkerOptions);694    unprocessedLCLinkerOptions.clear();695 696    for (unsigned i = 0; i < LCLinkerOptions.size(); ++i) {697      StringRef arg = LCLinkerOptions[i];698      if (arg.consume_front("-l")) {699        assert(!config->ignoreAutoLinkOptions.contains(arg));700        addLibrary(arg, /*isNeeded=*/false, /*isWeak=*/false,701                   /*isReexport=*/false, /*isHidden=*/false,702                   /*isExplicit=*/false, LoadType::LCLinkerOption);703      } else if (arg == "-framework") {704        StringRef name = LCLinkerOptions[++i];705        assert(!config->ignoreAutoLinkOptions.contains(name));706        addFramework(name, /*isNeeded=*/false, /*isWeak=*/false,707                     /*isReexport=*/false, /*isExplicit=*/false,708                     LoadType::LCLinkerOption);709      } else {710        error(arg + " is not allowed in LC_LINKER_OPTION");711      }712    }713  }714}715 716static void addFileList(StringRef path, bool isLazy,717                        DeferredFiles &deferredFiles) {718  std::optional<MemoryBufferRef> buffer = readFile(path);719  if (!buffer)720    return;721  MemoryBufferRef mbref = *buffer;722  for (StringRef path : args::getLines(mbref))723    deferFile(rerootPath(path), isLazy, deferredFiles);724}725 726// We expect sub-library names of the form "libfoo", which will match a dylib727// with a path of .*/libfoo.{dylib, tbd}.728// XXX ld64 seems to ignore the extension entirely when matching sub-libraries;729// I'm not sure what the use case for that is.730static bool markReexport(StringRef searchName, ArrayRef<StringRef> extensions) {731  for (InputFile *file : inputFiles) {732    if (auto *dylibFile = dyn_cast<DylibFile>(file)) {733      StringRef filename = path::filename(dylibFile->getName());734      if (filename.consume_front(searchName) &&735          (filename.empty() || llvm::is_contained(extensions, filename))) {736        dylibFile->reexport = true;737        return true;738      }739    }740  }741  return false;742}743 744// This function is called on startup. We need this for LTO since745// LTO calls LLVM functions to compile bitcode files to native code.746// Technically this can be delayed until we read bitcode files, but747// we don't bother to do lazily because the initialization is fast.748static void initLLVM() {749  InitializeAllTargets();750  InitializeAllTargetMCs();751  InitializeAllAsmPrinters();752  InitializeAllAsmParsers();753}754 755static bool compileBitcodeFiles() {756  TimeTraceScope timeScope("LTO");757  auto *lto = make<BitcodeCompiler>();758  for (InputFile *file : inputFiles)759    if (auto *bitcodeFile = dyn_cast<BitcodeFile>(file))760      if (!file->lazy)761        lto->add(*bitcodeFile);762 763  std::vector<ObjFile *> compiled = lto->compile();764  inputFiles.insert_range(compiled);765 766  return !compiled.empty();767}768 769// Replaces common symbols with defined symbols residing in __common sections.770// This function must be called after all symbol names are resolved (i.e. after771// all InputFiles have been loaded.) As a result, later operations won't see772// any CommonSymbols.773static void replaceCommonSymbols() {774  TimeTraceScope timeScope("Replace common symbols");775  ConcatOutputSection *osec = nullptr;776  for (Symbol *sym : symtab->getSymbols()) {777    auto *common = dyn_cast<CommonSymbol>(sym);778    if (common == nullptr)779      continue;780 781    // Casting to size_t will truncate large values on 32-bit architectures,782    // but it's not really worth supporting the linking of 64-bit programs on783    // 32-bit archs.784    ArrayRef<uint8_t> data = {nullptr, static_cast<size_t>(common->size)};785    // FIXME avoid creating one Section per symbol?786    auto *section =787        make<Section>(common->getFile(), segment_names::data,788                      section_names::common, S_ZEROFILL, /*addr=*/0);789    auto *isec = make<ConcatInputSection>(*section, data, common->align);790    if (!osec)791      osec = ConcatOutputSection::getOrCreateForInput(isec);792    isec->parent = osec;793    addInputSection(isec);794 795    // FIXME: CommonSymbol should store isReferencedDynamically, noDeadStrip796    // and pass them on here.797    replaceSymbol<Defined>(798        sym, sym->getName(), common->getFile(), isec, /*value=*/0, common->size,799        /*isWeakDef=*/false, /*isExternal=*/true, common->privateExtern,800        /*includeInSymtab=*/true, /*isReferencedDynamically=*/false,801        /*noDeadStrip=*/false);802  }803}804 805static void initializeSectionRenameMap() {806  if (config->dataConst) {807    SmallVector<StringRef> v{section_names::got,808                             section_names::authGot,809                             section_names::authPtr,810                             section_names::nonLazySymbolPtr,811                             section_names::const_,812                             section_names::cfString,813                             section_names::moduleInitFunc,814                             section_names::moduleTermFunc,815                             section_names::objcClassList,816                             section_names::objcNonLazyClassList,817                             section_names::objcCatList,818                             section_names::objcNonLazyCatList,819                             section_names::objcProtoList,820                             section_names::objCImageInfo};821    for (StringRef s : v)822      config->sectionRenameMap[{segment_names::data, s}] = {823          segment_names::dataConst, s};824  }825  config->sectionRenameMap[{segment_names::text, section_names::staticInit}] = {826      segment_names::text, section_names::text};827  config->sectionRenameMap[{segment_names::import, section_names::pointers}] = {828      config->dataConst ? segment_names::dataConst : segment_names::data,829      section_names::nonLazySymbolPtr};830}831 832static inline char toLowerDash(char x) {833  if (x >= 'A' && x <= 'Z')834    return x - 'A' + 'a';835  else if (x == ' ')836    return '-';837  return x;838}839 840static std::string lowerDash(StringRef s) {841  return std::string(map_iterator(s.begin(), toLowerDash),842                     map_iterator(s.end(), toLowerDash));843}844 845struct PlatformVersion {846  PlatformType platform = PLATFORM_UNKNOWN;847  llvm::VersionTuple minimum;848  llvm::VersionTuple sdk;849};850 851static PlatformVersion parsePlatformVersion(const Arg *arg) {852  assert(arg->getOption().getID() == OPT_platform_version);853  StringRef platformStr = arg->getValue(0);854  StringRef minVersionStr = arg->getValue(1);855  StringRef sdkVersionStr = arg->getValue(2);856 857  PlatformVersion platformVersion;858 859  // TODO(compnerd) see if we can generate this case list via XMACROS860  platformVersion.platform =861      StringSwitch<PlatformType>(lowerDash(platformStr))862          .Cases({"macos", "1"}, PLATFORM_MACOS)863          .Cases({"ios", "2"}, PLATFORM_IOS)864          .Cases({"tvos", "3"}, PLATFORM_TVOS)865          .Cases({"watchos", "4"}, PLATFORM_WATCHOS)866          .Cases({"bridgeos", "5"}, PLATFORM_BRIDGEOS)867          .Cases({"mac-catalyst", "6"}, PLATFORM_MACCATALYST)868          .Cases({"ios-simulator", "7"}, PLATFORM_IOSSIMULATOR)869          .Cases({"tvos-simulator", "8"}, PLATFORM_TVOSSIMULATOR)870          .Cases({"watchos-simulator", "9"}, PLATFORM_WATCHOSSIMULATOR)871          .Cases({"driverkit", "10"}, PLATFORM_DRIVERKIT)872          .Cases({"xros", "11"}, PLATFORM_XROS)873          .Cases({"xros-simulator", "12"}, PLATFORM_XROS_SIMULATOR)874          .Default(PLATFORM_UNKNOWN);875  if (platformVersion.platform == PLATFORM_UNKNOWN)876    error(Twine("malformed platform: ") + platformStr);877  // TODO: check validity of version strings, which varies by platform878  // NOTE: ld64 accepts version strings with 5 components879  // llvm::VersionTuple accepts no more than 4 components880  // Has Apple ever published version strings with 5 components?881  if (platformVersion.minimum.tryParse(minVersionStr))882    error(Twine("malformed minimum version: ") + minVersionStr);883  if (platformVersion.sdk.tryParse(sdkVersionStr))884    error(Twine("malformed sdk version: ") + sdkVersionStr);885  return platformVersion;886}887 888// Has the side-effect of setting Config::platformInfo and889// potentially Config::secondaryPlatformInfo.890static void setPlatformVersions(StringRef archName, const ArgList &args) {891  std::map<PlatformType, PlatformVersion> platformVersions;892  const PlatformVersion *lastVersionInfo = nullptr;893  for (const Arg *arg : args.filtered(OPT_platform_version)) {894    PlatformVersion version = parsePlatformVersion(arg);895 896    // For each platform, the last flag wins:897    // `-platform_version macos 2 3 -platform_version macos 4 5` has the same898    // effect as just passing `-platform_version macos 4 5`.899    // FIXME: ld64 warns on multiple flags for one platform. Should we?900    platformVersions[version.platform] = version;901    lastVersionInfo = &platformVersions[version.platform];902  }903 904  if (platformVersions.empty()) {905    error("must specify -platform_version");906    return;907  }908  if (platformVersions.size() > 2) {909    error("must specify -platform_version at most twice");910    return;911  }912  if (platformVersions.size() == 2) {913    bool isZipperedCatalyst = platformVersions.count(PLATFORM_MACOS) &&914                              platformVersions.count(PLATFORM_MACCATALYST);915 916    if (!isZipperedCatalyst) {917      error("lld supports writing zippered outputs only for "918            "macos and mac-catalyst");919    } else if (config->outputType != MH_DYLIB &&920               config->outputType != MH_BUNDLE) {921      error("writing zippered outputs only valid for -dylib and -bundle");922    }923 924    config->platformInfo = {925        MachO::Target(getArchitectureFromName(archName), PLATFORM_MACOS,926                      platformVersions[PLATFORM_MACOS].minimum),927        platformVersions[PLATFORM_MACOS].sdk};928    config->secondaryPlatformInfo = {929        MachO::Target(getArchitectureFromName(archName), PLATFORM_MACCATALYST,930                      platformVersions[PLATFORM_MACCATALYST].minimum),931        platformVersions[PLATFORM_MACCATALYST].sdk};932    return;933  }934 935  config->platformInfo = {MachO::Target(getArchitectureFromName(archName),936                                        lastVersionInfo->platform,937                                        lastVersionInfo->minimum),938                          lastVersionInfo->sdk};939}940 941// Has the side-effect of setting Config::target.942static TargetInfo *createTargetInfo(InputArgList &args) {943  StringRef archName = args.getLastArgValue(OPT_arch);944  if (archName.empty()) {945    error("must specify -arch");946    return nullptr;947  }948 949  setPlatformVersions(archName, args);950  auto [cpuType, cpuSubtype] = getCPUTypeFromArchitecture(config->arch());951  switch (cpuType) {952  case CPU_TYPE_X86_64:953    return createX86_64TargetInfo();954  case CPU_TYPE_ARM64:955    return createARM64TargetInfo();956  case CPU_TYPE_ARM64_32:957    return createARM64_32TargetInfo();958  default:959    error("missing or unsupported -arch " + archName);960    return nullptr;961  }962}963 964static UndefinedSymbolTreatment965getUndefinedSymbolTreatment(const ArgList &args) {966  StringRef treatmentStr = args.getLastArgValue(OPT_undefined);967  auto treatment =968      StringSwitch<UndefinedSymbolTreatment>(treatmentStr)969          .Cases({"error", ""}, UndefinedSymbolTreatment::error)970          .Case("warning", UndefinedSymbolTreatment::warning)971          .Case("suppress", UndefinedSymbolTreatment::suppress)972          .Case("dynamic_lookup", UndefinedSymbolTreatment::dynamic_lookup)973          .Default(UndefinedSymbolTreatment::unknown);974  if (treatment == UndefinedSymbolTreatment::unknown) {975    warn(Twine("unknown -undefined TREATMENT '") + treatmentStr +976         "', defaulting to 'error'");977    treatment = UndefinedSymbolTreatment::error;978  } else if (config->namespaceKind == NamespaceKind::twolevel &&979             (treatment == UndefinedSymbolTreatment::warning ||980              treatment == UndefinedSymbolTreatment::suppress)) {981    if (treatment == UndefinedSymbolTreatment::warning)982      fatal("'-undefined warning' only valid with '-flat_namespace'");983    else984      fatal("'-undefined suppress' only valid with '-flat_namespace'");985    treatment = UndefinedSymbolTreatment::error;986  }987  return treatment;988}989 990static ICFLevel getICFLevel(const ArgList &args) {991  StringRef icfLevelStr = args.getLastArgValue(OPT_icf_eq);992  auto icfLevel = StringSwitch<ICFLevel>(icfLevelStr)993                      .Cases({"none", ""}, ICFLevel::none)994                      .Case("safe", ICFLevel::safe)995                      .Case("safe_thunks", ICFLevel::safe_thunks)996                      .Case("all", ICFLevel::all)997                      .Default(ICFLevel::unknown);998 999  if ((icfLevel == ICFLevel::safe_thunks) && (config->arch() != AK_arm64)) {1000    error("--icf=safe_thunks is only supported on arm64 targets");1001  }1002 1003  if (icfLevel == ICFLevel::unknown) {1004    warn(Twine("unknown --icf=OPTION `") + icfLevelStr +1005         "', defaulting to `none'");1006    icfLevel = ICFLevel::none;1007  }1008  return icfLevel;1009}1010 1011static ObjCStubsMode getObjCStubsMode(const ArgList &args) {1012  const Arg *arg = args.getLastArg(OPT_objc_stubs_fast, OPT_objc_stubs_small);1013  if (!arg)1014    return ObjCStubsMode::fast;1015 1016  if (arg->getOption().getID() == OPT_objc_stubs_small) {1017    if (is_contained({AK_arm64e, AK_arm64}, config->arch()))1018      return ObjCStubsMode::small;1019    else1020      warn("-objc_stubs_small is not yet implemented, defaulting to "1021           "-objc_stubs_fast");1022  }1023  return ObjCStubsMode::fast;1024}1025 1026static void warnIfDeprecatedOption(const Option &opt) {1027  if (!opt.getGroup().isValid())1028    return;1029  if (opt.getGroup().getID() == OPT_grp_deprecated) {1030    warn("Option `" + opt.getPrefixedName() + "' is deprecated in ld64:");1031    warn(opt.getHelpText());1032  }1033}1034 1035static void warnIfUnimplementedOption(const Option &opt) {1036  if (!opt.getGroup().isValid() || !opt.hasFlag(DriverFlag::HelpHidden))1037    return;1038  switch (opt.getGroup().getID()) {1039  case OPT_grp_deprecated:1040    // warn about deprecated options elsewhere1041    break;1042  case OPT_grp_undocumented:1043    warn("Option `" + opt.getPrefixedName() +1044         "' is undocumented. Should lld implement it?");1045    break;1046  case OPT_grp_obsolete:1047    warn("Option `" + opt.getPrefixedName() +1048         "' is obsolete. Please modernize your usage.");1049    break;1050  case OPT_grp_ignored:1051    warn("Option `" + opt.getPrefixedName() + "' is ignored.");1052    break;1053  case OPT_grp_ignored_silently:1054    break;1055  default:1056    warn("Option `" + opt.getPrefixedName() +1057         "' is not yet implemented. Stay tuned...");1058    break;1059  }1060}1061 1062static const char *getReproduceOption(InputArgList &args) {1063  if (const Arg *arg = args.getLastArg(OPT_reproduce))1064    return arg->getValue();1065  return getenv("LLD_REPRODUCE");1066}1067 1068// Parse options of the form "old;new".1069static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &args,1070                                                        unsigned id) {1071  auto *arg = args.getLastArg(id);1072  if (!arg)1073    return {"", ""};1074 1075  StringRef s = arg->getValue();1076  std::pair<StringRef, StringRef> ret = s.split(';');1077  if (ret.second.empty())1078    error(arg->getSpelling() + " expects 'old;new' format, but got " + s);1079  return ret;1080}1081 1082// Parse options of the form "old;new[;extra]".1083static std::tuple<StringRef, StringRef, StringRef>1084getOldNewOptionsExtra(opt::InputArgList &args, unsigned id) {1085  auto [oldDir, second] = getOldNewOptions(args, id);1086  auto [newDir, extraDir] = second.split(';');1087  return {oldDir, newDir, extraDir};1088}1089 1090static void parseClangOption(StringRef opt, const Twine &msg) {1091  std::string err;1092  raw_string_ostream os(err);1093 1094  const char *argv[] = {"lld", opt.data()};1095  if (cl::ParseCommandLineOptions(2, argv, "", &os))1096    return;1097  error(msg + ": " + StringRef(err).trim());1098}1099 1100static uint32_t parseDylibVersion(const ArgList &args, unsigned id) {1101  const Arg *arg = args.getLastArg(id);1102  if (!arg)1103    return 0;1104 1105  if (config->outputType != MH_DYLIB) {1106    error(arg->getAsString(args) + ": only valid with -dylib");1107    return 0;1108  }1109 1110  PackedVersion version;1111  if (!version.parse32(arg->getValue())) {1112    error(arg->getAsString(args) + ": malformed version");1113    return 0;1114  }1115 1116  return version.rawValue();1117}1118 1119static uint32_t parseProtection(StringRef protStr) {1120  uint32_t prot = 0;1121  for (char c : protStr) {1122    switch (c) {1123    case 'r':1124      prot |= VM_PROT_READ;1125      break;1126    case 'w':1127      prot |= VM_PROT_WRITE;1128      break;1129    case 'x':1130      prot |= VM_PROT_EXECUTE;1131      break;1132    case '-':1133      break;1134    default:1135      error("unknown -segprot letter '" + Twine(c) + "' in " + protStr);1136      return 0;1137    }1138  }1139  return prot;1140}1141 1142static std::vector<SectionAlign> parseSectAlign(const opt::InputArgList &args) {1143  std::vector<SectionAlign> sectAligns;1144  for (const Arg *arg : args.filtered(OPT_sectalign)) {1145    StringRef segName = arg->getValue(0);1146    StringRef sectName = arg->getValue(1);1147    StringRef alignStr = arg->getValue(2);1148    alignStr.consume_front_insensitive("0x");1149    uint32_t align;1150    if (alignStr.getAsInteger(16, align)) {1151      error("-sectalign: failed to parse '" + StringRef(arg->getValue(2)) +1152            "' as number");1153      continue;1154    }1155    if (!isPowerOf2_32(align)) {1156      error("-sectalign: '" + StringRef(arg->getValue(2)) +1157            "' (in base 16) not a power of two");1158      continue;1159    }1160    sectAligns.push_back({segName, sectName, align});1161  }1162  return sectAligns;1163}1164 1165PlatformType macho::removeSimulator(PlatformType platform) {1166  switch (platform) {1167  case PLATFORM_IOSSIMULATOR:1168    return PLATFORM_IOS;1169  case PLATFORM_TVOSSIMULATOR:1170    return PLATFORM_TVOS;1171  case PLATFORM_WATCHOSSIMULATOR:1172    return PLATFORM_WATCHOS;1173  case PLATFORM_XROS_SIMULATOR:1174    return PLATFORM_XROS;1175  default:1176    return platform;1177  }1178}1179 1180static bool supportsNoPie() {1181  return !(config->arch() == AK_arm64 || config->arch() == AK_arm64e ||1182           config->arch() == AK_arm64_32);1183}1184 1185static bool shouldAdhocSignByDefault(Architecture arch, PlatformType platform) {1186  if (arch != AK_arm64 && arch != AK_arm64e)1187    return false;1188 1189  return platform == PLATFORM_MACOS || platform == PLATFORM_IOSSIMULATOR ||1190         platform == PLATFORM_TVOSSIMULATOR ||1191         platform == PLATFORM_WATCHOSSIMULATOR ||1192         platform == PLATFORM_XROS_SIMULATOR;1193}1194 1195template <std::size_t N>1196using MinVersions = std::array<std::pair<PlatformType, VersionTuple>, N>;1197 1198/// Returns true if the platform is greater than the min version.1199/// Returns false if the platform does not exist.1200template <std::size_t N>1201static bool greaterEqMinVersion(const MinVersions<N> &minVersions,1202                                bool ignoreSimulator) {1203  PlatformType platform = config->platformInfo.target.Platform;1204  if (ignoreSimulator)1205    platform = removeSimulator(platform);1206  auto it = llvm::find_if(minVersions,1207                          [&](const auto &p) { return p.first == platform; });1208  if (it != minVersions.end())1209    if (config->platformInfo.target.MinDeployment >= it->second)1210      return true;1211  return false;1212}1213 1214static bool dataConstDefault(const InputArgList &args) {1215  static const MinVersions<6> minVersion = {{1216      {PLATFORM_MACOS, VersionTuple(10, 15)},1217      {PLATFORM_IOS, VersionTuple(13, 0)},1218      {PLATFORM_TVOS, VersionTuple(13, 0)},1219      {PLATFORM_WATCHOS, VersionTuple(6, 0)},1220      {PLATFORM_XROS, VersionTuple(1, 0)},1221      {PLATFORM_BRIDGEOS, VersionTuple(4, 0)},1222  }};1223  if (!greaterEqMinVersion(minVersion, true))1224    return false;1225 1226  switch (config->outputType) {1227  case MH_EXECUTE:1228    return !(args.hasArg(OPT_no_pie) && supportsNoPie());1229  case MH_BUNDLE:1230    // FIXME: return false when -final_name ...1231    // has prefix "/System/Library/UserEventPlugins/"1232    // or matches "/usr/libexec/locationd" "/usr/libexec/terminusd"1233    return true;1234  case MH_DYLIB:1235    return true;1236  case MH_OBJECT:1237    return false;1238  default:1239    llvm_unreachable(1240        "unsupported output type for determining data-const default");1241  }1242  return false;1243}1244 1245static bool shouldEmitChainedFixups(const InputArgList &args) {1246  const Arg *arg = args.getLastArg(OPT_fixup_chains, OPT_no_fixup_chains);1247  if (arg && arg->getOption().matches(OPT_no_fixup_chains))1248    return false;1249 1250  bool requested = arg && arg->getOption().matches(OPT_fixup_chains);1251  if (!config->isPic) {1252    if (requested)1253      error("-fixup_chains is incompatible with -no_pie");1254 1255    return false;1256  }1257 1258  if (!is_contained({AK_x86_64, AK_x86_64h, AK_arm64}, config->arch())) {1259    if (requested)1260      error("-fixup_chains is only supported on x86_64 and arm64 targets");1261 1262    return false;1263  }1264 1265  if (args.hasArg(OPT_preload)) {1266    if (requested)1267      error("-fixup_chains is incompatible with -preload");1268 1269    return false;1270  }1271 1272  if (requested)1273    return true;1274 1275  static const MinVersions<9> minVersion = {{1276      {PLATFORM_IOS, VersionTuple(13, 4)},1277      {PLATFORM_IOSSIMULATOR, VersionTuple(16, 0)},1278      {PLATFORM_MACOS, VersionTuple(13, 0)},1279      {PLATFORM_TVOS, VersionTuple(14, 0)},1280      {PLATFORM_TVOSSIMULATOR, VersionTuple(15, 0)},1281      {PLATFORM_WATCHOS, VersionTuple(7, 0)},1282      {PLATFORM_WATCHOSSIMULATOR, VersionTuple(8, 0)},1283      {PLATFORM_XROS, VersionTuple(1, 0)},1284      {PLATFORM_XROS_SIMULATOR, VersionTuple(1, 0)},1285  }};1286  return greaterEqMinVersion(minVersion, false);1287}1288 1289static bool shouldEmitRelativeMethodLists(const InputArgList &args) {1290  const Arg *arg = args.getLastArg(OPT_objc_relative_method_lists,1291                                   OPT_no_objc_relative_method_lists);1292  if (arg && arg->getOption().getID() == OPT_objc_relative_method_lists)1293    return true;1294  if (arg && arg->getOption().getID() == OPT_no_objc_relative_method_lists)1295    return false;1296 1297  // If no flag is specified, enable this on newer versions by default.1298  // The min versions is taken from1299  // ld64(https://github.com/apple-oss-distributions/ld64/blob/47f477cb721755419018f7530038b272e9d0cdea/src/ld/ld.hpp#L310)1300  // to mimic to operation of ld641301  // [here](https://github.com/apple-oss-distributions/ld64/blob/47f477cb721755419018f7530038b272e9d0cdea/src/ld/Options.cpp#L6085-L6101)1302  static const MinVersions<6> minVersion = {{1303      {PLATFORM_MACOS, VersionTuple(10, 16)},1304      {PLATFORM_IOS, VersionTuple(14, 0)},1305      {PLATFORM_WATCHOS, VersionTuple(7, 0)},1306      {PLATFORM_TVOS, VersionTuple(14, 0)},1307      {PLATFORM_BRIDGEOS, VersionTuple(5, 0)},1308      {PLATFORM_XROS, VersionTuple(1, 0)},1309  }};1310  return greaterEqMinVersion(minVersion, true);1311}1312 1313void SymbolPatterns::clear() {1314  literals.clear();1315  globs.clear();1316}1317 1318void SymbolPatterns::insert(StringRef symbolName) {1319  if (symbolName.find_first_of("*?[]") == StringRef::npos)1320    literals.insert(CachedHashStringRef(symbolName));1321  else if (Expected<GlobPattern> pattern = GlobPattern::create(symbolName))1322    globs.emplace_back(*pattern);1323  else1324    error("invalid symbol-name pattern: " + symbolName);1325}1326 1327bool SymbolPatterns::matchLiteral(StringRef symbolName) const {1328  return literals.contains(CachedHashStringRef(symbolName));1329}1330 1331bool SymbolPatterns::matchGlob(StringRef symbolName) const {1332  for (const GlobPattern &glob : globs)1333    if (glob.match(symbolName))1334      return true;1335  return false;1336}1337 1338bool SymbolPatterns::match(StringRef symbolName) const {1339  return matchLiteral(symbolName) || matchGlob(symbolName);1340}1341 1342static void parseSymbolPatternsFile(const Arg *arg,1343                                    SymbolPatterns &symbolPatterns) {1344  StringRef path = arg->getValue();1345  std::optional<MemoryBufferRef> buffer = readFile(path);1346  if (!buffer) {1347    error("Could not read symbol file: " + path);1348    return;1349  }1350  MemoryBufferRef mbref = *buffer;1351  for (StringRef line : args::getLines(mbref)) {1352    line = line.take_until([](char c) { return c == '#'; }).trim();1353    if (!line.empty())1354      symbolPatterns.insert(line);1355  }1356}1357 1358static void handleSymbolPatterns(InputArgList &args,1359                                 SymbolPatterns &symbolPatterns,1360                                 unsigned singleOptionCode,1361                                 unsigned listFileOptionCode) {1362  for (const Arg *arg : args.filtered(singleOptionCode))1363    symbolPatterns.insert(arg->getValue());1364  for (const Arg *arg : args.filtered(listFileOptionCode))1365    parseSymbolPatternsFile(arg, symbolPatterns);1366}1367 1368static void createFiles(const InputArgList &args) {1369  TimeTraceScope timeScope("Load input files");1370  // This loop should be reserved for options whose exact ordering matters.1371  // Other options should be handled via filtered() and/or getLastArg().1372  bool isLazy = false;1373  // If we've processed an opening --start-lib, without a matching --end-lib1374  bool inLib = false;1375  DeferredFiles deferredFiles;1376 1377  for (const Arg *arg : args) {1378    const Option &opt = arg->getOption();1379    warnIfDeprecatedOption(opt);1380    warnIfUnimplementedOption(opt);1381 1382    switch (opt.getID()) {1383    case OPT_INPUT:1384      deferFile(rerootPath(arg->getValue()), isLazy, deferredFiles);1385      break;1386    case OPT_needed_library:1387      if (auto *dylibFile = dyn_cast_or_null<DylibFile>(1388              addFile(rerootPath(arg->getValue()), LoadType::CommandLine)))1389        dylibFile->forceNeeded = true;1390      break;1391    case OPT_reexport_library:1392      if (auto *dylibFile = dyn_cast_or_null<DylibFile>(1393              addFile(rerootPath(arg->getValue()), LoadType::CommandLine))) {1394        config->hasReexports = true;1395        dylibFile->reexport = true;1396      }1397      break;1398    case OPT_weak_library:1399      if (auto *dylibFile = dyn_cast_or_null<DylibFile>(1400              addFile(rerootPath(arg->getValue()), LoadType::CommandLine)))1401        dylibFile->forceWeakImport = true;1402      break;1403    case OPT_filelist:1404      addFileList(arg->getValue(), isLazy, deferredFiles);1405      break;1406    case OPT_force_load:1407      addFile(rerootPath(arg->getValue()), LoadType::CommandLineForce);1408      break;1409    case OPT_load_hidden:1410      addFile(rerootPath(arg->getValue()), LoadType::CommandLine,1411              /*isLazy=*/false, /*isExplicit=*/true, /*isBundleLoader=*/false,1412              /*isForceHidden=*/true);1413      break;1414    case OPT_l:1415    case OPT_needed_l:1416    case OPT_reexport_l:1417    case OPT_weak_l:1418    case OPT_hidden_l:1419      addLibrary(arg->getValue(), opt.getID() == OPT_needed_l,1420                 opt.getID() == OPT_weak_l, opt.getID() == OPT_reexport_l,1421                 opt.getID() == OPT_hidden_l,1422                 /*isExplicit=*/true, LoadType::CommandLine);1423      break;1424    case OPT_framework:1425    case OPT_needed_framework:1426    case OPT_reexport_framework:1427    case OPT_weak_framework:1428      addFramework(arg->getValue(), opt.getID() == OPT_needed_framework,1429                   opt.getID() == OPT_weak_framework,1430                   opt.getID() == OPT_reexport_framework, /*isExplicit=*/true,1431                   LoadType::CommandLine);1432      break;1433    case OPT_start_lib:1434      if (inLib)1435        error("nested --start-lib");1436      inLib = true;1437      if (!config->allLoad)1438        isLazy = true;1439      break;1440    case OPT_end_lib:1441      if (!inLib)1442        error("stray --end-lib");1443      inLib = false;1444      isLazy = false;1445      break;1446    default:1447      break;1448    }1449  }1450 1451#if LLVM_ENABLE_THREADS1452  if (config->readWorkers) {1453    multiThreadedPageIn(deferredFiles);1454 1455    DeferredFiles archiveContents;1456    std::vector<ArchiveFile *> archives;1457    for (auto &file : deferredFiles) {1458      auto inputFile = processFile(file.buffer, &archiveContents, file.path,1459                                   LoadType::CommandLine, file.isLazy);1460      if (ArchiveFile *archive = dyn_cast<ArchiveFile>(inputFile))1461        archives.push_back(archive);1462    }1463 1464    if (!archiveContents.empty())1465      multiThreadedPageIn(archiveContents);1466    for (auto *archive : archives)1467      archive->addLazySymbols();1468 1469    pageInQueue.stopAllWork = true;1470  }1471#endif1472}1473 1474static void gatherInputSections() {1475  TimeTraceScope timeScope("Gathering input sections");1476  for (const InputFile *file : inputFiles) {1477    for (const Section *section : file->sections) {1478      // Compact unwind entries require special handling elsewhere. (In1479      // contrast, EH frames are handled like regular ConcatInputSections.)1480      if (section->name == section_names::compactUnwind)1481        continue;1482      // Addrsig sections contain metadata only needed at link time.1483      if (section->name == section_names::addrSig)1484        continue;1485      for (const Subsection &subsection : section->subsections)1486        addInputSection(subsection.isec);1487    }1488    if (!file->objCImageInfo.empty())1489      in.objCImageInfo->addFile(file);1490  }1491}1492 1493static void codegenDataGenerate() {1494  TimeTraceScope timeScope("Generating codegen data");1495 1496  OutlinedHashTreeRecord globalOutlineRecord;1497  StableFunctionMapRecord globalMergeRecord;1498  for (ConcatInputSection *isec : inputSections) {1499    if (isec->getSegName() != segment_names::data)1500      continue;1501    if (isec->getName() == section_names::outlinedHashTree) {1502      // Read outlined hash tree from each section.1503      OutlinedHashTreeRecord localOutlineRecord;1504      // Use a pointer to allow modification by the function.1505      auto *data = isec->data.data();1506      localOutlineRecord.deserialize(data);1507 1508      // Merge it to the global hash tree.1509      globalOutlineRecord.merge(localOutlineRecord);1510    }1511    if (isec->getName() == section_names::functionMap) {1512      // Read stable functions from each section.1513      StableFunctionMapRecord localMergeRecord;1514      // Use a pointer to allow modification by the function.1515      auto *data = isec->data.data();1516      localMergeRecord.deserialize(data);1517 1518      // Merge it to the global function map.1519      globalMergeRecord.merge(localMergeRecord);1520    }1521  }1522 1523  globalMergeRecord.finalize();1524 1525  CodeGenDataWriter Writer;1526  if (!globalOutlineRecord.empty())1527    Writer.addRecord(globalOutlineRecord);1528  if (!globalMergeRecord.empty())1529    Writer.addRecord(globalMergeRecord);1530 1531  std::error_code EC;1532  auto fileName = config->codegenDataGeneratePath;1533  assert(!fileName.empty());1534  raw_fd_ostream Output(fileName, EC, sys::fs::OF_None);1535  if (EC)1536    error("fail to create " + fileName + ": " + EC.message());1537 1538  if (auto E = Writer.write(Output))1539    error("fail to write CGData: " + toString(std::move(E)));1540}1541 1542static void foldIdenticalLiterals() {1543  TimeTraceScope timeScope("Fold identical literals");1544  // We always create a cStringSection, regardless of whether dedupLiterals is1545  // true. If it isn't, we simply create a non-deduplicating CStringSection.1546  // Either way, we must unconditionally finalize it here.1547  for (auto *sec : in.cStringSections)1548    sec->finalizeContents();1549  in.wordLiteralSection->finalizeContents();1550}1551 1552static void addSynthenticMethnames() {1553  std::string &data = *make<std::string>();1554  llvm::raw_string_ostream os(data);1555  for (Symbol *sym : symtab->getSymbols())1556    if (isa<Undefined>(sym))1557      if (ObjCStubsSection::isObjCStubSymbol(sym))1558        os << ObjCStubsSection::getMethname(sym) << '\0';1559 1560  if (data.empty())1561    return;1562 1563  const auto *buf = reinterpret_cast<const uint8_t *>(data.c_str());1564  Section &section = *make<Section>(/*file=*/nullptr, segment_names::text,1565                                    section_names::objcMethname,1566                                    S_CSTRING_LITERALS, /*addr=*/0);1567 1568  auto *isec =1569      make<CStringInputSection>(section, ArrayRef<uint8_t>{buf, data.size()},1570                                /*align=*/1, /*dedupLiterals=*/true);1571  isec->splitIntoPieces();1572  for (auto &piece : isec->pieces)1573    piece.live = true;1574  section.subsections.push_back({0, isec});1575  in.objcMethnameSection->addInput(isec);1576  in.objcMethnameSection->isec->markLive(0);1577}1578 1579static void referenceStubBinder() {1580  bool needsStubHelper = config->outputType == MH_DYLIB ||1581                         config->outputType == MH_EXECUTE ||1582                         config->outputType == MH_BUNDLE;1583  if (!needsStubHelper || !symtab->find("dyld_stub_binder"))1584    return;1585 1586  // dyld_stub_binder is used by dyld to resolve lazy bindings. This code here1587  // adds a opportunistic reference to dyld_stub_binder if it happens to exist.1588  // dyld_stub_binder is in libSystem.dylib, which is usually linked in. This1589  // isn't needed for correctness, but the presence of that symbol suppresses1590  // "no symbols" diagnostics from `nm`.1591  // StubHelperSection::setUp() adds a reference and errors out if1592  // dyld_stub_binder doesn't exist in case it is actually needed.1593  symtab->addUndefined("dyld_stub_binder", /*file=*/nullptr, /*isWeak=*/false);1594}1595 1596static void createAliases() {1597  for (const auto &pair : config->aliasedSymbols) {1598    if (const auto &sym = symtab->find(pair.first)) {1599      if (const auto &defined = dyn_cast<Defined>(sym)) {1600        symtab->aliasDefined(defined, pair.second, defined->getFile())1601            ->noDeadStrip = true;1602      } else {1603        error("TODO: support aliasing to symbols of kind " +1604              Twine(sym->kind()));1605      }1606    } else {1607      warn("undefined base symbol '" + pair.first + "' for alias '" +1608           pair.second + "'\n");1609    }1610  }1611 1612  for (const InputFile *file : inputFiles) {1613    if (auto *objFile = dyn_cast<ObjFile>(file)) {1614      for (const AliasSymbol *alias : objFile->aliases) {1615        if (const auto &aliased = symtab->find(alias->getAliasedName())) {1616          if (const auto &defined = dyn_cast<Defined>(aliased)) {1617            symtab->aliasDefined(defined, alias->getName(), alias->getFile(),1618                                 alias->privateExtern);1619          } else {1620            // Common, dylib, and undefined symbols are all valid alias1621            // referents (undefineds can become valid Defined symbols later on1622            // in the link.)1623            error("TODO: support aliasing to symbols of kind " +1624                  Twine(aliased->kind()));1625          }1626        } else {1627          // This shouldn't happen since MC generates undefined symbols to1628          // represent the alias referents. Thus we fatal() instead of just1629          // warning here.1630          fatal("unable to find alias referent " + alias->getAliasedName() +1631                " for " + alias->getName());1632        }1633      }1634    }1635  }1636}1637 1638static void handleExplicitExports() {1639  static constexpr int kMaxWarnings = 3;1640  if (config->hasExplicitExports) {1641    std::atomic<uint64_t> warningsCount{0};1642    parallelForEach(symtab->getSymbols(), [&warningsCount](Symbol *sym) {1643      if (auto *defined = dyn_cast<Defined>(sym)) {1644        if (config->exportedSymbols.match(sym->getName())) {1645          if (defined->privateExtern) {1646            if (defined->weakDefCanBeHidden) {1647              // weak_def_can_be_hidden symbols behave similarly to1648              // private_extern symbols in most cases, except for when1649              // it is explicitly exported.1650              // The former can be exported but the latter cannot.1651              defined->privateExtern = false;1652            } else {1653              // Only print the first 3 warnings verbosely, and1654              // shorten the rest to avoid crowding logs.1655              if (warningsCount.fetch_add(1, std::memory_order_relaxed) <1656                  kMaxWarnings)1657                warn("cannot export hidden symbol " + toString(*defined) +1658                     "\n>>> defined in " + toString(defined->getFile()));1659            }1660          }1661        } else {1662          defined->privateExtern = true;1663        }1664      } else if (auto *dysym = dyn_cast<DylibSymbol>(sym)) {1665        dysym->shouldReexport = config->exportedSymbols.match(sym->getName());1666      }1667    });1668    if (warningsCount > kMaxWarnings)1669      warn("<... " + Twine(warningsCount - kMaxWarnings) +1670           " more similar warnings...>");1671  } else if (!config->unexportedSymbols.empty()) {1672    parallelForEach(symtab->getSymbols(), [](Symbol *sym) {1673      if (auto *defined = dyn_cast<Defined>(sym))1674        if (config->unexportedSymbols.match(defined->getName()))1675          defined->privateExtern = true;1676    });1677  }1678}1679 1680static void eraseInitializerSymbols() {1681  for (ConcatInputSection *isec : in.initOffsets->inputs())1682    for (Defined *sym : isec->symbols)1683      sym->used = false;1684}1685 1686static SmallVector<StringRef, 0> getRuntimePaths(opt::InputArgList &args) {1687  SmallVector<StringRef, 0> vals;1688  DenseSet<StringRef> seen;1689  for (const Arg *arg : args.filtered(OPT_rpath)) {1690    StringRef val = arg->getValue();1691    if (seen.insert(val).second)1692      vals.push_back(val);1693    else if (config->warnDuplicateRpath)1694      warn("duplicate -rpath '" + val + "' ignored [--warn-duplicate-rpath]");1695  }1696  return vals;1697}1698 1699static SmallVector<StringRef, 0> getAllowableClients(opt::InputArgList &args) {1700  SmallVector<StringRef, 0> vals;1701  DenseSet<StringRef> seen;1702  for (const Arg *arg : args.filtered(OPT_allowable_client)) {1703    StringRef val = arg->getValue();1704    if (seen.insert(val).second)1705      vals.push_back(val);1706  }1707  return vals;1708}1709 1710namespace lld {1711namespace macho {1712bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,1713          llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {1714  // This driver-specific context will be freed later by lldMain().1715  auto *ctx = new CommonLinkerContext;1716 1717  ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);1718  ctx->e.cleanupCallback = []() {1719    resolvedFrameworks.clear();1720    resolvedLibraries.clear();1721    cachedReads.clear();1722    concatOutputSections.clear();1723    inputFiles.clear();1724    inputSections.clear();1725    inputSectionsOrder = 0;1726    loadedArchives.clear();1727    loadedObjectFrameworks.clear();1728    missingAutolinkWarnings.clear();1729    syntheticSections.clear();1730    thunkMap.clear();1731    unprocessedLCLinkerOptions.clear();1732    ObjCSelRefsHelper::cleanup();1733 1734    firstTLVDataSection = nullptr;1735    tar = nullptr;1736    in = InStruct();1737 1738    resetLoadedDylibs();1739    resetOutputSegments();1740    resetWriter();1741    InputFile::resetIdCount();1742 1743    objc::doCleanup();1744  };1745 1746  ctx->e.logName = args::getFilenameWithoutExe(argsArr[0]);1747 1748  MachOOptTable parser;1749  InputArgList args = parser.parse(*ctx, argsArr.slice(1));1750 1751  ctx->e.errorLimitExceededMsg = "too many errors emitted, stopping now "1752                                 "(use --error-limit=0 to see all errors)";1753  ctx->e.errorLimit = args::getInteger(args, OPT_error_limit_eq, 20);1754  ctx->e.verbose = args.hasArg(OPT_verbose);1755 1756  if (args.hasArg(OPT_help_hidden)) {1757    parser.printHelp(*ctx, argsArr[0], /*showHidden=*/true);1758    return true;1759  }1760  if (args.hasArg(OPT_help)) {1761    parser.printHelp(*ctx, argsArr[0], /*showHidden=*/false);1762    return true;1763  }1764  if (args.hasArg(OPT_version)) {1765    message(getLLDVersion());1766    return true;1767  }1768 1769  config = std::make_unique<Configuration>();1770  symtab = std::make_unique<SymbolTable>();1771  config->outputType = getOutputType(args);1772  target = createTargetInfo(args);1773  depTracker = std::make_unique<DependencyTracker>(1774      args.getLastArgValue(OPT_dependency_info));1775 1776  config->ltoo = args::getInteger(args, OPT_lto_O, 2);1777  if (config->ltoo > 3)1778    error("--lto-O: invalid optimization level: " + Twine(config->ltoo));1779  unsigned ltoCgo =1780      args::getInteger(args, OPT_lto_CGO, args::getCGOptLevel(config->ltoo));1781  if (auto level = CodeGenOpt::getLevel(ltoCgo))1782    config->ltoCgo = *level;1783  else1784    error("--lto-CGO: invalid codegen optimization level: " + Twine(ltoCgo));1785 1786  if (errorCount())1787    return false;1788 1789  if (args.hasArg(OPT_pagezero_size)) {1790    uint64_t pagezeroSize = args::getHex(args, OPT_pagezero_size, 0);1791 1792    // ld64 does something really weird. It attempts to realign the value to the1793    // page size, but assumes the page size is 4K. This doesn't work with most1794    // of Apple's ARM64 devices, which use a page size of 16K. This means that1795    // it will first 4K align it by rounding down, then round up to 16K.  This1796    // probably only happened because no one using this arg with anything other1797    // then 0, so no one checked if it did what is what it says it does.1798 1799    // So we are not copying this weird behavior and doing the it in a logical1800    // way, by always rounding down to page size.1801    if (!isAligned(Align(target->getPageSize()), pagezeroSize)) {1802      pagezeroSize -= pagezeroSize % target->getPageSize();1803      warn("__PAGEZERO size is not page aligned, rounding down to 0x" +1804           Twine::utohexstr(pagezeroSize));1805    }1806 1807    target->pageZeroSize = pagezeroSize;1808  }1809 1810  config->osoPrefix = args.getLastArgValue(OPT_oso_prefix);1811  if (!config->osoPrefix.empty()) {1812    // The max path length is 4096, in theory. However that seems quite long1813    // and seems unlikely that any one would want to strip everything from the1814    // path. Hence we've picked a reasonably large number here.1815    SmallString<1024> expanded;1816    // Expand "." into the current working directory.1817    if (config->osoPrefix == "." && !fs::current_path(expanded)) {1818      // Note: LD64 expands "." to be `<current_dir>/1819      // (ie., it has a slash suffix) whereas current_path() doesn't.1820      // So we have to append '/' to be consistent because this is1821      // meaningful for our text based stripping.1822      expanded += sys::path::get_separator();1823    } else {1824      expanded = config->osoPrefix;1825    }1826    config->osoPrefix = saver().save(expanded.str());1827  }1828 1829  bool pie = args.hasFlag(OPT_pie, OPT_no_pie, true);1830  if (!supportsNoPie() && !pie) {1831    warn("-no_pie ignored for arm64");1832    pie = true;1833  }1834 1835  config->isPic = config->outputType == MH_DYLIB ||1836                  config->outputType == MH_BUNDLE ||1837                  (config->outputType == MH_EXECUTE && pie);1838 1839  // Must be set before any InputSections and Symbols are created.1840  config->deadStrip = args.hasArg(OPT_dead_strip);1841  config->interposable = args.hasArg(OPT_interposable);1842 1843  config->systemLibraryRoots = getSystemLibraryRoots(args);1844  if (const char *path = getReproduceOption(args)) {1845    // Note that --reproduce is a debug option so you can ignore it1846    // if you are trying to understand the whole picture of the code.1847    Expected<std::unique_ptr<TarWriter>> errOrWriter =1848        TarWriter::create(path, path::stem(path));1849    if (errOrWriter) {1850      tar = std::move(*errOrWriter);1851      tar->append("response.txt", createResponseFile(args));1852      tar->append("version.txt", getLLDVersion() + "\n");1853    } else {1854      error("--reproduce: " + toString(errOrWriter.takeError()));1855    }1856  }1857 1858  if (auto *arg = args.getLastArg(OPT_read_workers)) {1859#if LLVM_ENABLE_THREADS1860    StringRef v(arg->getValue());1861    unsigned workers = 0;1862    if (!llvm::to_integer(v, workers, 0))1863      error(arg->getSpelling() +1864            ": expected a non-negative integer, but got '" + arg->getValue() +1865            "'");1866    config->readWorkers = workers;1867#else1868    warn(arg->getSpelling() +1869         ": option unavailable because lld was not built with thread support");1870#endif1871  }1872  if (auto *arg = args.getLastArg(OPT_threads_eq)) {1873    StringRef v(arg->getValue());1874    unsigned threads = 0;1875    if (!llvm::to_integer(v, threads, 0) || threads == 0)1876      error(arg->getSpelling() + ": expected a positive integer, but got '" +1877            arg->getValue() + "'");1878    parallel::strategy = hardware_concurrency(threads);1879    config->thinLTOJobs = v;1880  }1881  if (auto *arg = args.getLastArg(OPT_thinlto_jobs_eq))1882    config->thinLTOJobs = arg->getValue();1883  if (!get_threadpool_strategy(config->thinLTOJobs))1884    error("--thinlto-jobs: invalid job count: " + config->thinLTOJobs);1885 1886  for (const Arg *arg : args.filtered(OPT_u)) {1887    config->explicitUndefineds.push_back(symtab->addUndefined(1888        arg->getValue(), /*file=*/nullptr, /*isWeakRef=*/false));1889  }1890 1891  for (const Arg *arg : args.filtered(OPT_U))1892    config->explicitDynamicLookups.insert(arg->getValue());1893 1894  config->mapFile = args.getLastArgValue(OPT_map);1895  config->optimize = args::getInteger(args, OPT_O, 1);1896  config->outputFile = args.getLastArgValue(OPT_o, "a.out");1897  config->finalOutput =1898      args.getLastArgValue(OPT_final_output, config->outputFile);1899  config->astPaths = args.getAllArgValues(OPT_add_ast_path);1900  config->headerPad = args::getHex(args, OPT_headerpad, /*Default=*/32);1901  config->headerPadMaxInstallNames =1902      args.hasArg(OPT_headerpad_max_install_names);1903  config->printDylibSearch =1904      args.hasArg(OPT_print_dylib_search) || getenv("RC_TRACE_DYLIB_SEARCHING");1905  config->printEachFile = args.hasArg(OPT_t);1906  config->printWhyLoad = args.hasArg(OPT_why_load);1907  config->omitDebugInfo = args.hasArg(OPT_S);1908  config->errorForArchMismatch = args.hasArg(OPT_arch_errors_fatal);1909  if (const Arg *arg = args.getLastArg(OPT_bundle_loader)) {1910    if (config->outputType != MH_BUNDLE)1911      error("-bundle_loader can only be used with MachO bundle output");1912    addFile(arg->getValue(), LoadType::CommandLine, /*isLazy=*/false,1913            /*isExplicit=*/false, /*isBundleLoader=*/true);1914  }1915  for (auto *arg : args.filtered(OPT_dyld_env)) {1916    StringRef envPair(arg->getValue());1917    if (!envPair.contains('='))1918      error("-dyld_env's argument is  malformed. Expected "1919            "-dyld_env <ENV_VAR>=<VALUE>, got `" +1920            envPair + "`");1921    config->dyldEnvs.push_back(envPair);1922  }1923  if (!config->dyldEnvs.empty() && config->outputType != MH_EXECUTE)1924    error("-dyld_env can only be used when creating executable output");1925 1926  if (const Arg *arg = args.getLastArg(OPT_umbrella)) {1927    if (config->outputType != MH_DYLIB)1928      warn("-umbrella used, but not creating dylib");1929    config->umbrella = arg->getValue();1930  }1931  config->ltoObjPath = args.getLastArgValue(OPT_object_path_lto);1932  config->ltoNewPmPasses = args.getLastArgValue(OPT_lto_newpm_passes);1933  config->thinLTOCacheDir = args.getLastArgValue(OPT_cache_path_lto);1934  config->thinLTOCachePolicy = getLTOCachePolicy(args);1935  config->thinLTOEmitImportsFiles = args.hasArg(OPT_thinlto_emit_imports_files);1936  config->thinLTOEmitIndexFiles = args.hasArg(OPT_thinlto_emit_index_files) ||1937                                  args.hasArg(OPT_thinlto_index_only) ||1938                                  args.hasArg(OPT_thinlto_index_only_eq);1939  config->thinLTOIndexOnly = args.hasArg(OPT_thinlto_index_only) ||1940                             args.hasArg(OPT_thinlto_index_only_eq);1941  config->thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_eq);1942  config->thinLTOObjectSuffixReplace =1943      getOldNewOptions(args, OPT_thinlto_object_suffix_replace_eq);1944  std::tie(config->thinLTOPrefixReplaceOld, config->thinLTOPrefixReplaceNew,1945           config->thinLTOPrefixReplaceNativeObject) =1946      getOldNewOptionsExtra(args, OPT_thinlto_prefix_replace_eq);1947  if (config->thinLTOEmitIndexFiles && !config->thinLTOIndexOnly) {1948    if (args.hasArg(OPT_thinlto_object_suffix_replace_eq))1949      error("--thinlto-object-suffix-replace is not supported with "1950            "--thinlto-emit-index-files");1951    else if (args.hasArg(OPT_thinlto_prefix_replace_eq))1952      error("--thinlto-prefix-replace is not supported with "1953            "--thinlto-emit-index-files");1954  }1955  if (!config->thinLTOPrefixReplaceNativeObject.empty() &&1956      config->thinLTOIndexOnlyArg.empty()) {1957    error("--thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with "1958          "--thinlto-index-only=");1959  }1960  config->warnDuplicateRpath =1961      args.hasFlag(OPT_warn_duplicate_rpath, OPT_no_warn_duplicate_rpath, true);1962  config->runtimePaths = getRuntimePaths(args);1963  config->allowableClients = getAllowableClients(args);1964  config->allLoad = args.hasFlag(OPT_all_load, OPT_noall_load, false);1965  config->archMultiple = args.hasArg(OPT_arch_multiple);1966  config->applicationExtension = args.hasFlag(1967      OPT_application_extension, OPT_no_application_extension, false);1968  config->exportDynamic = args.hasArg(OPT_export_dynamic);1969  config->forceLoadObjC = args.hasArg(OPT_ObjC);1970  config->forceLoadSwift = args.hasArg(OPT_force_load_swift_libs);1971  config->deadStripDylibs = args.hasArg(OPT_dead_strip_dylibs);1972  config->demangle = args.hasArg(OPT_demangle);1973  config->implicitDylibs = !args.hasArg(OPT_no_implicit_dylibs);1974  config->emitFunctionStarts =1975      args.hasFlag(OPT_function_starts, OPT_no_function_starts, true);1976  config->emitDataInCodeInfo =1977      args.hasFlag(OPT_data_in_code_info, OPT_no_data_in_code_info, true);1978  config->emitChainedFixups = shouldEmitChainedFixups(args);1979  config->emitInitOffsets =1980      config->emitChainedFixups || args.hasArg(OPT_init_offsets);1981  config->emitRelativeMethodLists = shouldEmitRelativeMethodLists(args);1982  config->icfLevel = getICFLevel(args);1983  config->keepICFStabs = args.hasArg(OPT_keep_icf_stabs);1984  config->dedupStrings =1985      args.hasFlag(OPT_deduplicate_strings, OPT_no_deduplicate_strings, true);1986  config->dedupSymbolStrings = !args.hasArg(OPT_no_deduplicate_symbol_strings);1987  config->deadStripDuplicates = args.hasArg(OPT_dead_strip_duplicates);1988  config->warnDylibInstallName = args.hasFlag(1989      OPT_warn_dylib_install_name, OPT_no_warn_dylib_install_name, false);1990  config->ignoreOptimizationHints = args.hasArg(OPT_ignore_optimization_hints);1991  config->callGraphProfileSort = args.hasFlag(1992      OPT_call_graph_profile_sort, OPT_no_call_graph_profile_sort, true);1993  config->printSymbolOrder = args.getLastArgValue(OPT_print_symbol_order_eq);1994  config->forceExactCpuSubtypeMatch =1995      getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH");1996  config->objcStubsMode = getObjCStubsMode(args);1997  config->ignoreAutoLink = args.hasArg(OPT_ignore_auto_link);1998  for (const Arg *arg : args.filtered(OPT_ignore_auto_link_option))1999    config->ignoreAutoLinkOptions.insert(arg->getValue());2000  config->strictAutoLink = args.hasArg(OPT_strict_auto_link);2001  config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);2002  config->codegenDataGeneratePath =2003      args.getLastArgValue(OPT_codegen_data_generate_path);2004  config->csProfileGenerate = args.hasArg(OPT_cs_profile_generate);2005  config->csProfilePath = args.getLastArgValue(OPT_cs_profile_path);2006  config->pgoWarnMismatch =2007      args.hasFlag(OPT_pgo_warn_mismatch, OPT_no_pgo_warn_mismatch, true);2008  config->warnThinArchiveMissingMembers =2009      args.hasFlag(OPT_warn_thin_archive_missing_members,2010                   OPT_no_warn_thin_archive_missing_members, true);2011  config->generateUuid = !args.hasArg(OPT_no_uuid);2012  config->disableVerify = args.hasArg(OPT_disable_verify);2013  config->separateCstringLiteralSections =2014      args.hasFlag(OPT_separate_cstring_literal_sections,2015                   OPT_no_separate_cstring_literal_sections, false);2016  config->tailMergeStrings =2017      args.hasFlag(OPT_tail_merge_strings, OPT_no_tail_merge_strings, false);2018 2019  auto IncompatWithCGSort = [&](StringRef firstArgStr) {2020    // Throw an error only if --call-graph-profile-sort is explicitly specified2021    if (config->callGraphProfileSort)2022      if (const Arg *arg = args.getLastArgNoClaim(OPT_call_graph_profile_sort))2023        error(firstArgStr + " is incompatible with " + arg->getSpelling());2024  };2025  if (args.hasArg(OPT_irpgo_profile_sort) ||2026      args.hasArg(OPT_irpgo_profile_sort_eq))2027    warn("--irpgo-profile-sort is deprecated. Please use "2028         "--bp-startup-sort=function");2029  if (const Arg *arg = args.getLastArg(OPT_irpgo_profile))2030    config->irpgoProfilePath = arg->getValue();2031 2032  if (const Arg *arg = args.getLastArg(OPT_irpgo_profile_sort)) {2033    config->irpgoProfilePath = arg->getValue();2034    config->bpStartupFunctionSort = true;2035    IncompatWithCGSort(arg->getSpelling());2036  }2037  config->bpCompressionSortStartupFunctions =2038      args.hasFlag(OPT_bp_compression_sort_startup_functions,2039                   OPT_no_bp_compression_sort_startup_functions, false);2040  if (const Arg *arg = args.getLastArg(OPT_bp_startup_sort)) {2041    StringRef startupSortStr = arg->getValue();2042    if (startupSortStr == "function") {2043      config->bpStartupFunctionSort = true;2044    } else if (startupSortStr != "none") {2045      error("unknown value `" + startupSortStr + "` for " + arg->getSpelling());2046    }2047    if (startupSortStr != "none")2048      IncompatWithCGSort(arg->getSpelling());2049  }2050  if (!config->bpStartupFunctionSort &&2051      config->bpCompressionSortStartupFunctions)2052    error("--bp-compression-sort-startup-functions must be used with "2053          "--bp-startup-sort=function");2054  if (config->irpgoProfilePath.empty() && config->bpStartupFunctionSort)2055    error("--bp-startup-sort=function must be used with "2056          "--irpgo-profile");2057  if (const Arg *arg = args.getLastArg(OPT_bp_compression_sort)) {2058    StringRef compressionSortStr = arg->getValue();2059    if (compressionSortStr == "function") {2060      config->bpFunctionOrderForCompression = true;2061    } else if (compressionSortStr == "data") {2062      config->bpDataOrderForCompression = true;2063    } else if (compressionSortStr == "both") {2064      config->bpFunctionOrderForCompression = true;2065      config->bpDataOrderForCompression = true;2066    } else if (compressionSortStr != "none") {2067      error("unknown value `" + compressionSortStr + "` for " +2068            arg->getSpelling());2069    }2070    if (compressionSortStr != "none")2071      IncompatWithCGSort(arg->getSpelling());2072  }2073  config->bpVerboseSectionOrderer = args.hasArg(OPT_verbose_bp_section_orderer);2074 2075  for (const Arg *arg : args.filtered(OPT_alias)) {2076    config->aliasedSymbols.push_back(2077        std::make_pair(arg->getValue(0), arg->getValue(1)));2078  }2079 2080  if (const char *zero = getenv("ZERO_AR_DATE"))2081    config->zeroModTime = strcmp(zero, "0") != 0;2082  if (args.getLastArg(OPT_reproducible))2083    config->zeroModTime = true;2084 2085  std::array<PlatformType, 4> encryptablePlatforms{2086      PLATFORM_IOS, PLATFORM_WATCHOS, PLATFORM_TVOS, PLATFORM_XROS};2087  config->emitEncryptionInfo =2088      args.hasFlag(OPT_encryptable, OPT_no_encryption,2089                   is_contained(encryptablePlatforms, config->platform()));2090 2091  if (const Arg *arg = args.getLastArg(OPT_install_name)) {2092    if (config->warnDylibInstallName && config->outputType != MH_DYLIB)2093      warn(2094          arg->getAsString(args) +2095          ": ignored, only has effect with -dylib [--warn-dylib-install-name]");2096    else2097      config->installName = arg->getValue();2098  } else if (config->outputType == MH_DYLIB) {2099    config->installName = config->finalOutput;2100  }2101 2102  auto getClientName = [&]() {2103    StringRef cn = path::filename(config->finalOutput);2104    cn.consume_front("lib");2105    auto firstDotOrUnderscore = cn.find_first_of("._");2106    cn = cn.take_front(firstDotOrUnderscore);2107    return cn;2108  };2109  config->clientName = args.getLastArgValue(OPT_client_name, getClientName());2110 2111  if (args.hasArg(OPT_mark_dead_strippable_dylib)) {2112    if (config->outputType != MH_DYLIB)2113      warn("-mark_dead_strippable_dylib: ignored, only has effect with -dylib");2114    else2115      config->markDeadStrippableDylib = true;2116  }2117 2118  if (const Arg *arg = args.getLastArg(OPT_static, OPT_dynamic))2119    config->staticLink = (arg->getOption().getID() == OPT_static);2120 2121  if (const Arg *arg =2122          args.getLastArg(OPT_flat_namespace, OPT_twolevel_namespace))2123    config->namespaceKind = arg->getOption().getID() == OPT_twolevel_namespace2124                                ? NamespaceKind::twolevel2125                                : NamespaceKind::flat;2126 2127  config->undefinedSymbolTreatment = getUndefinedSymbolTreatment(args);2128 2129  if (config->outputType == MH_EXECUTE)2130    config->entry = symtab->addUndefined(args.getLastArgValue(OPT_e, "_main"),2131                                         /*file=*/nullptr,2132                                         /*isWeakRef=*/false);2133 2134  config->librarySearchPaths =2135      getLibrarySearchPaths(args, config->systemLibraryRoots);2136  config->frameworkSearchPaths =2137      getFrameworkSearchPaths(args, config->systemLibraryRoots);2138  if (const Arg *arg =2139          args.getLastArg(OPT_search_paths_first, OPT_search_dylibs_first))2140    config->searchDylibsFirst =2141        arg->getOption().getID() == OPT_search_dylibs_first;2142 2143  config->dylibCompatibilityVersion =2144      parseDylibVersion(args, OPT_compatibility_version);2145  config->dylibCurrentVersion = parseDylibVersion(args, OPT_current_version);2146 2147  config->dataConst =2148      args.hasFlag(OPT_data_const, OPT_no_data_const, dataConstDefault(args));2149  // Populate config->sectionRenameMap with builtin default renames.2150  // Options -rename_section and -rename_segment are able to override.2151  initializeSectionRenameMap();2152  // Reject every special character except '.' and '$'2153  // TODO(gkm): verify that this is the proper set of invalid chars2154  StringRef invalidNameChars("!\"#%&'()*+,-/:;<=>?@[\\]^`{|}~");2155  auto validName = [invalidNameChars](StringRef s) {2156    if (s.find_first_of(invalidNameChars) != StringRef::npos)2157      error("invalid name for segment or section: " + s);2158    return s;2159  };2160  for (const Arg *arg : args.filtered(OPT_rename_section)) {2161    config->sectionRenameMap[{validName(arg->getValue(0)),2162                              validName(arg->getValue(1))}] = {2163        validName(arg->getValue(2)), validName(arg->getValue(3))};2164  }2165  for (const Arg *arg : args.filtered(OPT_rename_segment)) {2166    config->segmentRenameMap[validName(arg->getValue(0))] =2167        validName(arg->getValue(1));2168  }2169 2170  config->sectionAlignments = parseSectAlign(args);2171 2172  for (const Arg *arg : args.filtered(OPT_segprot)) {2173    StringRef segName = arg->getValue(0);2174    uint32_t maxProt = parseProtection(arg->getValue(1));2175    uint32_t initProt = parseProtection(arg->getValue(2));2176 2177    // FIXME: Check if this works on more platforms.2178    bool allowsDifferentInitAndMaxProt =2179        config->platform() == PLATFORM_MACOS ||2180        config->platform() == PLATFORM_MACCATALYST;2181    if (allowsDifferentInitAndMaxProt) {2182      if (initProt > maxProt)2183        error("invalid argument '" + arg->getAsString(args) +2184              "': init must not be more permissive than max");2185    } else {2186      if (maxProt != initProt && config->arch() != AK_i386)2187        error("invalid argument '" + arg->getAsString(args) +2188              "': max and init must be the same for non-macOS non-i386 archs");2189    }2190 2191    if (segName == segment_names::linkEdit)2192      error("-segprot cannot be used to change __LINKEDIT's protections");2193    config->segmentProtections.push_back({segName, maxProt, initProt});2194  }2195 2196  config->hasExplicitExports =2197      args.hasArg(OPT_no_exported_symbols) ||2198      args.hasArgNoClaim(OPT_exported_symbol, OPT_exported_symbols_list);2199  handleSymbolPatterns(args, config->exportedSymbols, OPT_exported_symbol,2200                       OPT_exported_symbols_list);2201  handleSymbolPatterns(args, config->unexportedSymbols, OPT_unexported_symbol,2202                       OPT_unexported_symbols_list);2203  if (config->hasExplicitExports && !config->unexportedSymbols.empty())2204    error("cannot use both -exported_symbol* and -unexported_symbol* options");2205 2206  if (args.hasArg(OPT_no_exported_symbols) && !config->exportedSymbols.empty())2207    error("cannot use both -exported_symbol* and -no_exported_symbols options");2208 2209  // Imitating LD64's:2210  // -non_global_symbols_no_strip_list and -non_global_symbols_strip_list can't2211  // both be present.2212  // But -x can be used with either of these two, in which case, the last arg2213  // takes effect.2214  // (TODO: This is kind of confusing - considering disallowing using them2215  // together for a more straightforward behaviour)2216  {2217    bool includeLocal = false;2218    bool excludeLocal = false;2219    for (const Arg *arg :2220         args.filtered(OPT_x, OPT_non_global_symbols_no_strip_list,2221                       OPT_non_global_symbols_strip_list)) {2222      switch (arg->getOption().getID()) {2223      case OPT_x:2224        config->localSymbolsPresence = SymtabPresence::None;2225        break;2226      case OPT_non_global_symbols_no_strip_list:2227        if (excludeLocal) {2228          error("cannot use both -non_global_symbols_no_strip_list and "2229                "-non_global_symbols_strip_list");2230        } else {2231          includeLocal = true;2232          config->localSymbolsPresence = SymtabPresence::SelectivelyIncluded;2233          parseSymbolPatternsFile(arg, config->localSymbolPatterns);2234        }2235        break;2236      case OPT_non_global_symbols_strip_list:2237        if (includeLocal) {2238          error("cannot use both -non_global_symbols_no_strip_list and "2239                "-non_global_symbols_strip_list");2240        } else {2241          excludeLocal = true;2242          config->localSymbolsPresence = SymtabPresence::SelectivelyExcluded;2243          parseSymbolPatternsFile(arg, config->localSymbolPatterns);2244        }2245        break;2246      default:2247        llvm_unreachable("unexpected option");2248      }2249    }2250  }2251  // Explicitly-exported literal symbols must be defined, but might2252  // languish in an archive if unreferenced elsewhere or if they are in the2253  // non-global strip list. Light a fire under those lazy symbols!2254  for (const CachedHashStringRef &cachedName : config->exportedSymbols.literals)2255    symtab->addUndefined(cachedName.val(), /*file=*/nullptr,2256                         /*isWeakRef=*/false);2257 2258  for (const Arg *arg : args.filtered(OPT_why_live))2259    config->whyLive.insert(arg->getValue());2260  if (!config->whyLive.empty() && !config->deadStrip)2261    warn("-why_live has no effect without -dead_strip, ignoring");2262 2263  config->saveTemps = args.hasArg(OPT_save_temps);2264 2265  config->adhocCodesign = args.hasFlag(2266      OPT_adhoc_codesign, OPT_no_adhoc_codesign,2267      shouldAdhocSignByDefault(config->arch(), config->platform()));2268 2269  if (args.hasArg(OPT_v)) {2270    message(getLLDVersion(), ctx->e.errs());2271    message(StringRef("Library search paths:") +2272                (config->librarySearchPaths.empty()2273                     ? ""2274                     : "\n\t" + join(config->librarySearchPaths, "\n\t")),2275            ctx->e.errs());2276    message(StringRef("Framework search paths:") +2277                (config->frameworkSearchPaths.empty()2278                     ? ""2279                     : "\n\t" + join(config->frameworkSearchPaths, "\n\t")),2280            ctx->e.errs());2281  }2282 2283  config->progName = argsArr[0];2284 2285  config->timeTraceEnabled = args.hasArg(OPT_time_trace_eq);2286  config->timeTraceGranularity =2287      args::getInteger(args, OPT_time_trace_granularity_eq, 500);2288 2289  // Initialize time trace profiler.2290  if (config->timeTraceEnabled)2291    timeTraceProfilerInitialize(config->timeTraceGranularity, config->progName);2292 2293  {2294    TimeTraceScope timeScope("ExecuteLinker");2295 2296    initLLVM(); // must be run before any call to addFile()2297    createFiles(args);2298 2299    // Now that all dylibs have been loaded, search for those that should be2300    // re-exported.2301    {2302      auto reexportHandler = [](const Arg *arg,2303                                const std::vector<StringRef> &extensions) {2304        config->hasReexports = true;2305        StringRef searchName = arg->getValue();2306        if (!markReexport(searchName, extensions))2307          error(arg->getSpelling() + " " + searchName +2308                " does not match a supplied dylib");2309      };2310      std::vector<StringRef> extensions = {".tbd"};2311      for (const Arg *arg : args.filtered(OPT_sub_umbrella))2312        reexportHandler(arg, extensions);2313 2314      extensions.push_back(".dylib");2315      for (const Arg *arg : args.filtered(OPT_sub_library))2316        reexportHandler(arg, extensions);2317    }2318 2319    cl::ResetAllOptionOccurrences();2320 2321    // Parse LTO options.2322    if (const Arg *arg = args.getLastArg(OPT_mcpu))2323      parseClangOption(saver().save("-mcpu=" + StringRef(arg->getValue())),2324                       arg->getSpelling());2325 2326    for (const Arg *arg : args.filtered(OPT_mllvm)) {2327      parseClangOption(arg->getValue(), arg->getSpelling());2328      config->mllvmOpts.emplace_back(arg->getValue());2329    }2330 2331    config->passPlugins = args::getStrings(args, OPT_load_pass_plugins);2332 2333    createSyntheticSections();2334    createSyntheticSymbols();2335    addSynthenticMethnames();2336 2337    createAliases();2338    // If we are in "explicit exports" mode, hide everything that isn't2339    // explicitly exported. Do this before running LTO so that LTO can better2340    // optimize.2341    handleExplicitExports();2342 2343    bool didCompileBitcodeFiles = compileBitcodeFiles();2344 2345    resolveLCLinkerOptions();2346 2347    // If --thinlto-index-only is given, we should create only "index2348    // files" and not object files. Index file creation is already done2349    // in compileBitcodeFiles, so we are done if that's the case.2350    if (config->thinLTOIndexOnly)2351      return errorCount() == 0;2352 2353    // LTO may emit a non-hidden (extern) object file symbol even if the2354    // corresponding bitcode symbol is hidden. In particular, this happens for2355    // cross-module references to hidden symbols under ThinLTO. Thus, if we2356    // compiled any bitcode files, we must redo the symbol hiding.2357    if (didCompileBitcodeFiles)2358      handleExplicitExports();2359    replaceCommonSymbols();2360 2361    StringRef orderFile = args.getLastArgValue(OPT_order_file);2362    if (!orderFile.empty())2363      priorityBuilder.parseOrderFile(orderFile);2364 2365    referenceStubBinder();2366 2367    // FIXME: should terminate the link early based on errors encountered so2368    // far?2369 2370    for (const Arg *arg : args.filtered(OPT_sectcreate)) {2371      StringRef segName = arg->getValue(0);2372      StringRef sectName = arg->getValue(1);2373      StringRef fileName = arg->getValue(2);2374      std::optional<MemoryBufferRef> buffer = readFile(fileName);2375      if (buffer)2376        inputFiles.insert(make<OpaqueFile>(*buffer, segName, sectName));2377    }2378 2379    for (const Arg *arg : args.filtered(OPT_add_empty_section)) {2380      StringRef segName = arg->getValue(0);2381      StringRef sectName = arg->getValue(1);2382      inputFiles.insert(make<OpaqueFile>(MemoryBufferRef(), segName, sectName));2383    }2384 2385    gatherInputSections();2386 2387    if (!config->codegenDataGeneratePath.empty())2388      codegenDataGenerate();2389 2390    if (config->callGraphProfileSort)2391      priorityBuilder.extractCallGraphProfile();2392 2393    if (config->deadStrip)2394      markLive();2395 2396    // Ensure that no symbols point inside __mod_init_func sections if they are2397    // removed due to -init_offsets. This must run after dead stripping.2398    if (config->emitInitOffsets)2399      eraseInitializerSymbols();2400 2401    // Categories are not subject to dead-strip. The __objc_catlist section is2402    // marked as NO_DEAD_STRIP and that propagates into all category data.2403    if (args.hasArg(OPT_check_category_conflicts))2404      objc::checkCategories();2405 2406    // Category merging uses "->live = false" to erase old category data, so2407    // it has to run after dead-stripping (markLive).2408    if (args.hasFlag(OPT_objc_category_merging, OPT_no_objc_category_merging,2409                     false))2410      objc::mergeCategories();2411 2412    // ICF assumes that all literals have been folded already, so we must run2413    // foldIdenticalLiterals before foldIdenticalSections.2414    foldIdenticalLiterals();2415    if (config->icfLevel != ICFLevel::none) {2416      if (config->icfLevel == ICFLevel::safe ||2417          config->icfLevel == ICFLevel::safe_thunks)2418        markAddrSigSymbols();2419      foldIdenticalSections(/*onlyCfStrings=*/false);2420    } else if (config->dedupStrings) {2421      foldIdenticalSections(/*onlyCfStrings=*/true);2422    }2423 2424    // Write to an output file.2425    if (target->wordSize == 8)2426      writeResult<LP64>();2427    else2428      writeResult<ILP32>();2429 2430    depTracker->write(getLLDVersion(), inputFiles, config->outputFile);2431  }2432 2433  if (config->timeTraceEnabled) {2434    checkError(timeTraceProfilerWrite(2435        args.getLastArgValue(OPT_time_trace_eq).str(), config->outputFile));2436 2437    timeTraceProfilerCleanup();2438  }2439 2440  if (errorCount() != 0 || config->strictAutoLink)2441    for (const auto &warning : missingAutolinkWarnings)2442      warn(warning);2443 2444  return errorCount() == 0;2445}2446} // namespace macho2447} // namespace lld2448