brintos

brintos / llvm-project-archived public Read only

0
0
Text · 100.4 KiB · 0e528de Raw
2870 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 "COFFLinkerContext.h"11#include "Config.h"12#include "DebugTypes.h"13#include "ICF.h"14#include "InputFiles.h"15#include "MarkLive.h"16#include "MinGW.h"17#include "SymbolTable.h"18#include "Symbols.h"19#include "Writer.h"20#include "lld/Common/Args.h"21#include "lld/Common/CommonLinkerContext.h"22#include "lld/Common/Filesystem.h"23#include "lld/Common/Timer.h"24#include "lld/Common/Version.h"25#include "llvm/ADT/IntrusiveRefCntPtr.h"26#include "llvm/ADT/StringSwitch.h"27#include "llvm/BinaryFormat/Magic.h"28#include "llvm/Config/llvm-config.h"29#include "llvm/LTO/LTO.h"30#include "llvm/Object/COFFImportFile.h"31#include "llvm/Option/Arg.h"32#include "llvm/Option/ArgList.h"33#include "llvm/Option/Option.h"34#include "llvm/Support/BinaryStreamReader.h"35#include "llvm/Support/CommandLine.h"36#include "llvm/Support/Debug.h"37#include "llvm/Support/LEB128.h"38#include "llvm/Support/MathExtras.h"39#include "llvm/Support/Parallel.h"40#include "llvm/Support/Path.h"41#include "llvm/Support/Process.h"42#include "llvm/Support/TarWriter.h"43#include "llvm/Support/TargetSelect.h"44#include "llvm/Support/TimeProfiler.h"45#include "llvm/Support/VirtualFileSystem.h"46#include "llvm/Support/raw_ostream.h"47#include "llvm/TargetParser/Triple.h"48#include "llvm/ToolDrivers/llvm-lib/LibDriver.h"49#include <algorithm>50#include <future>51#include <memory>52#include <optional>53#include <tuple>54 55using namespace lld;56using namespace lld::coff;57using namespace llvm;58using namespace llvm::object;59using namespace llvm::COFF;60using namespace llvm::sys;61 62COFFSyncStream::COFFSyncStream(COFFLinkerContext &ctx, DiagLevel level)63    : SyncStream(ctx.e, level), ctx(ctx) {}64 65COFFSyncStream coff::Log(COFFLinkerContext &ctx) {66  return {ctx, DiagLevel::Log};67}68COFFSyncStream coff::Msg(COFFLinkerContext &ctx) {69  return {ctx, DiagLevel::Msg};70}71COFFSyncStream coff::Warn(COFFLinkerContext &ctx) {72  return {ctx, DiagLevel::Warn};73}74COFFSyncStream coff::Err(COFFLinkerContext &ctx) {75  return {ctx, DiagLevel::Err};76}77COFFSyncStream coff::Fatal(COFFLinkerContext &ctx) {78  return {ctx, DiagLevel::Fatal};79}80uint64_t coff::errCount(COFFLinkerContext &ctx) { return ctx.e.errorCount; }81 82namespace lld::coff {83 84bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,85          llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {86  // This driver-specific context will be freed later by unsafeLldMain().87  auto *ctx = new COFFLinkerContext;88 89  ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);90  ctx->e.logName = args::getFilenameWithoutExe(args[0]);91  ctx->e.errorLimitExceededMsg = "too many errors emitted, stopping now"92                                 " (use /errorlimit:0 to see all errors)";93 94  ctx->driver.linkerMain(args);95 96  return errCount(*ctx) == 0;97}98 99// Parse options of the form "old;new".100static std::pair<StringRef, StringRef>101getOldNewOptions(COFFLinkerContext &ctx, opt::InputArgList &args, unsigned id) {102  auto *arg = args.getLastArg(id);103  if (!arg)104    return {"", ""};105 106  StringRef s = arg->getValue();107  std::pair<StringRef, StringRef> ret = s.split(';');108  if (ret.second.empty())109    Err(ctx) << arg->getSpelling() << " expects 'old;new' format, but got "110             << s;111  return ret;112}113 114// Parse options of the form "old;new[;extra]".115static std::tuple<StringRef, StringRef, StringRef>116getOldNewOptionsExtra(COFFLinkerContext &ctx, opt::InputArgList &args,117                      unsigned id) {118  auto [oldDir, second] = getOldNewOptions(ctx, args, id);119  auto [newDir, extraDir] = second.split(';');120  return {oldDir, newDir, extraDir};121}122 123// Drop directory components and replace extension with124// ".exe", ".dll" or ".sys".125static std::string getOutputPath(StringRef path, bool isDll, bool isDriver) {126  StringRef ext = ".exe";127  if (isDll)128    ext = ".dll";129  else if (isDriver)130    ext = ".sys";131 132  return (sys::path::stem(path) + ext).str();133}134 135// Returns true if S matches /crtend.?\.o$/.136static bool isCrtend(StringRef s) {137  if (!s.consume_back(".o"))138    return false;139  if (s.ends_with("crtend"))140    return true;141  return !s.empty() && s.drop_back().ends_with("crtend");142}143 144// ErrorOr is not default constructible, so it cannot be used as the type145// parameter of a future.146// FIXME: We could open the file in createFutureForFile and avoid needing to147// return an error here, but for the moment that would cost us a file descriptor148// (a limited resource on Windows) for the duration that the future is pending.149using MBErrPair = std::pair<std::unique_ptr<MemoryBuffer>, std::error_code>;150 151// Create a std::future that opens and maps a file using the best strategy for152// the host platform.153static std::future<MBErrPair> createFutureForFile(std::string path) {154#if _WIN64155  // On Windows, file I/O is relatively slow so it is best to do this156  // asynchronously.  But 32-bit has issues with potentially launching tons157  // of threads158  auto strategy = std::launch::async;159#else160  auto strategy = std::launch::deferred;161#endif162  return std::async(strategy, [=]() {163    auto mbOrErr = MemoryBuffer::getFile(path, /*IsText=*/false,164                                         /*RequiresNullTerminator=*/false);165    if (!mbOrErr)166      return MBErrPair{nullptr, mbOrErr.getError()};167    return MBErrPair{std::move(*mbOrErr), std::error_code()};168  });169}170 171llvm::Triple::ArchType LinkerDriver::getArch() {172  return getMachineArchType(ctx.config.machine);173}174 175std::vector<Chunk *> LinkerDriver::getChunks() const {176  std::vector<Chunk *> res;177  for (ObjFile *file : ctx.objFileInstances) {178    ArrayRef<Chunk *> v = file->getChunks();179    res.insert(res.end(), v.begin(), v.end());180  }181  return res;182}183 184static bool compatibleMachineType(COFFLinkerContext &ctx, MachineTypes mt) {185  if (mt == IMAGE_FILE_MACHINE_UNKNOWN)186    return true;187  switch (ctx.config.machine) {188  case ARM64:189    return mt == ARM64 || mt == ARM64X;190  case ARM64EC:191  case ARM64X:192    return isAnyArm64(mt) || mt == AMD64;193  case IMAGE_FILE_MACHINE_UNKNOWN:194    return true;195  default:196    return ctx.config.machine == mt;197  }198}199 200void LinkerDriver::addFile(InputFile *file) {201  Log(ctx) << "Reading " << toString(file);202  if (file->lazy) {203    if (auto *f = dyn_cast<BitcodeFile>(file))204      f->parseLazy();205    else206      cast<ObjFile>(file)->parseLazy();207  } else {208    ctx.consumedInputsSize += file->mb.getBufferSize();209    file->parse();210    if (auto *f = dyn_cast<ObjFile>(file)) {211      ctx.objFileInstances.push_back(f);212    } else if (auto *f = dyn_cast<BitcodeFile>(file)) {213      if (ltoCompilationDone) {214        Err(ctx) << "LTO object file " << toString(file)215                 << " linked in after "216                    "doing LTO compilation.";217      }218      f->symtab.bitcodeFileInstances.push_back(f);219    } else if (auto *f = dyn_cast<ImportFile>(file)) {220      ctx.importFileInstances.push_back(f);221    }222  }223 224  MachineTypes mt = file->getMachineType();225  // The ARM64EC target must be explicitly specified and cannot be inferred.226  if (mt == ARM64EC &&227      (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN ||228       (ctx.config.machineInferred &&229        (ctx.config.machine == ARM64 || ctx.config.machine == AMD64)))) {230    Err(ctx) << toString(file)231             << ": machine type arm64ec is ambiguous and cannot be "232                "inferred, use /machine:arm64ec or /machine:arm64x";233    return;234  }235  if (!compatibleMachineType(ctx, mt)) {236    Err(ctx) << toString(file) << ": machine type " << machineToStr(mt)237             << " conflicts with " << machineToStr(ctx.config.machine);238    return;239  }240  if (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN &&241      mt != IMAGE_FILE_MACHINE_UNKNOWN) {242    ctx.config.machineInferred = true;243    setMachine(mt);244  }245 246  parseDirectives(file);247}248 249MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> mb) {250  MemoryBufferRef mbref = *mb;251  make<std::unique_ptr<MemoryBuffer>>(std::move(mb)); // take ownership252 253  if (ctx.driver.tar)254    ctx.driver.tar->append(relativeToRoot(mbref.getBufferIdentifier()),255                           mbref.getBuffer());256  return mbref;257}258 259void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,260                             bool wholeArchive, bool lazy) {261  StringRef filename = mb->getBufferIdentifier();262 263  MemoryBufferRef mbref = takeBuffer(std::move(mb));264 265  // File type is detected by contents, not by file extension.266  switch (identify_magic(mbref.getBuffer())) {267  case file_magic::windows_resource:268    resources.push_back(mbref);269    break;270  case file_magic::archive:271    if (wholeArchive) {272      std::unique_ptr<Archive> file =273          CHECK(Archive::create(mbref), filename + ": failed to parse archive");274      Archive *archive = file.get();275      make<std::unique_ptr<Archive>>(std::move(file)); // take ownership276 277      int memberIndex = 0;278      for (MemoryBufferRef m : getArchiveMembers(ctx, archive)) {279        if (!archive->isThin())280          addArchiveBuffer(m, "<whole-archive>", filename, memberIndex++);281        else282          addThinArchiveBuffer(m, "<whole-archive>");283      }284 285      return;286    }287    addFile(make<ArchiveFile>(ctx, mbref));288    break;289  case file_magic::bitcode:290    addFile(BitcodeFile::create(ctx, mbref, "", 0, lazy));291    break;292  case file_magic::coff_object:293  case file_magic::coff_import_library:294    addFile(ObjFile::create(ctx, mbref, lazy));295    break;296  case file_magic::pdb:297    addFile(make<PDBInputFile>(ctx, mbref));298    break;299  case file_magic::coff_cl_gl_object:300    Err(ctx) << filename301             << ": is not a native COFF file. Recompile without /GL";302    break;303  case file_magic::pecoff_executable:304    if (ctx.config.mingw) {305      addFile(make<DLLFile>(ctx.symtab, mbref));306      break;307    }308    if (filename.ends_with_insensitive(".dll")) {309      Err(ctx) << filename310               << ": bad file type. Did you specify a DLL instead of an "311                  "import library?";312      break;313    }314    [[fallthrough]];315  default:316    Err(ctx) << mbref.getBufferIdentifier() << ": unknown file type";317    break;318  }319}320 321void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy) {322  auto future = std::make_shared<std::future<MBErrPair>>(323      createFutureForFile(std::string(path)));324  std::string pathStr = std::string(path);325  enqueueTask([=]() {326    llvm::TimeTraceScope timeScope("File: ", path);327    auto [mb, ec] = future->get();328    if (ec) {329      // Retry reading the file (synchronously) now that we may have added330      // winsysroot search paths from SymbolTable::addFile().331      // Retrying synchronously is important for keeping the order of inputs332      // consistent.333      // This makes it so that if the user passes something in the winsysroot334      // before something we can find with an architecture, we won't find the335      // winsysroot file.336      if (std::optional<StringRef> retryPath = findFileIfNew(pathStr)) {337        auto retryMb = MemoryBuffer::getFile(*retryPath, /*IsText=*/false,338                                             /*RequiresNullTerminator=*/false);339        ec = retryMb.getError();340        if (!ec)341          mb = std::move(*retryMb);342      } else {343        // We've already handled this file.344        return;345      }346    }347    if (ec) {348      std::string msg = "could not open '" + pathStr + "': " + ec.message();349      // Check if the filename is a typo for an option flag. OptTable thinks350      // that all args that are not known options and that start with / are351      // filenames, but e.g. `/nodefaultlibs` is more likely a typo for352      // the option `/nodefaultlib` than a reference to a file in the root353      // directory.354      std::string nearest;355      if (ctx.optTable.findNearest(pathStr, nearest) > 1)356        Err(ctx) << msg;357      else358        Err(ctx) << msg << "; did you mean '" << nearest << "'";359    } else360      ctx.driver.addBuffer(std::move(mb), wholeArchive, lazy);361  });362}363 364void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName,365                                    StringRef parentName,366                                    uint64_t offsetInArchive) {367  file_magic magic = identify_magic(mb.getBuffer());368  if (magic == file_magic::coff_import_library) {369    InputFile *imp = make<ImportFile>(ctx, mb);370    imp->parentName = parentName;371    addFile(imp);372    return;373  }374 375  InputFile *obj;376  if (magic == file_magic::coff_object) {377    obj = ObjFile::create(ctx, mb);378  } else if (magic == file_magic::bitcode) {379    obj = BitcodeFile::create(ctx, mb, parentName, offsetInArchive,380                              /*lazy=*/false);381  } else if (magic == file_magic::coff_cl_gl_object) {382    Err(ctx) << mb.getBufferIdentifier()383             << ": is not a native COFF file. Recompile without /GL?";384    return;385  } else {386    Err(ctx) << "unknown file type: " << mb.getBufferIdentifier();387    return;388  }389 390  obj->parentName = parentName;391  addFile(obj);392  Log(ctx) << "Loaded " << obj << " for " << symName;393}394 395void LinkerDriver::addThinArchiveBuffer(MemoryBufferRef mb, StringRef symName) {396  // Pass an empty string as the archive name and an offset of 0 so that397  // the original filename is used as the buffer identifier. This is398  // useful for DTLTO, where having the member identifier be the actual399  // path on disk enables distribution of bitcode files during ThinLTO.400  addArchiveBuffer(mb, symName, /*parentName=*/"", /*OffsetInArchive=*/0);401}402 403void LinkerDriver::enqueueArchiveMember(const Archive::Child &c,404                                        const Archive::Symbol &sym,405                                        StringRef parentName) {406 407  auto reportBufferError = [=](Error &&e) {408    StringRef childName =409      CHECK(c.getName(),410            "could not get child name for archive " + parentName +411            " while loading symbol " + toCOFFString(ctx, sym));412    Fatal(ctx) << "could not get the buffer for the member defining symbol "413               << &sym << ": " << parentName << "(" << childName414               << "): " << std::move(e);415  };416 417  if (!c.getParent()->isThin()) {418    uint64_t offsetInArchive = c.getChildOffset();419    Expected<MemoryBufferRef> mbOrErr = c.getMemoryBufferRef();420    if (!mbOrErr)421      reportBufferError(mbOrErr.takeError());422    MemoryBufferRef mb = mbOrErr.get();423    enqueueTask([=]() {424      llvm::TimeTraceScope timeScope("Archive: ", mb.getBufferIdentifier());425      ctx.driver.addArchiveBuffer(mb, toCOFFString(ctx, sym), parentName,426                                  offsetInArchive);427    });428    return;429  }430 431  std::string childName =432      CHECK(c.getFullName(),433            "could not get the filename for the member defining symbol " +434                toCOFFString(ctx, sym));435  auto future =436      std::make_shared<std::future<MBErrPair>>(createFutureForFile(childName));437  enqueueTask([=]() {438    auto mbOrErr = future->get();439    if (mbOrErr.second)440      reportBufferError(errorCodeToError(mbOrErr.second));441    llvm::TimeTraceScope timeScope("Archive: ",442                                   mbOrErr.first->getBufferIdentifier());443    ctx.driver.addThinArchiveBuffer(takeBuffer(std::move(mbOrErr.first)),444                                    toCOFFString(ctx, sym));445  });446}447 448bool LinkerDriver::isDecorated(StringRef sym) {449  return sym.starts_with("@") || sym.contains("@@") || sym.starts_with("?") ||450         (!ctx.config.mingw && sym.contains('@'));451}452 453// Parses .drectve section contents and returns a list of files454// specified by /defaultlib.455void LinkerDriver::parseDirectives(InputFile *file) {456  StringRef s = file->getDirectives();457  if (s.empty())458    return;459 460  Log(ctx) << "Directives: " << file << ": " << s;461 462  ArgParser parser(ctx);463  // .drectve is always tokenized using Windows shell rules.464  // /EXPORT: option can appear too many times, processing in fastpath.465  ParsedDirectives directives = parser.parseDirectives(s);466 467  for (StringRef e : directives.exports) {468    // If a common header file contains dllexported function469    // declarations, many object files may end up with having the470    // same /EXPORT options. In order to save cost of parsing them,471    // we dedup them first.472    if (!file->symtab.directivesExports.insert(e).second)473      continue;474 475    Export exp = parseExport(e);476    if (ctx.config.machine == I386 && ctx.config.mingw) {477      if (!isDecorated(exp.name))478        exp.name = saver().save("_" + exp.name);479      if (!exp.extName.empty() && !isDecorated(exp.extName))480        exp.extName = saver().save("_" + exp.extName);481    }482    exp.source = ExportSource::Directives;483    file->symtab.exports.push_back(exp);484  }485 486  // Handle /include: in bulk.487  for (StringRef inc : directives.includes)488    file->symtab.addGCRoot(inc);489 490  // Handle /exclude-symbols: in bulk.491  for (StringRef e : directives.excludes) {492    SmallVector<StringRef, 2> vec;493    e.split(vec, ',');494    for (StringRef sym : vec)495      excludedSymbols.insert(file->symtab.mangle(sym));496  }497 498  // https://docs.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=msvc-160499  for (auto *arg : directives.args) {500    switch (arg->getOption().getID()) {501    case OPT_aligncomm:502      file->symtab.parseAligncomm(arg->getValue());503      break;504    case OPT_alternatename:505      file->symtab.parseAlternateName(arg->getValue());506      break;507    case OPT_arm64xsameaddress:508      if (file->symtab.isEC())509        parseSameAddress(arg->getValue());510      else511        Warn(ctx) << arg->getSpelling()512                  << " is not allowed in non-ARM64EC files (" << toString(file)513                  << ")";514      break;515    case OPT_defaultlib:516      if (std::optional<StringRef> path = findLibIfNew(arg->getValue()))517        enqueuePath(*path, false, false);518      break;519    case OPT_entry:520      if (!arg->getValue()[0])521        Fatal(ctx) << "missing entry point symbol name";522      ctx.forEachActiveSymtab([&](SymbolTable &symtab) {523        symtab.entry = symtab.addGCRoot(symtab.mangle(arg->getValue()), true);524      });525      break;526    case OPT_failifmismatch:527      checkFailIfMismatch(arg->getValue(), file);528      break;529    case OPT_incl:530      file->symtab.addGCRoot(arg->getValue());531      break;532    case OPT_manifestdependency:533      ctx.config.manifestDependencies.insert(arg->getValue());534      break;535    case OPT_merge:536      parseMerge(arg->getValue());537      break;538    case OPT_nodefaultlib:539      ctx.config.noDefaultLibs.insert(findLib(arg->getValue()).lower());540      break;541    case OPT_release:542      ctx.config.writeCheckSum = true;543      break;544    case OPT_section:545      parseSection(arg->getValue());546      break;547    case OPT_stack:548      parseNumbers(arg->getValue(), &ctx.config.stackReserve,549                   &ctx.config.stackCommit);550      break;551    case OPT_subsystem: {552      bool gotVersion = false;553      parseSubsystem(arg->getValue(), &ctx.config.subsystem,554                     &ctx.config.majorSubsystemVersion,555                     &ctx.config.minorSubsystemVersion, &gotVersion);556      if (gotVersion) {557        ctx.config.majorOSVersion = ctx.config.majorSubsystemVersion;558        ctx.config.minorOSVersion = ctx.config.minorSubsystemVersion;559      }560      break;561    }562    // Only add flags here that link.exe accepts in563    // `#pragma comment(linker, "/flag")`-generated sections.564    case OPT_editandcontinue:565    case OPT_guardsym:566    case OPT_throwingnew:567    case OPT_inferasanlibs:568    case OPT_inferasanlibs_no:569      break;570    default:571      Err(ctx) << arg->getSpelling() << " is not allowed in .drectve ("572               << toString(file) << ")";573    }574  }575}576 577// Find file from search paths. You can omit ".obj", this function takes578// care of that. Note that the returned path is not guaranteed to exist.579StringRef LinkerDriver::findFile(StringRef filename) {580  auto getFilename = [this](StringRef filename) -> StringRef {581    if (ctx.config.vfs)582      if (auto statOrErr = ctx.config.vfs->status(filename))583        return saver().save(statOrErr->getName());584    return filename;585  };586 587  if (sys::path::is_absolute(filename))588    return getFilename(filename);589  bool hasExt = filename.contains('.');590  for (StringRef dir : searchPaths) {591    SmallString<128> path = dir;592    sys::path::append(path, filename);593    path = SmallString<128>{getFilename(path.str())};594    if (sys::fs::exists(path.str()))595      return saver().save(path.str());596    if (!hasExt) {597      path.append(".obj");598      path = SmallString<128>{getFilename(path.str())};599      if (sys::fs::exists(path.str()))600        return saver().save(path.str());601    }602  }603  return filename;604}605 606static std::optional<sys::fs::UniqueID> getUniqueID(StringRef path) {607  sys::fs::UniqueID ret;608  if (sys::fs::getUniqueID(path, ret))609    return std::nullopt;610  return ret;611}612 613// Resolves a file path. This never returns the same path614// (in that case, it returns std::nullopt).615std::optional<StringRef> LinkerDriver::findFileIfNew(StringRef filename) {616  StringRef path = findFile(filename);617 618  if (std::optional<sys::fs::UniqueID> id = getUniqueID(path)) {619    bool seen = !visitedFiles.insert(*id).second;620    if (seen)621      return std::nullopt;622  }623 624  if (path.ends_with_insensitive(".lib"))625    visitedLibs.insert(std::string(sys::path::filename(path).lower()));626  return path;627}628 629// MinGW specific. If an embedded directive specified to link to630// foo.lib, but it isn't found, try libfoo.a instead.631StringRef LinkerDriver::findLibMinGW(StringRef filename) {632  if (filename.contains('/') || filename.contains('\\'))633    return filename;634 635  SmallString<128> s = filename;636  sys::path::replace_extension(s, ".a");637  StringRef libName = saver().save("lib" + s.str());638  return findFile(libName);639}640 641// Find library file from search path.642StringRef LinkerDriver::findLib(StringRef filename) {643  // Add ".lib" to Filename if that has no file extension.644  bool hasExt = filename.contains('.');645  if (!hasExt)646    filename = saver().save(filename + ".lib");647  StringRef ret = findFile(filename);648  // For MinGW, if the find above didn't turn up anything, try649  // looking for a MinGW formatted library name.650  if (ctx.config.mingw && ret == filename)651    return findLibMinGW(filename);652  return ret;653}654 655// Resolves a library path. /nodefaultlib options are taken into656// consideration. This never returns the same path (in that case,657// it returns std::nullopt).658std::optional<StringRef> LinkerDriver::findLibIfNew(StringRef filename) {659  if (ctx.config.noDefaultLibAll)660    return std::nullopt;661  if (!visitedLibs.insert(filename.lower()).second)662    return std::nullopt;663 664  StringRef path = findLib(filename);665  if (ctx.config.noDefaultLibs.count(path.lower()))666    return std::nullopt;667 668  if (std::optional<sys::fs::UniqueID> id = getUniqueID(path))669    if (!visitedFiles.insert(*id).second)670      return std::nullopt;671  return path;672}673 674void LinkerDriver::setMachine(MachineTypes machine) {675  assert(ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN);676  assert(machine != IMAGE_FILE_MACHINE_UNKNOWN);677 678  ctx.config.machine = machine;679 680  if (!isArm64EC(machine)) {681    ctx.symtab.machine = machine;682  } else {683    // Set up a hybrid symbol table on ARM64EC/ARM64X. This is primarily useful684    // on ARM64X, where both the native and EC symbol tables are meaningful.685    // However, since ARM64EC can include native object files, we also need to686    // support a hybrid symbol table there.687    ctx.symtab.machine = ARM64EC;688    ctx.hybridSymtab.emplace(ctx, ARM64);689  }690 691  addWinSysRootLibSearchPaths();692}693 694void LinkerDriver::detectWinSysRoot(const opt::InputArgList &Args) {695  IntrusiveRefCntPtr<vfs::FileSystem> VFS = vfs::getRealFileSystem();696 697  // Check the command line first, that's the user explicitly telling us what to698  // use. Check the environment next, in case we're being invoked from a VS699  // command prompt. Failing that, just try to find the newest Visual Studio700  // version we can and use its default VC toolchain.701  std::optional<StringRef> VCToolsDir, VCToolsVersion, WinSysRoot;702  if (auto *A = Args.getLastArg(OPT_vctoolsdir))703    VCToolsDir = A->getValue();704  if (auto *A = Args.getLastArg(OPT_vctoolsversion))705    VCToolsVersion = A->getValue();706  if (auto *A = Args.getLastArg(OPT_winsysroot))707    WinSysRoot = A->getValue();708  if (!findVCToolChainViaCommandLine(*VFS, VCToolsDir, VCToolsVersion,709                                     WinSysRoot, vcToolChainPath, vsLayout) &&710      (Args.hasArg(OPT_lldignoreenv) ||711       !findVCToolChainViaEnvironment(*VFS, vcToolChainPath, vsLayout)) &&712      !findVCToolChainViaSetupConfig(*VFS, {}, vcToolChainPath, vsLayout) &&713      !findVCToolChainViaRegistry(vcToolChainPath, vsLayout))714    return;715 716  // If the VC environment hasn't been configured (perhaps because the user did717  // not run vcvarsall), try to build a consistent link environment.  If the718  // environment variable is set however, assume the user knows what they're719  // doing. If the user passes /vctoolsdir or /winsdkdir, trust that over env720  // vars.721  if (const auto *A = Args.getLastArg(OPT_diasdkdir, OPT_winsysroot)) {722    diaPath = A->getValue();723    if (A->getOption().getID() == OPT_winsysroot)724      path::append(diaPath, "DIA SDK");725  }726  useWinSysRootLibPath = !Process::GetEnv("LIB") ||727                         Args.hasArg(OPT_lldignoreenv, OPT_vctoolsdir,728                                     OPT_vctoolsversion, OPT_winsysroot);729  if (!Process::GetEnv("LIB") ||730      Args.hasArg(OPT_lldignoreenv, OPT_winsdkdir, OPT_winsdkversion,731                  OPT_winsysroot)) {732    std::optional<StringRef> WinSdkDir, WinSdkVersion;733    if (auto *A = Args.getLastArg(OPT_winsdkdir))734      WinSdkDir = A->getValue();735    if (auto *A = Args.getLastArg(OPT_winsdkversion))736      WinSdkVersion = A->getValue();737 738    if (useUniversalCRT(vsLayout, vcToolChainPath, getArch(), *VFS)) {739      std::string UniversalCRTSdkPath;740      std::string UCRTVersion;741      if (getUniversalCRTSdkDir(*VFS, WinSdkDir, WinSdkVersion, WinSysRoot,742                                UniversalCRTSdkPath, UCRTVersion)) {743        universalCRTLibPath = UniversalCRTSdkPath;744        path::append(universalCRTLibPath, "Lib", UCRTVersion, "ucrt");745      }746    }747 748    std::string sdkPath;749    std::string windowsSDKIncludeVersion;750    std::string windowsSDKLibVersion;751    if (getWindowsSDKDir(*VFS, WinSdkDir, WinSdkVersion, WinSysRoot, sdkPath,752                         sdkMajor, windowsSDKIncludeVersion,753                         windowsSDKLibVersion)) {754      windowsSdkLibPath = sdkPath;755      path::append(windowsSdkLibPath, "Lib");756      if (sdkMajor >= 8)757        path::append(windowsSdkLibPath, windowsSDKLibVersion, "um");758    }759  }760}761 762void LinkerDriver::addClangLibSearchPaths(const std::string &argv0) {763  std::string lldBinary = sys::fs::getMainExecutable(argv0.c_str(), nullptr);764  SmallString<128> binDir(lldBinary);765  sys::path::remove_filename(binDir);                 // remove lld-link.exe766  StringRef rootDir = sys::path::parent_path(binDir); // remove 'bin'767 768  SmallString<128> libDir(rootDir);769  sys::path::append(libDir, "lib");770 771  // Add the resource dir library path772  SmallString<128> runtimeLibDir(rootDir);773  sys::path::append(runtimeLibDir, "lib", "clang",774                    std::to_string(LLVM_VERSION_MAJOR), "lib");775  // Resource dir + osname, which is hardcoded to windows since we are in the776  // COFF driver.777  SmallString<128> runtimeLibDirWithOS(runtimeLibDir);778  sys::path::append(runtimeLibDirWithOS, "windows");779 780  searchPaths.push_back(saver().save(runtimeLibDirWithOS.str()));781  searchPaths.push_back(saver().save(runtimeLibDir.str()));782  searchPaths.push_back(saver().save(libDir.str()));783}784 785void LinkerDriver::addWinSysRootLibSearchPaths() {786  if (!diaPath.empty()) {787    // The DIA SDK always uses the legacy vc arch, even in new MSVC versions.788    path::append(diaPath, "lib", archToLegacyVCArch(getArch()));789    searchPaths.push_back(saver().save(diaPath.str()));790  }791  if (useWinSysRootLibPath) {792    searchPaths.push_back(saver().save(getSubDirectoryPath(793        SubDirectoryType::Lib, vsLayout, vcToolChainPath, getArch())));794    searchPaths.push_back(saver().save(795        getSubDirectoryPath(SubDirectoryType::Lib, vsLayout, vcToolChainPath,796                            getArch(), "atlmfc")));797  }798  if (!universalCRTLibPath.empty()) {799    StringRef ArchName = archToWindowsSDKArch(getArch());800    if (!ArchName.empty()) {801      path::append(universalCRTLibPath, ArchName);802      searchPaths.push_back(saver().save(universalCRTLibPath.str()));803    }804  }805  if (!windowsSdkLibPath.empty()) {806    std::string path;807    if (appendArchToWindowsSDKLibPath(sdkMajor, windowsSdkLibPath, getArch(),808                                      path))809      searchPaths.push_back(saver().save(path));810  }811 812  // Libraries specified by `/nodefaultlib:` may not be found in incomplete813  // search paths before lld infers a machine type from input files.814  std::set<std::string> noDefaultLibs;815  for (const std::string &path : ctx.config.noDefaultLibs)816    noDefaultLibs.insert(findLib(path).lower());817  ctx.config.noDefaultLibs = noDefaultLibs;818}819 820// Parses LIB environment which contains a list of search paths.821void LinkerDriver::addLibSearchPaths() {822  std::optional<std::string> envOpt = Process::GetEnv("LIB");823  if (!envOpt)824    return;825  StringRef env = saver().save(*envOpt);826  while (!env.empty()) {827    StringRef path;828    std::tie(path, env) = env.split(';');829    searchPaths.push_back(path);830  }831}832 833uint64_t LinkerDriver::getDefaultImageBase() {834  if (ctx.config.is64())835    return ctx.config.dll ? 0x180000000 : 0x140000000;836  return ctx.config.dll ? 0x10000000 : 0x400000;837}838 839static std::string rewritePath(StringRef s) {840  if (fs::exists(s))841    return relativeToRoot(s);842  return std::string(s);843}844 845// Reconstructs command line arguments so that so that you can re-run846// the same command with the same inputs. This is for --reproduce.847static std::string createResponseFile(const opt::InputArgList &args,848                                      ArrayRef<StringRef> searchPaths) {849  SmallString<0> data;850  raw_svector_ostream os(data);851 852  for (auto *arg : args) {853    switch (arg->getOption().getID()) {854    case OPT_linkrepro:855    case OPT_reproduce:856    case OPT_libpath:857    case OPT_winsysroot:858      break;859    case OPT_INPUT:860      os << quote(rewritePath(arg->getValue())) << "\n";861      break;862    case OPT_wholearchive_file:863      os << arg->getSpelling() << quote(rewritePath(arg->getValue())) << "\n";864      break;865    case OPT_call_graph_ordering_file:866    case OPT_deffile:867    case OPT_manifestinput:868    case OPT_natvis:869      os << arg->getSpelling() << quote(rewritePath(arg->getValue())) << '\n';870      break;871    case OPT_order: {872      StringRef orderFile = arg->getValue();873      orderFile.consume_front("@");874      os << arg->getSpelling() << '@' << quote(rewritePath(orderFile)) << '\n';875      break;876    }877    case OPT_pdbstream: {878      const std::pair<StringRef, StringRef> nameFile =879          StringRef(arg->getValue()).split("=");880      os << arg->getSpelling() << nameFile.first << '='881         << quote(rewritePath(nameFile.second)) << '\n';882      break;883    }884    case OPT_implib:885    case OPT_manifestfile:886    case OPT_pdb:887    case OPT_pdbstripped:888    case OPT_out:889      os << arg->getSpelling() << sys::path::filename(arg->getValue()) << "\n";890      break;891    default:892      os << toString(*arg) << "\n";893    }894  }895 896  for (StringRef path : searchPaths) {897    std::string relPath = relativeToRoot(path);898    os << "/libpath:" << quote(relPath) << "\n";899  }900 901  return std::string(data);902}903 904static unsigned parseDebugTypes(COFFLinkerContext &ctx,905                                const opt::InputArgList &args) {906  unsigned debugTypes = static_cast<unsigned>(DebugType::None);907 908  if (auto *a = args.getLastArg(OPT_debugtype)) {909    SmallVector<StringRef, 3> types;910    StringRef(a->getValue())911        .split(types, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);912 913    for (StringRef type : types) {914      unsigned v = StringSwitch<unsigned>(type.lower())915                       .Case("cv", static_cast<unsigned>(DebugType::CV))916                       .Case("pdata", static_cast<unsigned>(DebugType::PData))917                       .Case("fixup", static_cast<unsigned>(DebugType::Fixup))918                       .Default(0);919      if (v == 0) {920        Warn(ctx) << "/debugtype: unknown option '" << type << "'";921        continue;922      }923      debugTypes |= v;924    }925    return debugTypes;926  }927 928  // Default debug types929  debugTypes = static_cast<unsigned>(DebugType::CV);930  if (args.hasArg(OPT_driver))931    debugTypes |= static_cast<unsigned>(DebugType::PData);932  if (args.hasArg(OPT_profile))933    debugTypes |= static_cast<unsigned>(DebugType::Fixup);934 935  return debugTypes;936}937 938std::string LinkerDriver::getMapFile(const opt::InputArgList &args,939                                     opt::OptSpecifier os,940                                     opt::OptSpecifier osFile) {941  auto *arg = args.getLastArg(os, osFile);942  if (!arg)943    return "";944  if (arg->getOption().getID() == osFile.getID())945    return arg->getValue();946 947  assert(arg->getOption().getID() == os.getID());948  StringRef outFile = ctx.config.outputFile;949  return (outFile.substr(0, outFile.rfind('.')) + ".map").str();950}951 952std::string LinkerDriver::getImplibPath() {953  if (!ctx.config.implib.empty())954    return std::string(ctx.config.implib);955  SmallString<128> out = StringRef(ctx.config.outputFile);956  sys::path::replace_extension(out, ".lib");957  return std::string(out);958}959 960// The import name is calculated as follows:961//962//        | LIBRARY w/ ext |   LIBRARY w/o ext   | no LIBRARY963//   -----+----------------+---------------------+------------------964//   LINK | {value}        | {value}.{.dll/.exe} | {output name}965//    LIB | {value}        | {value}.dll         | {output name}.dll966//967std::string LinkerDriver::getImportName(bool asLib) {968  SmallString<128> out;969 970  if (ctx.config.importName.empty()) {971    out.assign(sys::path::filename(ctx.config.outputFile));972    if (asLib)973      sys::path::replace_extension(out, ".dll");974  } else {975    out.assign(ctx.config.importName);976    if (!sys::path::has_extension(out))977      sys::path::replace_extension(out,978                                   (ctx.config.dll || asLib) ? ".dll" : ".exe");979  }980 981  return std::string(out);982}983 984void LinkerDriver::createImportLibrary(bool asLib) {985  llvm::TimeTraceScope timeScope("Create import library");986  std::vector<COFFShortExport> exports, nativeExports;987 988  auto getExports = [](SymbolTable &symtab,989                       std::vector<COFFShortExport> &exports) {990    for (Export &e1 : symtab.exports) {991      COFFShortExport e2;992      e2.Name = std::string(e1.name);993      e2.SymbolName = std::string(e1.symbolName);994      e2.ExtName = std::string(e1.extName);995      e2.ExportAs = std::string(e1.exportAs);996      e2.ImportName = std::string(e1.importName);997      e2.Ordinal = e1.ordinal;998      e2.Noname = e1.noname;999      e2.Data = e1.data;1000      e2.Private = e1.isPrivate;1001      e2.Constant = e1.constant;1002      exports.push_back(e2);1003    }1004  };1005 1006  getExports(ctx.symtab, exports);1007  if (ctx.config.machine == ARM64X)1008    getExports(*ctx.hybridSymtab, nativeExports);1009 1010  std::string libName = getImportName(asLib);1011  std::string path = getImplibPath();1012 1013  if (!ctx.config.incremental) {1014    checkError(writeImportLibrary(libName, path, exports, ctx.config.machine,1015                                  ctx.config.mingw, nativeExports));1016    return;1017  }1018 1019  // If the import library already exists, replace it only if the contents1020  // have changed.1021  ErrorOr<std::unique_ptr<MemoryBuffer>> oldBuf = MemoryBuffer::getFile(1022      path, /*IsText=*/false, /*RequiresNullTerminator=*/false);1023  if (!oldBuf) {1024    checkError(writeImportLibrary(libName, path, exports, ctx.config.machine,1025                                  ctx.config.mingw, nativeExports));1026    return;1027  }1028 1029  SmallString<128> tmpName;1030  if (std::error_code ec =1031          sys::fs::createUniqueFile(path + ".tmp-%%%%%%%%.lib", tmpName))1032    Fatal(ctx) << "cannot create temporary file for import library " << path1033               << ": " << ec.message();1034 1035  if (Error e =1036          writeImportLibrary(libName, tmpName, exports, ctx.config.machine,1037                             ctx.config.mingw, nativeExports)) {1038    checkError(std::move(e));1039    return;1040  }1041 1042  std::unique_ptr<MemoryBuffer> newBuf = check(MemoryBuffer::getFile(1043      tmpName, /*IsText=*/false, /*RequiresNullTerminator=*/false));1044  if ((*oldBuf)->getBuffer() != newBuf->getBuffer()) {1045    oldBuf->reset();1046    checkError(errorCodeToError(sys::fs::rename(tmpName, path)));1047  } else {1048    sys::fs::remove(tmpName);1049  }1050}1051 1052void LinkerDriver::enqueueTask(std::function<void()> task) {1053  taskQueue.push_back(std::move(task));1054}1055 1056bool LinkerDriver::run() {1057  llvm::TimeTraceScope timeScope("Read input files");1058  ScopedTimer t(ctx.inputFileTimer);1059 1060  bool didWork = !taskQueue.empty();1061  while (!taskQueue.empty()) {1062    taskQueue.front()();1063    taskQueue.pop_front();1064  }1065  return didWork;1066}1067 1068// Parse an /order file. If an option is given, the linker places1069// COMDAT sections in the same order as their names appear in the1070// given file.1071void LinkerDriver::parseOrderFile(StringRef arg) {1072  // For some reason, the MSVC linker requires a filename to be1073  // preceded by "@".1074  if (!arg.starts_with("@")) {1075    Err(ctx) << "malformed /order option: '@' missing";1076    return;1077  }1078 1079  // Get a list of all comdat sections for error checking.1080  DenseSet<StringRef> set;1081  for (Chunk *c : ctx.driver.getChunks())1082    if (auto *sec = dyn_cast<SectionChunk>(c))1083      if (sec->sym)1084        set.insert(sec->sym->getName());1085 1086  // Open a file.1087  StringRef path = arg.substr(1);1088  std::unique_ptr<MemoryBuffer> mb =1089      CHECK(MemoryBuffer::getFile(path, /*IsText=*/false,1090                                  /*RequiresNullTerminator=*/false,1091                                  /*IsVolatile=*/true),1092            "could not open " + path);1093 1094  // Parse a file. An order file contains one symbol per line.1095  // All symbols that were not present in a given order file are1096  // considered to have the lowest priority 0 and are placed at1097  // end of an output section.1098  for (StringRef arg : args::getLines(mb->getMemBufferRef())) {1099    std::string s(arg);1100    if (ctx.config.machine == I386 && !isDecorated(s))1101      s = "_" + s;1102 1103    if (set.count(s) == 0) {1104      if (ctx.config.warnMissingOrderSymbol)1105        Warn(ctx) << "/order:" << arg << ": missing symbol: " << s1106                  << " [LNK4037]";1107    } else1108      ctx.config.order[s] = INT_MIN + ctx.config.order.size();1109  }1110 1111  // Include in /reproduce: output if applicable.1112  ctx.driver.takeBuffer(std::move(mb));1113}1114 1115void LinkerDriver::parseCallGraphFile(StringRef path) {1116  std::unique_ptr<MemoryBuffer> mb =1117      CHECK(MemoryBuffer::getFile(path, /*IsText=*/false,1118                                  /*RequiresNullTerminator=*/false,1119                                  /*IsVolatile=*/true),1120            "could not open " + path);1121 1122  // Build a map from symbol name to section.1123  DenseMap<StringRef, Symbol *> map;1124  for (ObjFile *file : ctx.objFileInstances)1125    for (Symbol *sym : file->getSymbols())1126      if (sym)1127        map[sym->getName()] = sym;1128 1129  auto findSection = [&](StringRef name) -> SectionChunk * {1130    Symbol *sym = map.lookup(name);1131    if (!sym) {1132      if (ctx.config.warnMissingOrderSymbol)1133        Warn(ctx) << path << ": no such symbol: " << name;1134      return nullptr;1135    }1136 1137    if (DefinedCOFF *dr = dyn_cast_or_null<DefinedCOFF>(sym))1138      return dyn_cast_or_null<SectionChunk>(dr->getChunk());1139    return nullptr;1140  };1141 1142  for (StringRef line : args::getLines(*mb)) {1143    SmallVector<StringRef, 3> fields;1144    line.split(fields, ' ');1145    uint64_t count;1146 1147    if (fields.size() != 3 || !to_integer(fields[2], count)) {1148      Err(ctx) << path << ": parse error";1149      return;1150    }1151 1152    if (SectionChunk *from = findSection(fields[0]))1153      if (SectionChunk *to = findSection(fields[1]))1154        ctx.config.callGraphProfile[{from, to}] += count;1155  }1156 1157  // Include in /reproduce: output if applicable.1158  ctx.driver.takeBuffer(std::move(mb));1159}1160 1161static void readCallGraphsFromObjectFiles(COFFLinkerContext &ctx) {1162  for (ObjFile *obj : ctx.objFileInstances) {1163    if (obj->callgraphSec) {1164      ArrayRef<uint8_t> contents;1165      cantFail(1166          obj->getCOFFObj()->getSectionContents(obj->callgraphSec, contents));1167      BinaryStreamReader reader(contents, llvm::endianness::little);1168      while (!reader.empty()) {1169        uint32_t fromIndex, toIndex;1170        uint64_t count;1171        if (Error err = reader.readInteger(fromIndex))1172          Fatal(ctx) << toString(obj) << ": Expected 32-bit integer";1173        if (Error err = reader.readInteger(toIndex))1174          Fatal(ctx) << toString(obj) << ": Expected 32-bit integer";1175        if (Error err = reader.readInteger(count))1176          Fatal(ctx) << toString(obj) << ": Expected 64-bit integer";1177        auto *fromSym = dyn_cast_or_null<Defined>(obj->getSymbol(fromIndex));1178        auto *toSym = dyn_cast_or_null<Defined>(obj->getSymbol(toIndex));1179        if (!fromSym || !toSym)1180          continue;1181        auto *from = dyn_cast_or_null<SectionChunk>(fromSym->getChunk());1182        auto *to = dyn_cast_or_null<SectionChunk>(toSym->getChunk());1183        if (from && to)1184          ctx.config.callGraphProfile[{from, to}] += count;1185      }1186    }1187  }1188}1189 1190static void markAddrsig(Symbol *s) {1191  if (auto *d = dyn_cast_or_null<Defined>(s))1192    if (SectionChunk *c = dyn_cast_or_null<SectionChunk>(d->getChunk()))1193      c->keepUnique = true;1194}1195 1196static void findKeepUniqueSections(COFFLinkerContext &ctx) {1197  llvm::TimeTraceScope timeScope("Find keep unique sections");1198 1199  // Exported symbols could be address-significant in other executables or DSOs,1200  // so we conservatively mark them as address-significant.1201  ctx.forEachSymtab([](SymbolTable &symtab) {1202    for (Export &r : symtab.exports)1203      markAddrsig(r.sym);1204  });1205 1206  // Visit the address-significance table in each object file and mark each1207  // referenced symbol as address-significant.1208  for (ObjFile *obj : ctx.objFileInstances) {1209    ArrayRef<Symbol *> syms = obj->getSymbols();1210    if (obj->addrsigSec) {1211      ArrayRef<uint8_t> contents;1212      cantFail(1213          obj->getCOFFObj()->getSectionContents(obj->addrsigSec, contents));1214      const uint8_t *cur = contents.begin();1215      while (cur != contents.end()) {1216        unsigned size;1217        const char *err = nullptr;1218        uint64_t symIndex = decodeULEB128(cur, &size, contents.end(), &err);1219        if (err)1220          Fatal(ctx) << toString(obj)1221                     << ": could not decode addrsig section: " << err;1222        if (symIndex >= syms.size())1223          Fatal(ctx) << toString(obj)1224                     << ": invalid symbol index in addrsig section";1225        markAddrsig(syms[symIndex]);1226        cur += size;1227      }1228    } else {1229      // If an object file does not have an address-significance table,1230      // conservatively mark all of its symbols as address-significant.1231      for (Symbol *s : syms)1232        markAddrsig(s);1233    }1234  }1235}1236 1237// link.exe replaces each %foo% in altPath with the contents of environment1238// variable foo, and adds the two magic env vars _PDB (expands to the basename1239// of pdb's output path) and _EXT (expands to the extension of the output1240// binary).1241// lld only supports %_PDB% and %_EXT% and warns on references to all other env1242// vars.1243void LinkerDriver::parsePDBAltPath() {1244  SmallString<128> buf;1245  StringRef pdbBasename =1246      sys::path::filename(ctx.config.pdbPath, sys::path::Style::windows);1247  StringRef binaryExtension =1248      sys::path::extension(ctx.config.outputFile, sys::path::Style::windows);1249  if (!binaryExtension.empty())1250    binaryExtension = binaryExtension.substr(1); // %_EXT% does not include '.'.1251 1252  // Invariant:1253  //   +--------- cursor ('a...' might be the empty string).1254  //   |   +----- firstMark1255  //   |   |   +- secondMark1256  //   v   v   v1257  //   a...%...%...1258  size_t cursor = 0;1259  while (cursor < ctx.config.pdbAltPath.size()) {1260    size_t firstMark, secondMark;1261    if ((firstMark = ctx.config.pdbAltPath.find('%', cursor)) ==1262            StringRef::npos ||1263        (secondMark = ctx.config.pdbAltPath.find('%', firstMark + 1)) ==1264            StringRef::npos) {1265      // Didn't find another full fragment, treat rest of string as literal.1266      buf.append(ctx.config.pdbAltPath.substr(cursor));1267      break;1268    }1269 1270    // Found a full fragment. Append text in front of first %, and interpret1271    // text between first and second % as variable name.1272    buf.append(ctx.config.pdbAltPath.substr(cursor, firstMark - cursor));1273    StringRef var =1274        ctx.config.pdbAltPath.substr(firstMark, secondMark - firstMark + 1);1275    if (var.equals_insensitive("%_pdb%"))1276      buf.append(pdbBasename);1277    else if (var.equals_insensitive("%_ext%"))1278      buf.append(binaryExtension);1279    else {1280      Warn(ctx) << "only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping "1281                << var << " as literal";1282      buf.append(var);1283    }1284 1285    cursor = secondMark + 1;1286  }1287 1288  ctx.config.pdbAltPath = buf;1289}1290 1291/// Convert resource files and potentially merge input resource object1292/// trees into one resource tree.1293/// Call after ObjFile::Instances is complete.1294void LinkerDriver::convertResources() {1295  llvm::TimeTraceScope timeScope("Convert resources");1296  std::vector<ObjFile *> resourceObjFiles;1297 1298  for (ObjFile *f : ctx.objFileInstances) {1299    if (f->isResourceObjFile())1300      resourceObjFiles.push_back(f);1301  }1302 1303  if (!ctx.config.mingw &&1304      (resourceObjFiles.size() > 1 ||1305       (resourceObjFiles.size() == 1 && !resources.empty()))) {1306    Err(ctx) << (!resources.empty()1307                     ? "internal .obj file created from .res files"1308                     : toString(resourceObjFiles[1]))1309             << ": more than one resource obj file not allowed, already got "1310             << resourceObjFiles.front();1311    return;1312  }1313 1314  if (resources.empty() && resourceObjFiles.size() <= 1) {1315    // No resources to convert, and max one resource object file in1316    // the input. Keep that preconverted resource section as is.1317    for (ObjFile *f : resourceObjFiles)1318      f->includeResourceChunks();1319    return;1320  }1321  ObjFile *f =1322      ObjFile::create(ctx, convertResToCOFF(resources, resourceObjFiles));1323  addFile(f);1324  f->includeResourceChunks();1325}1326 1327void LinkerDriver::maybeCreateECExportThunk(StringRef name, Symbol *&sym) {1328  if (!sym)1329    return;1330  Defined *def = sym->getDefined();1331  if (!def)1332    return;1333 1334  if (def->getChunk()->getArm64ECRangeType() != chpe_range_type::Arm64EC)1335    return;1336  StringRef expName;1337  if (auto mangledName = getArm64ECMangledFunctionName(name))1338    expName = saver().save("EXP+" + *mangledName);1339  else1340    expName = saver().save("EXP+" + name);1341  sym = ctx.symtab.addGCRoot(expName);1342  if (auto undef = dyn_cast<Undefined>(sym)) {1343    if (!undef->getWeakAlias()) {1344      auto thunk = make<ECExportThunkChunk>(def);1345      replaceSymbol<DefinedSynthetic>(undef, undef->getName(), thunk);1346    }1347  }1348}1349 1350void LinkerDriver::createECExportThunks() {1351  // Check if EXP+ symbols have corresponding $hp_target symbols and use them1352  // to create export thunks when available.1353  for (Symbol *s : ctx.symtab.expSymbols) {1354    if (!s->isUsedInRegularObj)1355      continue;1356    assert(s->getName().starts_with("EXP+"));1357    std::string targetName =1358        (s->getName().substr(strlen("EXP+")) + "$hp_target").str();1359    Symbol *sym = ctx.symtab.find(targetName);1360    if (!sym)1361      continue;1362    Defined *targetSym = sym->getDefined();1363    if (!targetSym)1364      continue;1365 1366    auto *undef = dyn_cast<Undefined>(s);1367    if (undef && !undef->getWeakAlias()) {1368      auto thunk = make<ECExportThunkChunk>(targetSym);1369      replaceSymbol<DefinedSynthetic>(undef, undef->getName(), thunk);1370    }1371    if (!targetSym->isGCRoot) {1372      targetSym->isGCRoot = true;1373      ctx.config.gcroot.push_back(targetSym);1374    }1375  }1376 1377  if (ctx.symtab.entry)1378    maybeCreateECExportThunk(ctx.symtab.entry->getName(), ctx.symtab.entry);1379  for (Export &e : ctx.symtab.exports) {1380    if (!e.data)1381      maybeCreateECExportThunk(e.extName.empty() ? e.name : e.extName, e.sym);1382  }1383}1384 1385void LinkerDriver::pullArm64ECIcallHelper() {1386  if (!ctx.config.arm64ECIcallHelper)1387    ctx.config.arm64ECIcallHelper =1388        ctx.symtab.addGCRoot("__icall_helper_arm64ec");1389}1390 1391// In MinGW, if no symbols are chosen to be exported, then all symbols are1392// automatically exported by default. This behavior can be forced by the1393// -export-all-symbols option, so that it happens even when exports are1394// explicitly specified. The automatic behavior can be disabled using the1395// -exclude-all-symbols option, so that lld-link behaves like link.exe rather1396// than MinGW in the case that nothing is explicitly exported.1397void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) {1398  if (!args.hasArg(OPT_export_all_symbols)) {1399    if (!ctx.config.dll)1400      return;1401 1402    if (ctx.symtab.hadExplicitExports ||1403        (ctx.config.machine == ARM64X && ctx.hybridSymtab->hadExplicitExports))1404      return;1405    if (args.hasArg(OPT_exclude_all_symbols))1406      return;1407  }1408 1409  ctx.forEachActiveSymtab([&](SymbolTable &symtab) {1410    AutoExporter exporter(symtab, excludedSymbols);1411 1412    for (auto *arg : args.filtered(OPT_wholearchive_file))1413      if (std::optional<StringRef> path = findFile(arg->getValue()))1414        exporter.addWholeArchive(*path);1415 1416    for (auto *arg : args.filtered(OPT_exclude_symbols)) {1417      SmallVector<StringRef, 2> vec;1418      StringRef(arg->getValue()).split(vec, ',');1419      for (StringRef sym : vec)1420        exporter.addExcludedSymbol(symtab.mangle(sym));1421    }1422 1423    symtab.forEachSymbol([&](Symbol *s) {1424      auto *def = dyn_cast<Defined>(s);1425      if (!exporter.shouldExport(def))1426        return;1427 1428      if (!def->isGCRoot) {1429        def->isGCRoot = true;1430        ctx.config.gcroot.push_back(def);1431      }1432 1433      Export e;1434      e.name = def->getName();1435      e.sym = def;1436      if (Chunk *c = def->getChunk())1437        if (!(c->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))1438          e.data = true;1439      s->isUsedInRegularObj = true;1440      symtab.exports.push_back(e);1441    });1442  });1443}1444 1445// lld has a feature to create a tar file containing all input files as well as1446// all command line options, so that other people can run lld again with exactly1447// the same inputs. This feature is accessible via /linkrepro and /reproduce.1448//1449// /linkrepro and /reproduce are very similar, but /linkrepro takes a directory1450// name while /reproduce takes a full path. We have /linkrepro for compatibility1451// with Microsoft link.exe.1452std::optional<std::string> getReproduceFile(const opt::InputArgList &args) {1453  if (auto *arg = args.getLastArg(OPT_reproduce))1454    return std::string(arg->getValue());1455 1456  if (auto *arg = args.getLastArg(OPT_linkrepro)) {1457    SmallString<64> path = StringRef(arg->getValue());1458    sys::path::append(path, "repro.tar");1459    return std::string(path);1460  }1461 1462  // This is intentionally not guarded by OPT_lldignoreenv since writing1463  // a repro tar file doesn't affect the main output.1464  if (auto *path = getenv("LLD_REPRODUCE"))1465    return std::string(path);1466 1467  return std::nullopt;1468}1469 1470static std::unique_ptr<llvm::vfs::FileSystem>1471getVFS(COFFLinkerContext &ctx, const opt::InputArgList &args) {1472  using namespace llvm::vfs;1473 1474  const opt::Arg *arg = args.getLastArg(OPT_vfsoverlay);1475  if (!arg)1476    return nullptr;1477 1478  auto bufOrErr = llvm::MemoryBuffer::getFile(arg->getValue());1479  if (!bufOrErr) {1480    checkError(errorCodeToError(bufOrErr.getError()));1481    return nullptr;1482  }1483 1484  if (auto ret = vfs::getVFSFromYAML(std::move(*bufOrErr),1485                                     /*DiagHandler*/ nullptr, arg->getValue()))1486    return ret;1487 1488  Err(ctx) << "Invalid vfs overlay";1489  return nullptr;1490}1491 1492constexpr const char *lldsaveTempsValues[] = {1493    "resolution", "preopt",     "promote", "internalize",  "import",1494    "opt",        "precodegen", "prelink", "combinedindex"};1495 1496void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {1497  ScopedTimer rootTimer(ctx.rootTimer);1498  Configuration *config = &ctx.config;1499 1500  // Needed for LTO.1501  InitializeAllTargetInfos();1502  InitializeAllTargets();1503  InitializeAllTargetMCs();1504  InitializeAllAsmParsers();1505  InitializeAllAsmPrinters();1506 1507  // If the first command line argument is "/lib", link.exe acts like lib.exe.1508  // We call our own implementation of lib.exe that understands bitcode files.1509  if (argsArr.size() > 1 &&1510      (StringRef(argsArr[1]).equals_insensitive("/lib") ||1511       StringRef(argsArr[1]).equals_insensitive("-lib"))) {1512    if (llvm::libDriverMain(argsArr.slice(1)) != 0)1513      Fatal(ctx) << "lib failed";1514    return;1515  }1516 1517  // Parse command line options.1518  ArgParser parser(ctx);1519  opt::InputArgList args = parser.parse(argsArr);1520 1521  // Initialize time trace profiler.1522  config->timeTraceEnabled = args.hasArg(OPT_time_trace_eq);1523  config->timeTraceGranularity =1524      args::getInteger(args, OPT_time_trace_granularity_eq, 500);1525 1526  if (config->timeTraceEnabled)1527    timeTraceProfilerInitialize(config->timeTraceGranularity, argsArr[0]);1528 1529  llvm::TimeTraceScope timeScope("COFF link");1530 1531  // Parse and evaluate -mllvm options.1532  std::vector<const char *> v;1533  v.push_back("lld-link (LLVM option parsing)");1534  for (const auto *arg : args.filtered(OPT_mllvm)) {1535    v.push_back(arg->getValue());1536    config->mllvmOpts.emplace_back(arg->getValue());1537  }1538  {1539    llvm::TimeTraceScope timeScope2("Parse cl::opt");1540    cl::ResetAllOptionOccurrences();1541    cl::ParseCommandLineOptions(v.size(), v.data());1542  }1543 1544  // Handle /errorlimit early, because error() depends on it.1545  if (auto *arg = args.getLastArg(OPT_errorlimit)) {1546    int n = 20;1547    StringRef s = arg->getValue();1548    if (s.getAsInteger(10, n))1549      Err(ctx) << arg->getSpelling() << " number expected, but got " << s;1550    ctx.e.errorLimit = n;1551  }1552 1553  config->vfs = getVFS(ctx, args);1554 1555  // Handle /help1556  if (args.hasArg(OPT_help)) {1557    printHelp(argsArr[0]);1558    return;1559  }1560 1561  // /threads: takes a positive integer and provides the default value for1562  // /opt:lldltojobs=.1563  if (auto *arg = args.getLastArg(OPT_threads)) {1564    StringRef v(arg->getValue());1565    unsigned threads = 0;1566    if (!llvm::to_integer(v, threads, 0) || threads == 0)1567      Err(ctx) << arg->getSpelling()1568               << ": expected a positive integer, but got '" << arg->getValue()1569               << "'";1570    parallel::strategy = hardware_concurrency(threads);1571    config->thinLTOJobs = v.str();1572  }1573 1574  if (args.hasArg(OPT_show_timing))1575    config->showTiming = true;1576 1577  config->showSummary = args.hasArg(OPT_summary);1578  config->printSearchPaths = args.hasArg(OPT_print_search_paths);1579 1580  // Handle --version, which is an lld extension. This option is a bit odd1581  // because it doesn't start with "/", but we deliberately chose "--" to1582  // avoid conflict with /version and for compatibility with clang-cl.1583  if (args.hasArg(OPT_dash_dash_version)) {1584    Msg(ctx) << getLLDVersion();1585    return;1586  }1587 1588  // Handle /lldmingw early, since it can potentially affect how other1589  // options are handled.1590  config->mingw = args.hasArg(OPT_lldmingw);1591  if (config->mingw)1592    ctx.e.errorLimitExceededMsg = "too many errors emitted, stopping now"1593                                  " (use --error-limit=0 to see all errors)";1594 1595  // Handle /linkrepro and /reproduce.1596  {1597    llvm::TimeTraceScope timeScope2("Reproducer");1598    if (std::optional<std::string> path = getReproduceFile(args)) {1599      Expected<std::unique_ptr<TarWriter>> errOrWriter =1600          TarWriter::create(*path, sys::path::stem(*path));1601 1602      if (errOrWriter) {1603        tar = std::move(*errOrWriter);1604      } else {1605        Err(ctx) << "/linkrepro: failed to open " << *path << ": "1606                 << toString(errOrWriter.takeError());1607      }1608    }1609  }1610 1611  if (!args.hasArg(OPT_INPUT, OPT_wholearchive_file)) {1612    if (args.hasArg(OPT_deffile))1613      config->noEntry = true;1614    else1615      Fatal(ctx) << "no input files";1616  }1617 1618  // Construct search path list.1619  {1620    llvm::TimeTraceScope timeScope2("Search paths");1621    searchPaths.emplace_back("");1622    for (auto *arg : args.filtered(OPT_libpath))1623      searchPaths.push_back(arg->getValue());1624    if (!config->mingw) {1625      // Prefer the Clang provided builtins over the ones bundled with MSVC.1626      // In MinGW mode, the compiler driver passes the necessary libpath1627      // options explicitly.1628      addClangLibSearchPaths(argsArr[0]);1629      // Don't automatically deduce the lib path from the environment or MSVC1630      // installations when operating in mingw mode. (This also makes LLD ignore1631      // winsysroot and vctoolsdir arguments.)1632      detectWinSysRoot(args);1633      if (!args.hasArg(OPT_lldignoreenv, OPT_winsysroot, OPT_vctoolsdir,1634                       OPT_vctoolsversion, OPT_winsdkdir, OPT_winsdkversion))1635        addLibSearchPaths();1636    } else {1637      if (args.hasArg(OPT_vctoolsdir, OPT_winsysroot))1638        Warn(ctx) << "ignoring /vctoolsdir or /winsysroot flags in MinGW mode";1639    }1640  }1641 1642  // Handle /ignore1643  for (auto *arg : args.filtered(OPT_ignore)) {1644    SmallVector<StringRef, 8> vec;1645    StringRef(arg->getValue()).split(vec, ',');1646    for (StringRef s : vec) {1647      if (s == "4037")1648        config->warnMissingOrderSymbol = false;1649      else if (s == "4099")1650        config->warnDebugInfoUnusable = false;1651      else if (s == "4217")1652        config->warnLocallyDefinedImported = false;1653      else if (s == "longsections")1654        config->warnLongSectionNames = false;1655      else if (s == "importeddllmain")1656        config->warnImportedDllMain = false;1657      // Other warning numbers are ignored.1658    }1659  }1660 1661  // Handle /out1662  if (auto *arg = args.getLastArg(OPT_out))1663    config->outputFile = arg->getValue();1664 1665  // Handle /verbose1666  if (args.hasArg(OPT_verbose))1667    config->verbose = true;1668  ctx.e.verbose = config->verbose;1669 1670  // Handle /force or /force:unresolved1671  if (args.hasArg(OPT_force, OPT_force_unresolved))1672    config->forceUnresolved = true;1673 1674  // Handle /force or /force:multiple1675  if (args.hasArg(OPT_force, OPT_force_multiple))1676    config->forceMultiple = true;1677 1678  // Handle /force or /force:multipleres1679  if (args.hasArg(OPT_force, OPT_force_multipleres))1680    config->forceMultipleRes = true;1681 1682  // Don't warn about long section names, such as .debug_info, for mingw (or1683  // when -debug:dwarf is requested, handled below).1684  if (config->mingw)1685    config->warnLongSectionNames = false;1686 1687  bool doGC = true;1688 1689  // Handle /debug1690  bool shouldCreatePDB = false;1691  for (auto *arg : args.filtered(OPT_debug, OPT_debug_opt)) {1692    std::string str;1693    if (arg->getOption().getID() == OPT_debug)1694      str = "full";1695    else1696      str = StringRef(arg->getValue()).lower();1697    SmallVector<StringRef, 1> vec;1698    StringRef(str).split(vec, ',');1699    for (StringRef s : vec) {1700      if (s == "fastlink") {1701        Warn(ctx) << "/debug:fastlink unsupported; using /debug:full";1702        s = "full";1703      }1704      if (s == "none") {1705        config->debug = false;1706        config->incremental = false;1707        config->includeDwarfChunks = false;1708        config->debugGHashes = false;1709        config->writeSymtab = false;1710        shouldCreatePDB = false;1711        doGC = true;1712      } else if (s == "full" || s == "ghash" || s == "noghash") {1713        config->debug = true;1714        config->incremental = true;1715        config->includeDwarfChunks = true;1716        if (s == "full" || s == "ghash")1717          config->debugGHashes = true;1718        shouldCreatePDB = true;1719        doGC = false;1720      } else if (s == "dwarf") {1721        config->debug = true;1722        config->incremental = true;1723        config->includeDwarfChunks = true;1724        config->writeSymtab = true;1725        config->warnLongSectionNames = false;1726        doGC = false;1727      } else if (s == "nodwarf") {1728        config->includeDwarfChunks = false;1729      } else if (s == "symtab") {1730        config->writeSymtab = true;1731        doGC = false;1732      } else if (s == "nosymtab") {1733        config->writeSymtab = false;1734      } else {1735        Err(ctx) << "/debug: unknown option: " << s;1736      }1737    }1738  }1739 1740  // Handle /demangle1741  config->demangle = args.hasFlag(OPT_demangle, OPT_demangle_no, true);1742 1743  // Handle /debugtype1744  config->debugTypes = parseDebugTypes(ctx, args);1745 1746  // Handle /driver[:uponly|:wdm].1747  config->driverUponly = args.hasArg(OPT_driver_uponly) ||1748                         args.hasArg(OPT_driver_uponly_wdm) ||1749                         args.hasArg(OPT_driver_wdm_uponly);1750  config->driverWdm = args.hasArg(OPT_driver_wdm) ||1751                      args.hasArg(OPT_driver_uponly_wdm) ||1752                      args.hasArg(OPT_driver_wdm_uponly);1753  config->driver =1754      config->driverUponly || config->driverWdm || args.hasArg(OPT_driver);1755 1756  // Handle /pdb1757  if (shouldCreatePDB) {1758    if (auto *arg = args.getLastArg(OPT_pdb))1759      config->pdbPath = arg->getValue();1760    if (auto *arg = args.getLastArg(OPT_pdbaltpath))1761      config->pdbAltPath = arg->getValue();1762    if (auto *arg = args.getLastArg(OPT_pdbpagesize))1763      parsePDBPageSize(arg->getValue());1764    if (args.hasArg(OPT_natvis))1765      config->natvisFiles = args.getAllArgValues(OPT_natvis);1766    if (args.hasArg(OPT_pdbstream)) {1767      for (const StringRef value : args.getAllArgValues(OPT_pdbstream)) {1768        const std::pair<StringRef, StringRef> nameFile = value.split("=");1769        const StringRef name = nameFile.first;1770        const std::string file = nameFile.second.str();1771        config->namedStreams[name] = file;1772      }1773    }1774 1775    if (auto *arg = args.getLastArg(OPT_pdb_source_path))1776      config->pdbSourcePath = arg->getValue();1777  }1778 1779  // Handle /pdbstripped1780  if (args.hasArg(OPT_pdbstripped))1781    Warn(ctx) << "ignoring /pdbstripped flag, it is not yet supported";1782 1783  // Handle /noentry1784  if (args.hasArg(OPT_noentry)) {1785    if (args.hasArg(OPT_dll))1786      config->noEntry = true;1787    else1788      Err(ctx) << "/noentry must be specified with /dll";1789  }1790 1791  // Handle /dll1792  if (args.hasArg(OPT_dll)) {1793    config->dll = true;1794    config->manifestID = 2;1795  }1796 1797  // Handle /dynamicbase and /fixed. We can't use hasFlag for /dynamicbase1798  // because we need to explicitly check whether that option or its inverse was1799  // present in the argument list in order to handle /fixed.1800  auto *dynamicBaseArg = args.getLastArg(OPT_dynamicbase, OPT_dynamicbase_no);1801  if (dynamicBaseArg &&1802      dynamicBaseArg->getOption().getID() == OPT_dynamicbase_no)1803    config->dynamicBase = false;1804 1805  // MSDN claims "/FIXED:NO is the default setting for a DLL, and /FIXED is the1806  // default setting for any other project type.", but link.exe defaults to1807  // /FIXED:NO for exe outputs as well. Match behavior, not docs.1808  bool fixed = args.hasFlag(OPT_fixed, OPT_fixed_no, false);1809  if (fixed) {1810    if (dynamicBaseArg &&1811        dynamicBaseArg->getOption().getID() == OPT_dynamicbase) {1812      Err(ctx) << "/fixed must not be specified with /dynamicbase";1813    } else {1814      config->relocatable = false;1815      config->dynamicBase = false;1816    }1817  }1818 1819  // Handle /appcontainer1820  config->appContainer =1821      args.hasFlag(OPT_appcontainer, OPT_appcontainer_no, false);1822 1823  // Handle /machine1824  {1825    llvm::TimeTraceScope timeScope2("Machine arg");1826    if (auto *arg = args.getLastArg(OPT_machine)) {1827      MachineTypes machine = getMachineType(arg->getValue());1828      if (machine == IMAGE_FILE_MACHINE_UNKNOWN)1829        Fatal(ctx) << "unknown /machine argument: " << arg->getValue();1830      setMachine(machine);1831    }1832  }1833 1834  // Handle /nodefaultlib:<filename>1835  {1836    llvm::TimeTraceScope timeScope2("Nodefaultlib");1837    for (auto *arg : args.filtered(OPT_nodefaultlib))1838      config->noDefaultLibs.insert(findLib(arg->getValue()).lower());1839  }1840 1841  // Handle /nodefaultlib1842  if (args.hasArg(OPT_nodefaultlib_all))1843    config->noDefaultLibAll = true;1844 1845  // Handle /base1846  if (auto *arg = args.getLastArg(OPT_base))1847    parseNumbers(arg->getValue(), &config->imageBase);1848 1849  // Handle /filealign1850  if (auto *arg = args.getLastArg(OPT_filealign)) {1851    parseNumbers(arg->getValue(), &config->fileAlign);1852    if (!isPowerOf2_64(config->fileAlign))1853      Err(ctx) << "/filealign: not a power of two: " << config->fileAlign;1854  }1855 1856  // Handle /stack1857  if (auto *arg = args.getLastArg(OPT_stack))1858    parseNumbers(arg->getValue(), &config->stackReserve, &config->stackCommit);1859 1860  // Handle /guard:cf1861  if (auto *arg = args.getLastArg(OPT_guard))1862    parseGuard(arg->getValue());1863 1864  // Handle /heap1865  if (auto *arg = args.getLastArg(OPT_heap))1866    parseNumbers(arg->getValue(), &config->heapReserve, &config->heapCommit);1867 1868  // Handle /version1869  if (auto *arg = args.getLastArg(OPT_version))1870    parseVersion(arg->getValue(), &config->majorImageVersion,1871                 &config->minorImageVersion);1872 1873  // Handle /subsystem1874  if (auto *arg = args.getLastArg(OPT_subsystem))1875    parseSubsystem(arg->getValue(), &config->subsystem,1876                   &config->majorSubsystemVersion,1877                   &config->minorSubsystemVersion);1878 1879  // Handle /osversion1880  if (auto *arg = args.getLastArg(OPT_osversion)) {1881    parseVersion(arg->getValue(), &config->majorOSVersion,1882                 &config->minorOSVersion);1883  } else {1884    config->majorOSVersion = config->majorSubsystemVersion;1885    config->minorOSVersion = config->minorSubsystemVersion;1886  }1887 1888  // Handle /timestamp1889  if (llvm::opt::Arg *arg = args.getLastArg(OPT_timestamp, OPT_repro)) {1890    if (arg->getOption().getID() == OPT_repro) {1891      config->timestamp = 0;1892      config->repro = true;1893    } else {1894      config->repro = false;1895      StringRef value(arg->getValue());1896      if (value.getAsInteger(0, config->timestamp))1897        Fatal(ctx) << "invalid timestamp: " << value1898                   << ".  Expected 32-bit integer";1899    }1900  } else {1901    config->repro = false;1902    if (std::optional<std::string> epoch =1903            Process::GetEnv("SOURCE_DATE_EPOCH")) {1904      StringRef value(*epoch);1905      if (value.getAsInteger(0, config->timestamp))1906        Fatal(ctx) << "invalid SOURCE_DATE_EPOCH timestamp: " << value1907                   << ".  Expected 32-bit integer";1908    } else {1909      config->timestamp = time(nullptr);1910    }1911  }1912 1913  // Handle /alternatename1914  for (auto *arg : args.filtered(OPT_alternatename))1915    ctx.symtab.parseAlternateName(arg->getValue());1916 1917  // Handle /include1918  for (auto *arg : args.filtered(OPT_incl))1919    ctx.symtab.addGCRoot(arg->getValue());1920 1921  // Handle /implib1922  if (auto *arg = args.getLastArg(OPT_implib))1923    config->implib = arg->getValue();1924 1925  config->noimplib = args.hasArg(OPT_noimplib);1926 1927  if (args.hasArg(OPT_profile))1928    doGC = true;1929  // Handle /opt.1930  std::optional<ICFLevel> icfLevel;1931  if (args.hasArg(OPT_profile))1932    icfLevel = ICFLevel::None;1933  unsigned tailMerge = 1;1934  bool ltoDebugPM = false;1935  for (auto *arg : args.filtered(OPT_opt)) {1936    std::string str = StringRef(arg->getValue()).lower();1937    SmallVector<StringRef, 1> vec;1938    StringRef(str).split(vec, ',');1939    for (StringRef s : vec) {1940      if (s == "ref") {1941        doGC = true;1942      } else if (s == "noref") {1943        doGC = false;1944      } else if (s == "icf" || s.starts_with("icf=")) {1945        icfLevel = ICFLevel::All;1946      } else if (s == "safeicf") {1947        icfLevel = ICFLevel::Safe;1948      } else if (s == "noicf") {1949        icfLevel = ICFLevel::None;1950      } else if (s == "lldtailmerge") {1951        tailMerge = 2;1952      } else if (s == "nolldtailmerge") {1953        tailMerge = 0;1954      } else if (s == "ltodebugpassmanager") {1955        ltoDebugPM = true;1956      } else if (s == "noltodebugpassmanager") {1957        ltoDebugPM = false;1958      } else if (s.consume_front("lldlto=")) {1959        if (s.getAsInteger(10, config->ltoo) || config->ltoo > 3)1960          Err(ctx) << "/opt:lldlto: invalid optimization level: " << s;1961      } else if (s.consume_front("lldltocgo=")) {1962        config->ltoCgo.emplace();1963        if (s.getAsInteger(10, *config->ltoCgo) || *config->ltoCgo > 3)1964          Err(ctx) << "/opt:lldltocgo: invalid codegen optimization level: "1965                   << s;1966      } else if (s.consume_front("lldltojobs=")) {1967        if (!get_threadpool_strategy(s))1968          Err(ctx) << "/opt:lldltojobs: invalid job count: " << s;1969        config->thinLTOJobs = s.str();1970      } else if (s.consume_front("lldltopartitions=")) {1971        if (s.getAsInteger(10, config->ltoPartitions) ||1972            config->ltoPartitions == 0)1973          Err(ctx) << "/opt:lldltopartitions: invalid partition count: " << s;1974      } else if (s != "lbr" && s != "nolbr")1975        Err(ctx) << "/opt: unknown option: " << s;1976    }1977  }1978 1979  if (!icfLevel)1980    icfLevel = doGC ? ICFLevel::All : ICFLevel::None;1981  config->doGC = doGC;1982  config->doICF = *icfLevel;1983  config->tailMerge =1984      (tailMerge == 1 && config->doICF != ICFLevel::None) || tailMerge == 2;1985  config->ltoDebugPassManager = ltoDebugPM;1986 1987  // Handle /lldsavetemps1988  if (args.hasArg(OPT_lldsavetemps)) {1989    config->saveTempsArgs.insert_range(lldsaveTempsValues);1990  } else {1991    for (auto *arg : args.filtered(OPT_lldsavetemps_colon)) {1992      StringRef s = arg->getValue();1993      if (llvm::is_contained(lldsaveTempsValues, s))1994        config->saveTempsArgs.insert(s);1995      else1996        Err(ctx) << "unknown /lldsavetemps value: " << s;1997    }1998  }1999 2000  // Handle /lldemit2001  if (auto *arg = args.getLastArg(OPT_lldemit)) {2002    StringRef s = arg->getValue();2003    if (s == "obj")2004      config->emit = EmitKind::Obj;2005    else if (s == "llvm")2006      config->emit = EmitKind::LLVM;2007    else if (s == "asm")2008      config->emit = EmitKind::ASM;2009    else2010      Err(ctx) << "/lldemit: unknown option: " << s;2011  }2012 2013  // Handle /kill-at2014  if (args.hasArg(OPT_kill_at))2015    config->killAt = true;2016 2017  // Handle /lldltocache2018  if (auto *arg = args.getLastArg(OPT_lldltocache))2019    config->ltoCache = arg->getValue();2020 2021  // Handle /lldsavecachepolicy2022  if (auto *arg = args.getLastArg(OPT_lldltocachepolicy))2023    config->ltoCachePolicy = CHECK(2024        parseCachePruningPolicy(arg->getValue()),2025        Twine("/lldltocachepolicy: invalid cache policy: ") + arg->getValue());2026 2027  // Handle /failifmismatch2028  for (auto *arg : args.filtered(OPT_failifmismatch))2029    checkFailIfMismatch(arg->getValue(), nullptr);2030 2031  // Handle /merge2032  for (auto *arg : args.filtered(OPT_merge))2033    parseMerge(arg->getValue());2034 2035  // Add default section merging rules after user rules. User rules take2036  // precedence, but we will emit a warning if there is a conflict.2037  parseMerge(".idata=.rdata");2038  parseMerge(".didat=.rdata");2039  parseMerge(".edata=.rdata");2040  parseMerge(".xdata=.rdata");2041  parseMerge(".00cfg=.rdata");2042  parseMerge(".bss=.data");2043 2044  if (isArm64EC(config->machine))2045    parseMerge(".wowthk=.text");2046 2047  if (config->mingw) {2048    parseMerge(".ctors=.rdata");2049    parseMerge(".dtors=.rdata");2050    parseMerge(".CRT=.rdata");2051    parseMerge(".data_cygwin_nocopy=.data");2052  }2053 2054  // Handle /section2055  for (auto *arg : args.filtered(OPT_section))2056    parseSection(arg->getValue());2057  // Handle /sectionlayout2058  if (auto *arg = args.getLastArg(OPT_sectionlayout))2059    parseSectionLayout(arg->getValue());2060 2061  // Handle /align2062  if (auto *arg = args.getLastArg(OPT_align)) {2063    parseNumbers(arg->getValue(), &config->align);2064    if (!isPowerOf2_64(config->align))2065      Err(ctx) << "/align: not a power of two: " << StringRef(arg->getValue());2066    if (!args.hasArg(OPT_driver))2067      Warn(ctx) << "/align specified without /driver; image may not run";2068  }2069 2070  // Handle /aligncomm2071  for (auto *arg : args.filtered(OPT_aligncomm))2072    ctx.symtab.parseAligncomm(arg->getValue());2073 2074  // Handle /manifestdependency.2075  for (auto *arg : args.filtered(OPT_manifestdependency))2076    config->manifestDependencies.insert(arg->getValue());2077 2078  // Handle /manifest and /manifest:2079  if (auto *arg = args.getLastArg(OPT_manifest, OPT_manifest_colon)) {2080    if (arg->getOption().getID() == OPT_manifest)2081      config->manifest = Configuration::SideBySide;2082    else2083      parseManifest(arg->getValue());2084  }2085 2086  // Handle /manifestuac2087  if (auto *arg = args.getLastArg(OPT_manifestuac))2088    parseManifestUAC(arg->getValue());2089 2090  // Handle /manifestfile2091  if (auto *arg = args.getLastArg(OPT_manifestfile))2092    config->manifestFile = arg->getValue();2093 2094  // Handle /manifestinput2095  for (auto *arg : args.filtered(OPT_manifestinput))2096    config->manifestInput.push_back(arg->getValue());2097 2098  if (!config->manifestInput.empty() &&2099      config->manifest != Configuration::Embed) {2100    Fatal(ctx) << "/manifestinput: requires /manifest:embed";2101  }2102 2103  // Handle /thinlto-distributor:<path>2104  config->dtltoDistributor = args.getLastArgValue(OPT_thinlto_distributor);2105 2106  // Handle /thinlto-distributor-arg:<arg>2107  config->dtltoDistributorArgs =2108      args::getStrings(args, OPT_thinlto_distributor_arg);2109 2110  // Handle /thinlto-remote-compiler:<path>2111  config->dtltoCompiler = args.getLastArgValue(OPT_thinlto_remote_compiler);2112  if (!config->dtltoDistributor.empty() && config->dtltoCompiler.empty())2113    Err(ctx) << "A value must be specified for /thinlto-remote-compiler if "2114                "/thinlto-distributor is specified.";2115 2116  // Handle /thinlto-remote-compiler-prepend-arg:<arg>2117  config->dtltoCompilerPrependArgs =2118      args::getStrings(args, OPT_thinlto_remote_compiler_prepend_arg);2119 2120  // Handle /thinlto-remote-compiler-arg:<arg>2121  config->dtltoCompilerArgs =2122      args::getStrings(args, OPT_thinlto_remote_compiler_arg);2123 2124  // Handle /dwodir2125  config->dwoDir = args.getLastArgValue(OPT_dwodir);2126 2127  config->thinLTOEmitImportsFiles = args.hasArg(OPT_thinlto_emit_imports_files);2128  config->thinLTOIndexOnly = args.hasArg(OPT_thinlto_index_only) ||2129                             args.hasArg(OPT_thinlto_index_only_arg);2130  config->thinLTOIndexOnlyArg =2131      args.getLastArgValue(OPT_thinlto_index_only_arg);2132  std::tie(config->thinLTOPrefixReplaceOld, config->thinLTOPrefixReplaceNew,2133           config->thinLTOPrefixReplaceNativeObject) =2134      getOldNewOptionsExtra(ctx, args, OPT_thinlto_prefix_replace);2135  config->thinLTOObjectSuffixReplace =2136      getOldNewOptions(ctx, args, OPT_thinlto_object_suffix_replace);2137  config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path);2138  config->ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate);2139  config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file);2140  config->ltoSampleProfileName = args.getLastArgValue(OPT_lto_sample_profile);2141  // Handle miscellaneous boolean flags.2142  config->ltoPGOWarnMismatch = args.hasFlag(OPT_lto_pgo_warn_mismatch,2143                                            OPT_lto_pgo_warn_mismatch_no, true);2144  config->allowBind = args.hasFlag(OPT_allowbind, OPT_allowbind_no, true);2145  config->allowIsolation =2146      args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true);2147  config->incremental =2148      args.hasFlag(OPT_incremental, OPT_incremental_no,2149                   !config->doGC && config->doICF == ICFLevel::None &&2150                       !args.hasArg(OPT_order) && !args.hasArg(OPT_profile));2151  config->integrityCheck =2152      args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false);2153  config->cetCompat = args.hasFlag(OPT_cetcompat, OPT_cetcompat_no, false);2154  config->cetCompatStrict =2155      args.hasFlag(OPT_cetcompatstrict, OPT_cetcompatstrict_no, false);2156  config->cetCompatIpValidationRelaxed = args.hasFlag(2157      OPT_cetipvalidationrelaxed, OPT_cetipvalidationrelaxed_no, false);2158  config->cetCompatDynamicApisInProcOnly = args.hasFlag(2159      OPT_cetdynamicapisinproc, OPT_cetdynamicapisinproc_no, false);2160  config->hotpatchCompat =2161      args.hasFlag(OPT_hotpatchcompatible, OPT_hotpatchcompatible_no, false);2162  config->nxCompat = args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true);2163  for (auto *arg : args.filtered(OPT_swaprun))2164    parseSwaprun(arg->getValue());2165  config->terminalServerAware =2166      !config->dll && args.hasFlag(OPT_tsaware, OPT_tsaware_no, true);2167  config->autoImport =2168      args.hasFlag(OPT_auto_import, OPT_auto_import_no, config->mingw);2169  config->pseudoRelocs = args.hasFlag(2170      OPT_runtime_pseudo_reloc, OPT_runtime_pseudo_reloc_no, config->mingw);2171  config->callGraphProfileSort = args.hasFlag(2172      OPT_call_graph_profile_sort, OPT_call_graph_profile_sort_no, true);2173  config->stdcallFixup =2174      args.hasFlag(OPT_stdcall_fixup, OPT_stdcall_fixup_no, config->mingw);2175  config->warnStdcallFixup = !args.hasArg(OPT_stdcall_fixup);2176  config->allowDuplicateWeak =2177      args.hasFlag(OPT_lld_allow_duplicate_weak,2178                   OPT_lld_allow_duplicate_weak_no, config->mingw);2179 2180  if (args.hasFlag(OPT_inferasanlibs, OPT_inferasanlibs_no, false))2181    Warn(ctx) << "ignoring '/inferasanlibs', this flag is not supported";2182 2183  if (config->incremental && args.hasArg(OPT_profile)) {2184    Warn(ctx) << "ignoring '/incremental' due to '/profile' specification";2185    config->incremental = false;2186  }2187 2188  if (config->incremental && args.hasArg(OPT_order)) {2189    Warn(ctx) << "ignoring '/incremental' due to '/order' specification";2190    config->incremental = false;2191  }2192 2193  if (config->incremental && config->doGC) {2194    Warn(ctx) << "ignoring '/incremental' because REF is enabled; use "2195                 "'/opt:noref' to "2196                 "disable";2197    config->incremental = false;2198  }2199 2200  if (config->incremental && config->doICF != ICFLevel::None) {2201    Warn(ctx) << "ignoring '/incremental' because ICF is enabled; use "2202                 "'/opt:noicf' to "2203                 "disable";2204    config->incremental = false;2205  }2206 2207  if (errCount(ctx))2208    return;2209 2210  std::set<sys::fs::UniqueID> wholeArchives;2211  for (auto *arg : args.filtered(OPT_wholearchive_file))2212    if (std::optional<StringRef> path = findFile(arg->getValue()))2213      if (std::optional<sys::fs::UniqueID> id = getUniqueID(*path))2214        wholeArchives.insert(*id);2215 2216  // A predicate returning true if a given path is an argument for2217  // /wholearchive:, or /wholearchive is enabled globally.2218  // This function is a bit tricky because "foo.obj /wholearchive:././foo.obj"2219  // needs to be handled as "/wholearchive:foo.obj foo.obj".2220  auto isWholeArchive = [&](StringRef path) -> bool {2221    if (args.hasArg(OPT_wholearchive_flag))2222      return true;2223    if (std::optional<sys::fs::UniqueID> id = getUniqueID(path))2224      return wholeArchives.count(*id);2225    return false;2226  };2227 2228  // Create a list of input files. These can be given as OPT_INPUT options2229  // and OPT_wholearchive_file options, and we also need to track OPT_start_lib2230  // and OPT_end_lib.2231  {2232    llvm::TimeTraceScope timeScope2("Parse & queue inputs");2233    bool inLib = false;2234    for (auto *arg : args) {2235      switch (arg->getOption().getID()) {2236      case OPT_end_lib:2237        if (!inLib)2238          Err(ctx) << "stray " << arg->getSpelling();2239        inLib = false;2240        break;2241      case OPT_start_lib:2242        if (inLib)2243          Err(ctx) << "nested " << arg->getSpelling();2244        inLib = true;2245        break;2246      case OPT_wholearchive_file:2247        if (std::optional<StringRef> path = findFileIfNew(arg->getValue()))2248          enqueuePath(*path, true, inLib);2249        break;2250      case OPT_INPUT:2251        if (std::optional<StringRef> path = findFileIfNew(arg->getValue()))2252          enqueuePath(*path, isWholeArchive(*path), inLib);2253        break;2254      default:2255        // Ignore other options.2256        break;2257      }2258    }2259  }2260 2261  // Read all input files given via the command line.2262  run();2263  if (errorCount())2264    return;2265 2266  // We should have inferred a machine type by now from the input files, but if2267  // not we assume x64.2268  if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) {2269    Warn(ctx) << "/machine is not specified. x64 is assumed";2270    setMachine(AMD64);2271  }2272  config->wordsize = config->is64() ? 8 : 4;2273 2274  if (config->printSearchPaths) {2275    SmallString<256> buffer;2276    raw_svector_ostream stream(buffer);2277    stream << "Library search paths:\n";2278 2279    for (StringRef path : searchPaths) {2280      if (path == "")2281        path = "(cwd)";2282      stream << "  " << path << "\n";2283    }2284 2285    Msg(ctx) << buffer;2286  }2287 2288  // Process files specified as /defaultlib. These must be processed after2289  // addWinSysRootLibSearchPaths(), which is why they are in a separate loop.2290  for (auto *arg : args.filtered(OPT_defaultlib))2291    if (std::optional<StringRef> path = findLibIfNew(arg->getValue()))2292      enqueuePath(*path, false, false);2293  run();2294  if (errorCount())2295    return;2296 2297  // Handle /RELEASE2298  if (args.hasArg(OPT_release))2299    config->writeCheckSum = true;2300 2301  // Handle /safeseh, x86 only, on by default, except for mingw.2302  if (config->machine == I386) {2303    config->safeSEH = args.hasFlag(OPT_safeseh, OPT_safeseh_no, !config->mingw);2304    config->noSEH = args.hasArg(OPT_noseh);2305  }2306 2307  // Handle /stub2308  if (auto *arg = args.getLastArg(OPT_stub))2309    parseDosStub(arg->getValue());2310 2311  // Handle /functionpadmin2312  for (auto *arg : args.filtered(OPT_functionpadmin, OPT_functionpadmin_opt))2313    parseFunctionPadMin(arg);2314 2315  // MS link.exe compatibility, at least 6 bytes of function padding is2316  // required if hotpatchable2317  if (config->hotpatchCompat && config->functionPadMin < 6)2318    Err(ctx)2319        << "/hotpatchcompatible: requires at least 6 bytes of /functionpadmin";2320 2321  // Handle /dependentloadflag2322  for (auto *arg :2323       args.filtered(OPT_dependentloadflag, OPT_dependentloadflag_opt))2324    parseDependentLoadFlags(arg);2325 2326  for (auto *arg : args.filtered(OPT_arm64xsameaddress)) {2327    if (ctx.hybridSymtab)2328      parseSameAddress(arg->getValue());2329    else2330      Warn(ctx) << arg->getSpelling() << " is allowed only on EC targets";2331  }2332 2333  if (tar) {2334    llvm::TimeTraceScope timeScope("Reproducer: response file");2335    tar->append(2336        "response.txt",2337        createResponseFile(args, ArrayRef<StringRef>(searchPaths).slice(1)));2338  }2339 2340  // Handle /largeaddressaware2341  config->largeAddressAware = args.hasFlag(2342      OPT_largeaddressaware, OPT_largeaddressaware_no, config->is64());2343 2344  // Handle /highentropyva2345  config->highEntropyVA =2346      config->is64() &&2347      args.hasFlag(OPT_highentropyva, OPT_highentropyva_no, true);2348 2349  // Handle /nodbgdirmerge2350  config->mergeDebugDirectory = !args.hasArg(OPT_nodbgdirmerge);2351 2352  if (!config->dynamicBase &&2353      (config->machine == ARMNT || isAnyArm64(config->machine)))2354    Err(ctx) << "/dynamicbase:no is not compatible with "2355             << machineToStr(config->machine);2356 2357  // Handle /export2358  {2359    llvm::TimeTraceScope timeScope("Parse /export");2360    for (auto *arg : args.filtered(OPT_export)) {2361      Export e = parseExport(arg->getValue());2362      if (config->machine == I386) {2363        if (!isDecorated(e.name))2364          e.name = saver().save("_" + e.name);2365        if (!e.extName.empty() && !isDecorated(e.extName))2366          e.extName = saver().save("_" + e.extName);2367      }2368      ctx.symtab.exports.push_back(e);2369    }2370  }2371 2372  // Handle /def2373  if (auto *arg = args.getLastArg(OPT_deffile)) {2374    // parseModuleDefs mutates Config object.2375    ctx.symtab.parseModuleDefs(arg->getValue());2376    if (ctx.config.machine == ARM64X) {2377      // MSVC ignores the /defArm64Native argument on non-ARM64X targets.2378      // It is also ignored if the /def option is not specified.2379      if (auto *arg = args.getLastArg(OPT_defarm64native))2380        ctx.hybridSymtab->parseModuleDefs(arg->getValue());2381    }2382  }2383 2384  // Handle generation of import library from a def file.2385  if (!args.hasArg(OPT_INPUT, OPT_wholearchive_file)) {2386    ctx.forEachSymtab([](SymbolTable &symtab) { symtab.fixupExports(); });2387    if (!config->noimplib)2388      createImportLibrary(/*asLib=*/true);2389    return;2390  }2391 2392  // Windows specific -- if no /subsystem is given, we need to infer2393  // that from entry point name.  Must happen before /entry handling,2394  // and after the early return when just writing an import library.2395  if (config->subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {2396    llvm::TimeTraceScope timeScope("Infer subsystem");2397    config->subsystem = ctx.symtab.inferSubsystem();2398    if (config->subsystem == IMAGE_SUBSYSTEM_UNKNOWN)2399      Fatal(ctx) << "subsystem must be defined";2400  }2401 2402  // Handle /entry and /dll2403  ctx.forEachActiveSymtab([&](SymbolTable &symtab) {2404    llvm::TimeTraceScope timeScope("Entry point");2405    if (auto *arg = args.getLastArg(OPT_entry)) {2406      if (!arg->getValue()[0])2407        Fatal(ctx) << "missing entry point symbol name";2408      symtab.entry = symtab.addGCRoot(symtab.mangle(arg->getValue()), true);2409    } else if (!symtab.entry && !config->noEntry) {2410      if (args.hasArg(OPT_dll)) {2411        StringRef s = (config->machine == I386) ? "__DllMainCRTStartup@12"2412                                                : "_DllMainCRTStartup";2413        symtab.entry = symtab.addGCRoot(s, true);2414      } else if (config->driverWdm) {2415        // /driver:wdm implies /entry:_NtProcessStartup2416        symtab.entry =2417            symtab.addGCRoot(symtab.mangle("_NtProcessStartup"), true);2418      } else {2419        // Windows specific -- If entry point name is not given, we need to2420        // infer that from user-defined entry name.2421        StringRef s = symtab.findDefaultEntry();2422        if (s.empty())2423          Fatal(ctx) << "entry point must be defined";2424        symtab.entry = symtab.addGCRoot(s, true);2425        Log(ctx) << "Entry name inferred: " << s;2426      }2427    }2428  });2429 2430  // Handle /delayload2431  {2432    llvm::TimeTraceScope timeScope("Delay load");2433    for (auto *arg : args.filtered(OPT_delayload)) {2434      config->delayLoads.insert(StringRef(arg->getValue()).lower());2435      ctx.forEachActiveSymtab([&](SymbolTable &symtab) {2436        if (symtab.machine == I386) {2437          symtab.delayLoadHelper = symtab.addGCRoot("___delayLoadHelper2@8");2438        } else {2439          symtab.delayLoadHelper = symtab.addGCRoot("__delayLoadHelper2", true);2440        }2441      });2442    }2443  }2444 2445  // Set default image name if neither /out or /def set it.2446  if (config->outputFile.empty()) {2447    config->outputFile = getOutputPath(2448        (*args.filtered(OPT_INPUT, OPT_wholearchive_file).begin())->getValue(),2449        config->dll, config->driver);2450  }2451 2452  // Fail early if an output file is not writable.2453  if (auto e = tryCreateFile(config->outputFile)) {2454    Err(ctx) << "cannot open output file " << config->outputFile << ": "2455             << e.message();2456    return;2457  }2458 2459  config->lldmapFile = getMapFile(args, OPT_lldmap, OPT_lldmap_file);2460  config->mapFile = getMapFile(args, OPT_map, OPT_map_file);2461 2462  if (config->mapFile != "" && args.hasArg(OPT_map_info)) {2463    for (auto *arg : args.filtered(OPT_map_info)) {2464      std::string s = StringRef(arg->getValue()).lower();2465      if (s == "exports")2466        config->mapInfo = true;2467      else2468        Err(ctx) << "unknown option: /mapinfo:" << s;2469    }2470  }2471 2472  if (config->lldmapFile != "" && config->lldmapFile == config->mapFile) {2473    Warn(ctx) << "/lldmap and /map have the same output file '"2474              << config->mapFile << "'.\n>>> ignoring /lldmap";2475    config->lldmapFile.clear();2476  }2477 2478  // If should create PDB, use the hash of PDB content for build id. Otherwise,2479  // generate using the hash of executable content.2480  if (args.hasFlag(OPT_build_id, OPT_build_id_no, false))2481    config->buildIDHash = BuildIDHash::Binary;2482 2483  if (shouldCreatePDB) {2484    // Put the PDB next to the image if no /pdb flag was passed.2485    if (config->pdbPath.empty()) {2486      config->pdbPath = config->outputFile;2487      sys::path::replace_extension(config->pdbPath, ".pdb");2488    }2489 2490    // The embedded PDB path should be the absolute path to the PDB if no2491    // /pdbaltpath flag was passed.2492    if (config->pdbAltPath.empty()) {2493      config->pdbAltPath = config->pdbPath;2494 2495      // It's important to make the path absolute and remove dots.  This path2496      // will eventually be written into the PE header, and certain Microsoft2497      // tools won't work correctly if these assumptions are not held.2498      sys::fs::make_absolute(config->pdbAltPath);2499      sys::path::remove_dots(config->pdbAltPath);2500    } else {2501      // Don't do this earlier, so that ctx.OutputFile is ready.2502      parsePDBAltPath();2503    }2504    config->buildIDHash = BuildIDHash::PDB;2505  }2506 2507  // Set default image base if /base is not given.2508  if (config->imageBase == uint64_t(-1))2509    config->imageBase = getDefaultImageBase();2510 2511  ctx.forEachSymtab([&](SymbolTable &symtab) {2512    symtab.addSynthetic(symtab.mangle("__ImageBase"), nullptr);2513    if (symtab.machine == I386) {2514      symtab.addAbsolute("___safe_se_handler_table", 0);2515      symtab.addAbsolute("___safe_se_handler_count", 0);2516    }2517 2518    symtab.addAbsolute(symtab.mangle("__guard_fids_count"), 0);2519    symtab.addAbsolute(symtab.mangle("__guard_fids_table"), 0);2520    symtab.addAbsolute(symtab.mangle("__guard_flags"), 0);2521    symtab.addAbsolute(symtab.mangle("__guard_iat_count"), 0);2522    symtab.addAbsolute(symtab.mangle("__guard_iat_table"), 0);2523    symtab.addAbsolute(symtab.mangle("__guard_longjmp_count"), 0);2524    symtab.addAbsolute(symtab.mangle("__guard_longjmp_table"), 0);2525    // Needed for MSVC 2017 15.5 CRT.2526    symtab.addAbsolute(symtab.mangle("__enclave_config"), 0);2527    // Needed for MSVC 2019 16.8 CRT.2528    symtab.addAbsolute(symtab.mangle("__guard_eh_cont_count"), 0);2529    symtab.addAbsolute(symtab.mangle("__guard_eh_cont_table"), 0);2530 2531    if (symtab.isEC()) {2532      symtab.addAbsolute("__arm64x_extra_rfe_table", 0);2533      symtab.addAbsolute("__arm64x_extra_rfe_table_size", 0);2534      symtab.addAbsolute("__arm64x_redirection_metadata", 0);2535      symtab.addAbsolute("__arm64x_redirection_metadata_count", 0);2536      symtab.addAbsolute("__hybrid_auxiliary_delayload_iat_copy", 0);2537      symtab.addAbsolute("__hybrid_auxiliary_delayload_iat", 0);2538      symtab.addAbsolute("__hybrid_auxiliary_iat", 0);2539      symtab.addAbsolute("__hybrid_auxiliary_iat_copy", 0);2540      symtab.addAbsolute("__hybrid_code_map", 0);2541      symtab.addAbsolute("__hybrid_code_map_count", 0);2542      symtab.addAbsolute("__hybrid_image_info_bitfield", 0);2543      symtab.addAbsolute("__x64_code_ranges_to_entry_points", 0);2544      symtab.addAbsolute("__x64_code_ranges_to_entry_points_count", 0);2545      symtab.addSynthetic("__guard_check_icall_a64n_fptr", nullptr);2546      symtab.addSynthetic("__arm64x_native_entrypoint", nullptr);2547    }2548 2549    if (config->pseudoRelocs) {2550      symtab.addAbsolute(symtab.mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0);2551      symtab.addAbsolute(symtab.mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0);2552    }2553    if (config->mingw) {2554      symtab.addAbsolute(symtab.mangle("__CTOR_LIST__"), 0);2555      symtab.addAbsolute(symtab.mangle("__DTOR_LIST__"), 0);2556      symtab.addAbsolute("__data_start__", 0);2557      symtab.addAbsolute("__data_end__", 0);2558      symtab.addAbsolute("__bss_start__", 0);2559      symtab.addAbsolute("__bss_end__", 0);2560    }2561    if (config->debug || config->buildIDHash != BuildIDHash::None)2562      if (symtab.findUnderscore("__buildid"))2563        symtab.addUndefined(symtab.mangle("__buildid"));2564  });2565 2566  // This code may add new undefined symbols to the link, which may enqueue more2567  // symbol resolution tasks, so we need to continue executing tasks until we2568  // converge.2569  {2570    llvm::TimeTraceScope timeScope("Add unresolved symbols");2571    do {2572      ctx.forEachSymtab([&](SymbolTable &symtab) {2573        // Windows specific -- if entry point is not found,2574        // search for its mangled names.2575        if (symtab.entry)2576          symtab.mangleMaybe(symtab.entry);2577 2578        // Windows specific -- Make sure we resolve all dllexported symbols.2579        for (Export &e : symtab.exports) {2580          if (!e.forwardTo.empty())2581            continue;2582          e.sym = symtab.addGCRoot(e.name, !e.data);2583          if (e.source != ExportSource::Directives)2584            e.symbolName = symtab.mangleMaybe(e.sym);2585        }2586 2587        symtab.resolveAlternateNames();2588      });2589 2590      ctx.forEachActiveSymtab([&](SymbolTable &symtab) {2591        // If any inputs are bitcode files, the LTO code generator may create2592        // references to library functions that are not explicit in the bitcode2593        // file's symbol table. If any of those library functions are defined in2594        // a bitcode file in an archive member, we need to arrange to use LTO to2595        // compile those archive members by adding them to the link beforehand.2596        if (!symtab.bitcodeFileInstances.empty()) {2597          llvm::Triple TT(2598              symtab.bitcodeFileInstances.front()->obj->getTargetTriple());2599          for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT))2600            symtab.addLibcall(s);2601        }2602 2603        // Windows specific -- if __load_config_used can be resolved, resolve2604        // it.2605        if (symtab.findUnderscore("_load_config_used"))2606          symtab.addGCRoot(symtab.mangle("_load_config_used"));2607 2608        if (args.hasArg(OPT_include_optional)) {2609          // Handle /includeoptional2610          for (auto *arg : args.filtered(OPT_include_optional))2611            if (isa_and_nonnull<LazyArchive>(symtab.find(arg->getValue())))2612              symtab.addGCRoot(arg->getValue());2613        }2614      });2615    } while (run());2616  }2617 2618  // Handle /includeglob2619  for (StringRef pat : args::getStrings(args, OPT_incl_glob))2620    ctx.forEachActiveSymtab(2621        [&](SymbolTable &symtab) { symtab.addUndefinedGlob(pat); });2622 2623  // Create wrapped symbols for -wrap option.2624  ctx.forEachSymtab([&](SymbolTable &symtab) {2625    addWrappedSymbols(symtab, args);2626    // Load more object files that might be needed for wrapped symbols.2627    if (!symtab.wrapped.empty())2628      while (run())2629        ;2630  });2631 2632  if (config->autoImport || config->stdcallFixup) {2633    // MinGW specific.2634    // Load any further object files that might be needed for doing automatic2635    // imports, and do stdcall fixups.2636    //2637    // For cases with no automatically imported symbols, this iterates once2638    // over the symbol table and doesn't do anything.2639    //2640    // For the normal case with a few automatically imported symbols, this2641    // should only need to be run once, since each new object file imported2642    // is an import library and wouldn't add any new undefined references,2643    // but there's nothing stopping the __imp_ symbols from coming from a2644    // normal object file as well (although that won't be used for the2645    // actual autoimport later on). If this pass adds new undefined references,2646    // we won't iterate further to resolve them.2647    //2648    // If stdcall fixups only are needed for loading import entries from2649    // a DLL without import library, this also just needs running once.2650    // If it ends up pulling in more object files from static libraries,2651    // (and maybe doing more stdcall fixups along the way), this would need2652    // to loop these two calls.2653    ctx.forEachSymtab([](SymbolTable &symtab) { symtab.loadMinGWSymbols(); });2654    run();2655  }2656 2657  // At this point, we should not have any symbols that cannot be resolved.2658  // If we are going to do codegen for link-time optimization, check for2659  // unresolvable symbols first, so we don't spend time generating code that2660  // will fail to link anyway.2661  if (!config->forceUnresolved)2662    ctx.forEachSymtab([](SymbolTable &symtab) {2663      if (!symtab.bitcodeFileInstances.empty())2664        symtab.reportUnresolvable();2665    });2666  if (errorCount())2667    return;2668 2669  ctx.forEachSymtab([](SymbolTable &symtab) {2670    symtab.hadExplicitExports = !symtab.exports.empty();2671  });2672  if (config->mingw) {2673    // In MinGW, all symbols are automatically exported if no symbols2674    // are chosen to be exported.2675    maybeExportMinGWSymbols(args);2676  }2677 2678  // Do LTO by compiling bitcode input files to a set of native COFF files then2679  // link those files (unless -thinlto-index-only was given, in which case we2680  // resolve symbols and write indices, but don't generate native code or link).2681  ltoCompilationDone = true;2682  ctx.forEachSymtab([](SymbolTable &symtab) { symtab.compileBitcodeFiles(); });2683 2684  if (Defined *d =2685          dyn_cast_or_null<Defined>(ctx.symtab.findUnderscore("_tls_used")))2686    config->gcroot.push_back(d);2687 2688  // If -thinlto-index-only is given, we should create only "index2689  // files" and not object files. Index file creation is already done2690  // in addCombinedLTOObject, so we are done if that's the case.2691  // Likewise, don't emit object files for other /lldemit options.2692  if (config->emit != EmitKind::Obj || config->thinLTOIndexOnly)2693    return;2694 2695  // If we generated native object files from bitcode files, this resolves2696  // references to the symbols we use from them.2697  run();2698 2699  // Apply symbol renames for -wrap.2700  ctx.forEachSymtab([](SymbolTable &symtab) {2701    if (!symtab.wrapped.empty())2702      wrapSymbols(symtab);2703  });2704 2705  if (isArm64EC(config->machine))2706    createECExportThunks();2707 2708  // Resolve remaining undefined symbols and warn about imported locals.2709  std::vector<Undefined *> aliases;2710  ctx.forEachSymtab(2711      [&](SymbolTable &symtab) { symtab.resolveRemainingUndefines(aliases); });2712 2713  if (errorCount())2714    return;2715 2716  ctx.forEachActiveSymtab([](SymbolTable &symtab) {2717    symtab.initializeECThunks();2718    symtab.initializeLoadConfig();2719  });2720 2721  // Identify unreferenced COMDAT sections.2722  if (config->doGC) {2723    if (config->mingw) {2724      // markLive doesn't traverse .eh_frame, but the personality function is2725      // only reached that way. The proper solution would be to parse and2726      // traverse the .eh_frame section, like the ELF linker does.2727      // For now, just manually try to retain the known possible personality2728      // functions. This doesn't bring in more object files, but only marks2729      // functions that already have been included to be retained.2730      ctx.forEachSymtab([&](SymbolTable &symtab) {2731        for (const char *n : {"__gxx_personality_v0", "__gcc_personality_v0",2732                              "rust_eh_personality"}) {2733          Defined *d = dyn_cast_or_null<Defined>(symtab.findUnderscore(n));2734          if (d && !d->isGCRoot) {2735            d->isGCRoot = true;2736            config->gcroot.push_back(d);2737          }2738        }2739      });2740    }2741 2742    markLive(ctx);2743  }2744 2745  ctx.symtab.initializeSameAddressThunks();2746  for (auto alias : aliases) {2747    assert(alias->kind() == Symbol::UndefinedKind);2748    alias->resolveWeakAlias();2749  }2750 2751  if (config->mingw) {2752    // Make sure the crtend.o object is the last object file. This object2753    // file can contain terminating section chunks that need to be placed2754    // last. GNU ld processes files and static libraries explicitly in the2755    // order provided on the command line, while lld will pull in needed2756    // files from static libraries only after the last object file on the2757    // command line.2758    for (auto i = ctx.objFileInstances.begin(), e = ctx.objFileInstances.end();2759         i != e; i++) {2760      ObjFile *file = *i;2761      if (isCrtend(file->getName())) {2762        ctx.objFileInstances.erase(i);2763        ctx.objFileInstances.push_back(file);2764        break;2765      }2766    }2767  }2768 2769  // Windows specific -- when we are creating a .dll file, we also2770  // need to create a .lib file. In MinGW mode, we only do that when the2771  // -implib option is given explicitly, for compatibility with GNU ld.2772  if (config->dll || !ctx.symtab.exports.empty() ||2773      (ctx.config.machine == ARM64X && !ctx.hybridSymtab->exports.empty())) {2774    llvm::TimeTraceScope timeScope("Create .lib exports");2775    ctx.forEachActiveSymtab([](SymbolTable &symtab) { symtab.fixupExports(); });2776    if (!config->noimplib && (!config->mingw || !config->implib.empty()))2777      createImportLibrary(/*asLib=*/false);2778    ctx.forEachActiveSymtab(2779        [](SymbolTable &symtab) { symtab.assignExportOrdinals(); });2780  }2781 2782  // Handle /output-def (MinGW specific).2783  if (auto *arg = args.getLastArg(OPT_output_def))2784    writeDefFile(ctx, arg->getValue(), ctx.symtab.exports);2785 2786  // Set extra alignment for .comm symbols2787  ctx.forEachSymtab([&](SymbolTable &symtab) {2788    for (auto pair : symtab.alignComm) {2789      StringRef name = pair.first;2790      uint32_t alignment = pair.second;2791 2792      Symbol *sym = symtab.find(name);2793      if (!sym) {2794        Warn(ctx) << "/aligncomm symbol " << name << " not found";2795        continue;2796      }2797 2798      // If the symbol isn't common, it must have been replaced with a regular2799      // symbol, which will carry its own alignment.2800      auto *dc = dyn_cast<DefinedCommon>(sym);2801      if (!dc)2802        continue;2803 2804      CommonChunk *c = dc->getChunk();2805      c->setAlignment(std::max(c->getAlignment(), alignment));2806    }2807  });2808 2809  // Windows specific -- Create an embedded or side-by-side manifest.2810  // /manifestdependency: enables /manifest unless an explicit /manifest:no is2811  // also passed.2812  if (config->manifest == Configuration::Embed)2813    addBuffer(createManifestRes(), false, false);2814  else if (config->manifest == Configuration::SideBySide ||2815           (config->manifest == Configuration::Default &&2816            !config->manifestDependencies.empty()))2817    createSideBySideManifest();2818 2819  // Handle /order. We want to do this at this moment because we2820  // need a complete list of comdat sections to warn on nonexistent2821  // functions.2822  if (auto *arg = args.getLastArg(OPT_order)) {2823    if (args.hasArg(OPT_call_graph_ordering_file))2824      Err(ctx) << "/order and /call-graph-order-file may not be used together";2825    parseOrderFile(arg->getValue());2826    config->callGraphProfileSort = false;2827  }2828 2829  // Handle /call-graph-ordering-file and /call-graph-profile-sort (default on).2830  if (config->callGraphProfileSort) {2831    llvm::TimeTraceScope timeScope("Call graph");2832    if (auto *arg = args.getLastArg(OPT_call_graph_ordering_file))2833      parseCallGraphFile(arg->getValue());2834    else2835      readCallGraphsFromObjectFiles(ctx);2836  }2837 2838  // Handle /print-symbol-order.2839  if (auto *arg = args.getLastArg(OPT_print_symbol_order))2840    config->printSymbolOrder = arg->getValue();2841 2842  // Needs to happen after the last call to addFile().2843  convertResources();2844 2845  // Identify identical COMDAT sections to merge them.2846  if (config->doICF != ICFLevel::None) {2847    findKeepUniqueSections(ctx);2848    doICF(ctx);2849  }2850 2851  // Write the result.2852  writeResult(ctx);2853 2854  // Stop early so we can print the results.2855  rootTimer.stop();2856  if (config->showTiming)2857    ctx.rootTimer.print();2858 2859  if (config->timeTraceEnabled) {2860    // Manually stop the topmost "COFF link" scope, since we're shutting down.2861    timeTraceProfilerEnd();2862 2863    checkError(timeTraceProfilerWrite(2864        args.getLastArgValue(OPT_time_trace_eq).str(), config->outputFile));2865    timeTraceProfilerCleanup();2866  }2867}2868 2869} // namespace lld::coff2870