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 = [<oPolicy](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 §ion = *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