//===- Driver.cpp ---------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// The driver drives the entire linking process. It is responsible for
// parsing command line options and doing whatever it is instructed to do.
//
// One notable thing in the LLD's driver when compared to other linkers is
// that the LLD's driver is agnostic on the host operating system.
// Other linkers usually have implicit default values (such as a dynamic
// linker path or library paths) for each host OS.
//
// I don't think implicit default values are useful because they are
// usually explicitly specified by the compiler ctx.driver. They can even
// be harmful when you are doing cross-linking. Therefore, in LLD, we
// simply trust the compiler driver to pass all required options and
// don't try to make effort on our side.
//
//===----------------------------------------------------------------------===//

#include "Driver.h"
#include "Config.h"
#include "ICF.h"
#include "InputFiles.h"
#include "InputSection.h"
#include "LTO.h"
#include "LinkerScript.h"
#include "MarkLive.h"
#include "OutputSections.h"
#include "ScriptParser.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "Writer.h"
#include "lld/Common/Args.h"
#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Filesystem.h"
#include "lld/Common/Memory.h"
#include "lld/Common/Strings.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/IRObjectFile.h"
#include "llvm/Remarks/HotnessThresholdParser.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/GlobPattern.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/TarWriter.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <tuple>
#include <utility>

using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;
using namespace llvm::sys;
using namespace llvm::support;
using namespace lld;
using namespace lld::elf;

static void setConfigs(Ctx &ctx, opt::InputArgList &args);
static void readConfigs(Ctx &ctx, opt::InputArgList &args);

ELFSyncStream elf::Log(Ctx &ctx) { return {ctx, DiagLevel::Log}; }
ELFSyncStream elf::Msg(Ctx &ctx) { return {ctx, DiagLevel::Msg}; }
ELFSyncStream elf::Warn(Ctx &ctx) { return {ctx, DiagLevel::Warn}; }
ELFSyncStream elf::Err(Ctx &ctx) {
  return {ctx, ctx.arg.noinhibitExec ? DiagLevel::Warn : DiagLevel::Err};
}
ELFSyncStream elf::ErrAlways(Ctx &ctx) { return {ctx, DiagLevel::Err}; }
ELFSyncStream elf::Fatal(Ctx &ctx) { return {ctx, DiagLevel::Fatal}; }
uint64_t elf::errCount(Ctx &ctx) { return ctx.e.errorCount; }

ELFSyncStream elf::InternalErr(Ctx &ctx, const uint8_t *buf) {
  ELFSyncStream s(ctx, DiagLevel::Err);
  s << "internal linker error: ";
  return s;
}

Ctx::Ctx() : driver(*this) {}

llvm::raw_fd_ostream Ctx::openAuxiliaryFile(llvm::StringRef filename,
                                            std::error_code &ec) {
  using namespace llvm::sys::fs;
  OpenFlags flags =
      auxiliaryFiles.insert(filename).second ? OF_None : OF_Append;
  if (e.disableOutput && filename == "-") {
#ifdef _WIN32
    filename = "NUL";
#else
    filename = "/dev/null";
#endif
  }
  return {filename, ec, flags};
}

namespace lld {
namespace elf {
bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
          llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {
  // This driver-specific context will be freed later by unsafeLldMain().
  auto *context = new Ctx;
  Ctx &ctx = *context;

  context->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
  context->e.logName = args::getFilenameWithoutExe(args[0]);
  context->e.errorLimitExceededMsg =
      "too many errors emitted, stopping now (use "
      "--error-limit=0 to see all errors)";

  LinkerScript script(ctx);
  ctx.script = &script;
  ctx.symAux.emplace_back();
  ctx.symtab = std::make_unique<SymbolTable>(ctx);

  ctx.partitions.clear();
  ctx.partitions.emplace_back(ctx);

  ctx.arg.progName = args[0];

  ctx.driver.linkerMain(args);

  return errCount(ctx) == 0;
}
} // namespace elf
} // namespace lld

// Parses a linker -m option.
static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(Ctx &ctx,
                                                             StringRef emul) {
  uint8_t osabi = 0;
  StringRef s = emul;
  if (s.ends_with("_fbsd")) {
    s = s.drop_back(5);
    osabi = ELFOSABI_FREEBSD;
  }

  std::pair<ELFKind, uint16_t> ret =
      StringSwitch<std::pair<ELFKind, uint16_t>>(s)
          .Cases("aarch64elf", "aarch64linux", {ELF64LEKind, EM_AARCH64})
          .Cases("aarch64elfb", "aarch64linuxb", {ELF64BEKind, EM_AARCH64})
          .Cases("armelf", "armelf_linux_eabi", {ELF32LEKind, EM_ARM})
          .Cases("armelfb", "armelfb_linux_eabi", {ELF32BEKind, EM_ARM})
          .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64})
          .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS})
          .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS})
          .Case("elf32lriscv", {ELF32LEKind, EM_RISCV})
          .Cases("elf32ppc", "elf32ppclinux", {ELF32BEKind, EM_PPC})
          .Cases("elf32lppc", "elf32lppclinux", {ELF32LEKind, EM_PPC})
          .Case("elf32loongarch", {ELF32LEKind, EM_LOONGARCH})
          .Case("elf64btsmip", {ELF64BEKind, EM_MIPS})
          .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS})
          .Case("elf64lriscv", {ELF64LEKind, EM_RISCV})
          .Case("elf64ppc", {ELF64BEKind, EM_PPC64})
          .Case("elf64lppc", {ELF64LEKind, EM_PPC64})
          .Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64})
          .Case("elf_i386", {ELF32LEKind, EM_386})
          .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU})
          .Case("elf64_sparc", {ELF64BEKind, EM_SPARCV9})
          .Case("msp430elf", {ELF32LEKind, EM_MSP430})
          .Case("elf64_amdgpu", {ELF64LEKind, EM_AMDGPU})
          .Case("elf64loongarch", {ELF64LEKind, EM_LOONGARCH})
          .Case("elf64_s390", {ELF64BEKind, EM_S390})
          .Case("hexagonelf", {ELF32LEKind, EM_HEXAGON})
          .Default({ELFNoneKind, EM_NONE});

  if (ret.first == ELFNoneKind)
    ErrAlways(ctx) << "unknown emulation: " << emul;
  if (ret.second == EM_MSP430)
    osabi = ELFOSABI_STANDALONE;
  else if (ret.second == EM_AMDGPU)
    osabi = ELFOSABI_AMDGPU_HSA;
  return std::make_tuple(ret.first, ret.second, osabi);
}

// Returns slices of MB by parsing MB as an archive file.
// Each slice consists of a member file in the archive.
std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers(
    Ctx &ctx, MemoryBufferRef mb) {
  std::unique_ptr<Archive> file =
      CHECK(Archive::create(mb),
            mb.getBufferIdentifier() + ": failed to parse archive");

  std::vector<std::pair<MemoryBufferRef, uint64_t>> v;
  Error err = Error::success();
  bool addToTar = file->isThin() && ctx.tar;
  for (const Archive::Child &c : file->children(err)) {
    MemoryBufferRef mbref =
        CHECK(c.getMemoryBufferRef(),
              mb.getBufferIdentifier() +
                  ": could not get the buffer for a child of the archive");
    if (addToTar)
      ctx.tar->append(relativeToRoot(check(c.getFullName())),
                      mbref.getBuffer());
    v.push_back(std::make_pair(mbref, c.getChildOffset()));
  }
  if (err)
    Fatal(ctx) << mb.getBufferIdentifier()
               << ": Archive::children failed: " << std::move(err);

  // Take ownership of memory buffers created for members of thin archives.
  std::vector<std::unique_ptr<MemoryBuffer>> mbs = file->takeThinBuffers();
  std::move(mbs.begin(), mbs.end(), std::back_inserter(ctx.memoryBuffers));

  return v;
}

static bool isBitcode(MemoryBufferRef mb) {
  return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode;
}

bool LinkerDriver::tryAddFatLTOFile(MemoryBufferRef mb, StringRef archiveName,
                                    uint64_t offsetInArchive, bool lazy) {
  if (!ctx.arg.fatLTOObjects)
    return false;
  Expected<MemoryBufferRef> fatLTOData =
      IRObjectFile::findBitcodeInMemBuffer(mb);
  if (errorToBool(fatLTOData.takeError()))
    return false;
  files.push_back(std::make_unique<BitcodeFile>(ctx, *fatLTOData, archiveName,
                                                offsetInArchive, lazy));
  return true;
}

// Opens a file and create a file object. Path has to be resolved already.
void LinkerDriver::addFile(StringRef path, bool withLOption) {
  using namespace sys::fs;

  std::optional<MemoryBufferRef> buffer = readFile(ctx, path);
  if (!buffer)
    return;
  MemoryBufferRef mbref = *buffer;

  if (ctx.arg.formatBinary) {
    files.push_back(std::make_unique<BinaryFile>(ctx, mbref));
    return;
  }

  switch (identify_magic(mbref.getBuffer())) {
  case file_magic::unknown:
    readLinkerScript(ctx, mbref);
    return;
  case file_magic::archive: {
    auto members = getArchiveMembers(ctx, mbref);
    if (inWholeArchive) {
      for (const std::pair<MemoryBufferRef, uint64_t> &p : members) {
        if (isBitcode(p.first))
          files.push_back(std::make_unique<BitcodeFile>(ctx, p.first, path,
                                                        p.second, false));
        else if (!tryAddFatLTOFile(p.first, path, p.second, false))
          files.push_back(createObjFile(ctx, p.first, path));
      }
      return;
    }

    archiveFiles.emplace_back(path, members.size());

    // Handle archives and --start-lib/--end-lib using the same code path. This
    // scans all the ELF relocatable object files and bitcode files in the
    // archive rather than just the index file, with the benefit that the
    // symbols are only loaded once. For many projects archives see high
    // utilization rates and it is a net performance win. --start-lib scans
    // symbols in the same order that llvm-ar adds them to the index, so in the
    // common case the semantics are identical. If the archive symbol table was
    // created in a different order, or is incomplete, this strategy has
    // different semantics. Such output differences are considered user error.
    //
    // All files within the archive get the same group ID to allow mutual
    // references for --warn-backrefs.
    SaveAndRestore saved(isInGroup, true);
    for (const std::pair<MemoryBufferRef, uint64_t> &p : members) {
      auto magic = identify_magic(p.first.getBuffer());
      if (magic == file_magic::elf_relocatable) {
        if (!tryAddFatLTOFile(p.first, path, p.second, true))
          files.push_back(createObjFile(ctx, p.first, path, true));
      } else if (magic == file_magic::bitcode)
        files.push_back(
            std::make_unique<BitcodeFile>(ctx, p.first, path, p.second, true));
      else
        Warn(ctx) << path << ": archive member '"
                  << p.first.getBufferIdentifier()
                  << "' is neither ET_REL nor LLVM bitcode";
    }
    if (!saved.get())
      ++nextGroupId;
    return;
  }
  case file_magic::elf_shared_object: {
    if (ctx.arg.isStatic) {
      ErrAlways(ctx) << "attempted static link of dynamic object " << path;
      return;
    }

    // Shared objects are identified by soname. soname is (if specified)
    // DT_SONAME and falls back to filename. If a file was specified by -lfoo,
    // the directory part is ignored. Note that path may be a temporary and
    // cannot be stored into SharedFile::soName.
    path = mbref.getBufferIdentifier();
    auto f = std::make_unique<SharedFile>(
        ctx, mbref, withLOption ? path::filename(path) : path);
    f->init();
    files.push_back(std::move(f));
    return;
  }
  case file_magic::bitcode:
    files.push_back(std::make_unique<BitcodeFile>(ctx, mbref, "", 0, inLib));
    break;
  case file_magic::elf_relocatable:
    if (!tryAddFatLTOFile(mbref, "", 0, inLib))
      files.push_back(createObjFile(ctx, mbref, "", inLib));
    break;
  default:
    ErrAlways(ctx) << path << ": unknown file type";
  }
}

// Add a given library by searching it from input search paths.
void LinkerDriver::addLibrary(StringRef name) {
  if (std::optional<std::string> path = searchLibrary(ctx, name))
    addFile(ctx.saver.save(*path), /*withLOption=*/true);
  else
    ctx.e.error("unable to find library -l" + name, ErrorTag::LibNotFound,
                {name});
}

// This function is called on startup. We need this for LTO since
// LTO calls LLVM functions to compile bitcode files to native code.
// Technically this can be delayed until we read bitcode files, but
// we don't bother to do lazily because the initialization is fast.
static void initLLVM() {
  InitializeAllTargets();
  InitializeAllTargetMCs();
  InitializeAllAsmPrinters();
  InitializeAllAsmParsers();
}

// Some command line options or some combinations of them are not allowed.
// This function checks for such errors.
static void checkOptions(Ctx &ctx) {
  // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup
  // table which is a relatively new feature.
  if (ctx.arg.emachine == EM_MIPS && ctx.arg.gnuHash)
    ErrAlways(ctx)
        << "the .gnu.hash section is not compatible with the MIPS target";

  if (ctx.arg.emachine == EM_ARM) {
    if (!ctx.arg.cmseImplib) {
      if (!ctx.arg.cmseInputLib.empty())
        ErrAlways(ctx) << "--in-implib may not be used without --cmse-implib";
      if (!ctx.arg.cmseOutputLib.empty())
        ErrAlways(ctx) << "--out-implib may not be used without --cmse-implib";
    }
    if (ctx.arg.fixCortexA8 && !ctx.arg.isLE)
      ErrAlways(ctx)
          << "--fix-cortex-a8 is not supported on big endian targets";
  } else {
    if (ctx.arg.cmseImplib)
      ErrAlways(ctx) << "--cmse-implib is only supported on ARM targets";
    if (!ctx.arg.cmseInputLib.empty())
      ErrAlways(ctx) << "--in-implib is only supported on ARM targets";
    if (!ctx.arg.cmseOutputLib.empty())
      ErrAlways(ctx) << "--out-implib is only supported on ARM targets";
    if (ctx.arg.fixCortexA8)
      ErrAlways(ctx) << "--fix-cortex-a8 is only supported on ARM targets";
    if (ctx.arg.armBe8)
      ErrAlways(ctx) << "--be8 is only supported on ARM targets";
  }

  if (ctx.arg.emachine != EM_AARCH64) {
    if (ctx.arg.executeOnly)
      ErrAlways(ctx) << "--execute-only is only supported on AArch64 targets";
    if (ctx.arg.fixCortexA53Errata843419)
      ErrAlways(ctx) << "--fix-cortex-a53-843419 is only supported on AArch64";
    if (ctx.arg.zPacPlt)
      ErrAlways(ctx) << "-z pac-plt only supported on AArch64";
    if (ctx.arg.zForceBti)
      ErrAlways(ctx) << "-z force-bti only supported on AArch64";
    if (ctx.arg.zBtiReport != ReportPolicy::None)
      ErrAlways(ctx) << "-z bti-report only supported on AArch64";
    if (ctx.arg.zPauthReport != ReportPolicy::None)
      ErrAlways(ctx) << "-z pauth-report only supported on AArch64";
    if (ctx.arg.zGcsReport != ReportPolicy::None)
      ErrAlways(ctx) << "-z gcs-report only supported on AArch64";
    if (ctx.arg.zGcsReportDynamic != ReportPolicy::None)
      ErrAlways(ctx) << "-z gcs-report-dynamic only supported on AArch64";
    if (ctx.arg.zGcs != GcsPolicy::Implicit)
      ErrAlways(ctx) << "-z gcs only supported on AArch64";
  }

  if (ctx.arg.emachine != EM_AARCH64 && ctx.arg.emachine != EM_ARM &&
      ctx.arg.zExecuteOnlyReport != ReportPolicy::None)
    ErrAlways(ctx)
        << "-z execute-only-report only supported on AArch64 and ARM";

  if (ctx.arg.emachine != EM_PPC64) {
    if (ctx.arg.tocOptimize)
      ErrAlways(ctx) << "--toc-optimize is only supported on PowerPC64 targets";
    if (ctx.arg.pcRelOptimize)
      ErrAlways(ctx)
          << "--pcrel-optimize is only supported on PowerPC64 targets";
  }

  if (ctx.arg.emachine != EM_RISCV) {
    if (ctx.arg.relaxGP)
      ErrAlways(ctx) << "--relax-gp is only supported on RISC-V targets";
    if (ctx.arg.zZicfilpUnlabeledReport != ReportPolicy::None)
      ErrAlways(ctx) << "-z zicfilip-unlabeled-report is only supported on "
                        "RISC-V targets";
    if (ctx.arg.zZicfilpFuncSigReport != ReportPolicy::None)
      ErrAlways(ctx) << "-z zicfilip-func-sig-report is only supported on "
                        "RISC-V targets";
    if (ctx.arg.zZicfissReport != ReportPolicy::None)
      ErrAlways(ctx) << "-z zicfiss-report is only supported on RISC-V targets";
    if (ctx.arg.zZicfilp != ZicfilpPolicy::Implicit)
      ErrAlways(ctx) << "-z zicfilp is only supported on RISC-V targets";
    if (ctx.arg.zZicfiss != ZicfissPolicy::Implicit)
      ErrAlways(ctx) << "-z zicfiss is only supported on RISC-V targets";
  }

  if (ctx.arg.emachine != EM_386 && ctx.arg.emachine != EM_X86_64 &&
      ctx.arg.zCetReport != ReportPolicy::None)
    ErrAlways(ctx) << "-z cet-report only supported on X86 and X86_64";

  if (ctx.arg.pie && ctx.arg.shared)
    ErrAlways(ctx) << "-shared and -pie may not be used together";

  if (!ctx.arg.shared && !ctx.arg.filterList.empty())
    ErrAlways(ctx) << "-F may not be used without -shared";

  if (!ctx.arg.shared && !ctx.arg.auxiliaryList.empty())
    ErrAlways(ctx) << "-f may not be used without -shared";

  if (ctx.arg.strip == StripPolicy::All && ctx.arg.emitRelocs)
    ErrAlways(ctx) << "--strip-all and --emit-relocs may not be used together";

  if (ctx.arg.zText && ctx.arg.zIfuncNoplt)
    ErrAlways(ctx) << "-z text and -z ifunc-noplt may not be used together";

  if (ctx.arg.relocatable) {
    if (ctx.arg.shared)
      ErrAlways(ctx) << "-r and -shared may not be used together";
    if (ctx.arg.gdbIndex)
      ErrAlways(ctx) << "-r and --gdb-index may not be used together";
    if (ctx.arg.icf != ICFLevel::None)
      ErrAlways(ctx) << "-r and --icf may not be used together";
    if (ctx.arg.pie)
      ErrAlways(ctx) << "-r and -pie may not be used together";
    if (ctx.arg.exportDynamic)
      ErrAlways(ctx) << "-r and --export-dynamic may not be used together";
    if (ctx.arg.debugNames)
      ErrAlways(ctx) << "-r and --debug-names may not be used together";
    if (!ctx.arg.zSectionHeader)
      ErrAlways(ctx) << "-r and -z nosectionheader may not be used together";
  }

  if (ctx.arg.executeOnly) {
    if (ctx.arg.singleRoRx && !ctx.script->hasSectionsCommand)
      ErrAlways(ctx)
          << "--execute-only and --no-rosegment cannot be used together";
  }

  if (ctx.arg.zRetpolineplt && ctx.arg.zForceIbt)
    ErrAlways(ctx) << "-z force-ibt may not be used with -z retpolineplt";
}

static const char *getReproduceOption(opt::InputArgList &args) {
  if (auto *arg = args.getLastArg(OPT_reproduce))
    return arg->getValue();
  return getenv("LLD_REPRODUCE");
}

static bool hasZOption(opt::InputArgList &args, StringRef key) {
  bool ret = false;
  for (auto *arg : args.filtered(OPT_z))
    if (key == arg->getValue()) {
      ret = true;
      arg->claim();
    }
  return ret;
}

static bool getZFlag(opt::InputArgList &args, StringRef k1, StringRef k2,
                     bool defaultValue) {
  for (auto *arg : args.filtered(OPT_z)) {
    StringRef v = arg->getValue();
    if (k1 == v)
      defaultValue = true;
    else if (k2 == v)
      defaultValue = false;
    else
      continue;
    arg->claim();
  }
  return defaultValue;
}

static SeparateSegmentKind getZSeparate(opt::InputArgList &args) {
  auto ret = SeparateSegmentKind::None;
  for (auto *arg : args.filtered(OPT_z)) {
    StringRef v = arg->getValue();
    if (v == "noseparate-code")
      ret = SeparateSegmentKind::None;
    else if (v == "separate-code")
      ret = SeparateSegmentKind::Code;
    else if (v == "separate-loadable-segments")
      ret = SeparateSegmentKind::Loadable;
    else
      continue;
    arg->claim();
  }
  return ret;
}

static GnuStackKind getZGnuStack(opt::InputArgList &args) {
  auto ret = GnuStackKind::NoExec;
  for (auto *arg : args.filtered(OPT_z)) {
    StringRef v = arg->getValue();
    if (v == "execstack")
      ret = GnuStackKind::Exec;
    else if (v == "noexecstack")
      ret = GnuStackKind::NoExec;
    else if (v == "nognustack")
      ret = GnuStackKind::None;
    else
      continue;
    arg->claim();
  }
  return ret;
}

static uint8_t getZStartStopVisibility(Ctx &ctx, opt::InputArgList &args) {
  uint8_t ret = STV_PROTECTED;
  for (auto *arg : args.filtered(OPT_z)) {
    std::pair<StringRef, StringRef> kv = StringRef(arg->getValue()).split('=');
    if (kv.first == "start-stop-visibility") {
      arg->claim();
      if (kv.second == "default")
        ret = STV_DEFAULT;
      else if (kv.second == "internal")
        ret = STV_INTERNAL;
      else if (kv.second == "hidden")
        ret = STV_HIDDEN;
      else if (kv.second == "protected")
        ret = STV_PROTECTED;
      else
        ErrAlways(ctx) << "unknown -z start-stop-visibility= value: "
                       << StringRef(kv.second);
    }
  }
  return ret;
}

static GcsPolicy getZGcs(Ctx &ctx, opt::InputArgList &args) {
  GcsPolicy ret = GcsPolicy::Implicit;
  for (auto *arg : args.filtered(OPT_z)) {
    std::pair<StringRef, StringRef> kv = StringRef(arg->getValue()).split('=');
    if (kv.first == "gcs") {
      arg->claim();
      if (kv.second == "implicit")
        ret = GcsPolicy::Implicit;
      else if (kv.second == "never")
        ret = GcsPolicy::Never;
      else if (kv.second == "always")
        ret = GcsPolicy::Always;
      else
        ErrAlways(ctx) << "unknown -z gcs= value: " << kv.second;
    }
  }
  return ret;
}

static ZicfilpPolicy getZZicfilp(Ctx &ctx, opt::InputArgList &args) {
  auto ret = ZicfilpPolicy::Implicit;
  for (auto *arg : args.filtered(OPT_z)) {
    std::pair<StringRef, StringRef> kv = StringRef(arg->getValue()).split('=');
    if (kv.first == "zicfilp") {
      arg->claim();
      if (kv.second == "unlabeled")
        ret = ZicfilpPolicy::Unlabeled;
      else if (kv.second == "func-sig")
        ret = ZicfilpPolicy::FuncSig;
      else if (kv.second == "never")
        ret = ZicfilpPolicy::Never;
      else if (kv.second == "implicit")
        ret = ZicfilpPolicy::Implicit;
      else
        ErrAlways(ctx) << "unknown -z zicfilp= value: " << kv.second;
    }
  }
  return ret;
}

static ZicfissPolicy getZZicfiss(Ctx &ctx, opt::InputArgList &args) {
  auto ret = ZicfissPolicy::Implicit;
  for (auto *arg : args.filtered(OPT_z)) {
    std::pair<StringRef, StringRef> kv = StringRef(arg->getValue()).split('=');
    if (kv.first == "zicfiss") {
      arg->claim();
      if (kv.second == "always")
        ret = ZicfissPolicy::Always;
      else if (kv.second == "never")
        ret = ZicfissPolicy::Never;
      else if (kv.second == "implicit")
        ret = ZicfissPolicy::Implicit;
      else
        ErrAlways(ctx) << "unknown -z zicfiss= value: " << kv.second;
    }
  }
  return ret;
}

// Report a warning for an unknown -z option.
static void checkZOptions(Ctx &ctx, opt::InputArgList &args) {
  // This function is called before getTarget(), when certain options are not
  // initialized yet. Claim them here.
  args::getZOptionValue(args, OPT_z, "max-page-size", 0);
  args::getZOptionValue(args, OPT_z, "common-page-size", 0);
  getZFlag(args, "rel", "rela", false);
  getZFlag(args, "dynamic-undefined-weak", "nodynamic-undefined-weak", false);
  for (auto *arg : args.filtered(OPT_z))
    if (!arg->isClaimed())
      Warn(ctx) << "unknown -z value: " << StringRef(arg->getValue());
}

constexpr const char *saveTempsValues[] = {
    "resolution", "preopt",     "promote", "internalize",  "import",
    "opt",        "precodegen", "prelink", "combinedindex"};

LinkerDriver::LinkerDriver(Ctx &ctx) : ctx(ctx) {}

void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
  ELFOptTable parser;
  opt::InputArgList args = parser.parse(ctx, argsArr.slice(1));

  // Interpret these flags early because Err/Warn depend on them.
  ctx.e.errorLimit = args::getInteger(args, OPT_error_limit, 20);
  ctx.e.fatalWarnings =
      args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false) &&
      !args.hasArg(OPT_no_warnings);
  ctx.e.suppressWarnings = args.hasArg(OPT_no_warnings);

  // Handle -help
  if (args.hasArg(OPT_help)) {
    printHelp(ctx);
    return;
  }

  // Handle -v or -version.
  //
  // A note about "compatible with GNU linkers" message: this is a hack for
  // scripts generated by GNU Libtool up to 2021-10 to recognize LLD as
  // a GNU compatible linker. See
  // <https://lists.gnu.org/archive/html/libtool/2017-01/msg00007.html>.
  //
  // This is somewhat ugly hack, but in reality, we had no choice other
  // than doing this. Considering the very long release cycle of Libtool,
  // it is not easy to improve it to recognize LLD as a GNU compatible
  // linker in a timely manner. Even if we can make it, there are still a
  // lot of "configure" scripts out there that are generated by old version
  // of Libtool. We cannot convince every software developer to migrate to
  // the latest version and re-generate scripts. So we have this hack.
  if (args.hasArg(OPT_v) || args.hasArg(OPT_version))
    Msg(ctx) << getLLDVersion() << " (compatible with GNU linkers)";

  if (const char *path = getReproduceOption(args)) {
    // Note that --reproduce is a debug option so you can ignore it
    // if you are trying to understand the whole picture of the code.
    Expected<std::unique_ptr<TarWriter>> errOrWriter =
        TarWriter::create(path, path::stem(path));
    if (errOrWriter) {
      ctx.tar = std::move(*errOrWriter);
      ctx.tar->append("response.txt", createResponseFile(args));
      ctx.tar->append("version.txt", getLLDVersion() + "\n");
      StringRef ltoSampleProfile = args.getLastArgValue(OPT_lto_sample_profile);
      if (!ltoSampleProfile.empty())
        readFile(ctx, ltoSampleProfile);
    } else {
      ErrAlways(ctx) << "--reproduce: " << errOrWriter.takeError();
    }
  }

  readConfigs(ctx, args);
  checkZOptions(ctx, args);

  // The behavior of -v or --version is a bit strange, but this is
  // needed for compatibility with GNU linkers.
  if (args.hasArg(OPT_v) && !args.hasArg(OPT_INPUT))
    return;
  if (args.hasArg(OPT_version))
    return;

  // Initialize time trace profiler.
  if (ctx.arg.timeTraceEnabled)
    timeTraceProfilerInitialize(ctx.arg.timeTraceGranularity, ctx.arg.progName);

  {
    llvm::TimeTraceScope timeScope("ExecuteLinker");

    initLLVM();
    createFiles(args);
    if (errCount(ctx))
      return;

    inferMachineType();
    setConfigs(ctx, args);
    checkOptions(ctx);
    if (errCount(ctx))
      return;

    invokeELFT(link, args);
  }

  if (ctx.arg.timeTraceEnabled) {
    checkError(ctx.e, timeTraceProfilerWrite(
                          args.getLastArgValue(OPT_time_trace_eq).str(),
                          ctx.arg.outputFile));
    timeTraceProfilerCleanup();
  }
}

static std::string getRpath(opt::InputArgList &args) {
  SmallVector<StringRef, 0> v = args::getStrings(args, OPT_rpath);
  return llvm::join(v.begin(), v.end(), ":");
}

// Determines what we should do if there are remaining unresolved
// symbols after the name resolution.
static void setUnresolvedSymbolPolicy(Ctx &ctx, opt::InputArgList &args) {
  UnresolvedPolicy errorOrWarn = args.hasFlag(OPT_error_unresolved_symbols,
                                              OPT_warn_unresolved_symbols, true)
                                     ? UnresolvedPolicy::ReportError
                                     : UnresolvedPolicy::Warn;
  // -shared implies --unresolved-symbols=ignore-all because missing
  // symbols are likely to be resolved at runtime.
  bool diagRegular = !ctx.arg.shared, diagShlib = !ctx.arg.shared;

  for (const opt::Arg *arg : args) {
    switch (arg->getOption().getID()) {
    case OPT_unresolved_symbols: {
      StringRef s = arg->getValue();
      if (s == "ignore-all") {
        diagRegular = false;
        diagShlib = false;
      } else if (s == "ignore-in-object-files") {
        diagRegular = false;
        diagShlib = true;
      } else if (s == "ignore-in-shared-libs") {
        diagRegular = true;
        diagShlib = false;
      } else if (s == "report-all") {
        diagRegular = true;
        diagShlib = true;
      } else {
        ErrAlways(ctx) << "unknown --unresolved-symbols value: " << s;
      }
      break;
    }
    case OPT_no_undefined:
      diagRegular = true;
      break;
    case OPT_z:
      if (StringRef(arg->getValue()) == "defs")
        diagRegular = true;
      else if (StringRef(arg->getValue()) == "undefs")
        diagRegular = false;
      else
        break;
      arg->claim();
      break;
    case OPT_allow_shlib_undefined:
      diagShlib = false;
      break;
    case OPT_no_allow_shlib_undefined:
      diagShlib = true;
      break;
    }
  }

  ctx.arg.unresolvedSymbols =
      diagRegular ? errorOrWarn : UnresolvedPolicy::Ignore;
  ctx.arg.unresolvedSymbolsInShlib =
      diagShlib ? errorOrWarn : UnresolvedPolicy::Ignore;
}

static Target2Policy getTarget2(Ctx &ctx, opt::InputArgList &args) {
  StringRef s = args.getLastArgValue(OPT_target2, "got-rel");
  if (s == "rel")
    return Target2Policy::Rel;
  if (s == "abs")
    return Target2Policy::Abs;
  if (s == "got-rel")
    return Target2Policy::GotRel;
  ErrAlways(ctx) << "unknown --target2 option: " << s;
  return Target2Policy::GotRel;
}

static bool isOutputFormatBinary(Ctx &ctx, opt::InputArgList &args) {
  StringRef s = args.getLastArgValue(OPT_oformat, "elf");
  if (s == "binary")
    return true;
  if (!s.starts_with("elf"))
    ErrAlways(ctx) << "unknown --oformat value: " << s;
  return false;
}

static DiscardPolicy getDiscard(opt::InputArgList &args) {
  auto *arg =
      args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none);
  if (!arg)
    return DiscardPolicy::Default;
  if (arg->getOption().getID() == OPT_discard_all)
    return DiscardPolicy::All;
  if (arg->getOption().getID() == OPT_discard_locals)
    return DiscardPolicy::Locals;
  return DiscardPolicy::None;
}

static StringRef getDynamicLinker(Ctx &ctx, opt::InputArgList &args) {
  auto *arg = args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker);
  if (!arg)
    return "";
  if (arg->getOption().getID() == OPT_no_dynamic_linker)
    return "";
  return arg->getValue();
}

static int getMemtagMode(Ctx &ctx, opt::InputArgList &args) {
  StringRef memtagModeArg = args.getLastArgValue(OPT_android_memtag_mode);
  if (memtagModeArg.empty()) {
    if (ctx.arg.androidMemtagStack)
      Warn(ctx) << "--android-memtag-mode is unspecified, leaving "
                   "--android-memtag-stack a no-op";
    else if (ctx.arg.androidMemtagHeap)
      Warn(ctx) << "--android-memtag-mode is unspecified, leaving "
                   "--android-memtag-heap a no-op";
    return ELF::NT_MEMTAG_LEVEL_NONE;
  }

  if (memtagModeArg == "sync")
    return ELF::NT_MEMTAG_LEVEL_SYNC;
  if (memtagModeArg == "async")
    return ELF::NT_MEMTAG_LEVEL_ASYNC;
  if (memtagModeArg == "none")
    return ELF::NT_MEMTAG_LEVEL_NONE;

  ErrAlways(ctx) << "unknown --android-memtag-mode value: \"" << memtagModeArg
                 << "\", should be one of {async, sync, none}";
  return ELF::NT_MEMTAG_LEVEL_NONE;
}

static ICFLevel getICF(opt::InputArgList &args) {
  auto *arg = args.getLastArg(OPT_icf_none, OPT_icf_safe, OPT_icf_all);
  if (!arg || arg->getOption().getID() == OPT_icf_none)
    return ICFLevel::None;
  if (arg->getOption().getID() == OPT_icf_safe)
    return ICFLevel::Safe;
  return ICFLevel::All;
}

static void parsePackageMetadata(Ctx &ctx, const opt::Arg &arg) {
  unsigned c0, c1;
  SmallVector<uint8_t, 0> decoded;
  StringRef s = arg.getValue();
  for (size_t i = 0, e = s.size(); i != e; ++i) {
    if (s[i] != '%') {
      decoded.push_back(s[i]);
    } else if (i + 2 < e && (c1 = hexDigitValue(s[i + 1])) != -1u &&
               (c0 = hexDigitValue(s[i + 2])) != -1u) {
      decoded.push_back(uint8_t(c1 * 16 + c0));
      i += 2;
    } else {
      ErrAlways(ctx) << arg.getSpelling() << ": invalid % escape at byte " << i
                     << "; supports only %[0-9a-fA-F][0-9a-fA-F]";
      return;
    }
  }
  ctx.arg.packageMetadata = std::move(decoded);
}

static StripPolicy getStrip(Ctx &ctx, opt::InputArgList &args) {
  if (args.hasArg(OPT_relocatable))
    return StripPolicy::None;
  if (!ctx.arg.zSectionHeader)
    return StripPolicy::All;

  auto *arg = args.getLastArg(OPT_strip_all, OPT_strip_debug);
  if (!arg)
    return StripPolicy::None;
  if (arg->getOption().getID() == OPT_strip_all)
    return StripPolicy::All;
  return StripPolicy::Debug;
}

static uint64_t parseSectionAddress(Ctx &ctx, StringRef s,
                                    opt::InputArgList &args,
                                    const opt::Arg &arg) {
  uint64_t va = 0;
  s.consume_front("0x");
  if (!to_integer(s, va, 16))
    ErrAlways(ctx) << "invalid argument: " << arg.getAsString(args);
  return va;
}

static StringMap<uint64_t> getSectionStartMap(Ctx &ctx,
                                              opt::InputArgList &args) {
  StringMap<uint64_t> ret;
  for (auto *arg : args.filtered(OPT_section_start)) {
    StringRef name;
    StringRef addr;
    std::tie(name, addr) = StringRef(arg->getValue()).split('=');
    ret[name] = parseSectionAddress(ctx, addr, args, *arg);
  }

  if (auto *arg = args.getLastArg(OPT_Ttext))
    ret[".text"] = parseSectionAddress(ctx, arg->getValue(), args, *arg);
  if (auto *arg = args.getLastArg(OPT_Tdata))
    ret[".data"] = parseSectionAddress(ctx, arg->getValue(), args, *arg);
  if (auto *arg = args.getLastArg(OPT_Tbss))
    ret[".bss"] = parseSectionAddress(ctx, arg->getValue(), args, *arg);
  return ret;
}

static SortSectionPolicy getSortSection(Ctx &ctx, opt::InputArgList &args) {
  StringRef s = args.getLastArgValue(OPT_sort_section);
  if (s == "alignment")
    return SortSectionPolicy::Alignment;
  if (s == "name")
    return SortSectionPolicy::Name;
  if (!s.empty())
    ErrAlways(ctx) << "unknown --sort-section rule: " << s;
  return SortSectionPolicy::Default;
}

static OrphanHandlingPolicy getOrphanHandling(Ctx &ctx,
                                              opt::InputArgList &args) {
  StringRef s = args.getLastArgValue(OPT_orphan_handling, "place");
  if (s == "warn")
    return OrphanHandlingPolicy::Warn;
  if (s == "error")
    return OrphanHandlingPolicy::Error;
  if (s != "place")
    ErrAlways(ctx) << "unknown --orphan-handling mode: " << s;
  return OrphanHandlingPolicy::Place;
}

// Parse --build-id or --build-id=<style>. We handle "tree" as a
// synonym for "sha1" because all our hash functions including
// --build-id=sha1 are actually tree hashes for performance reasons.
static std::pair<BuildIdKind, SmallVector<uint8_t, 0>>
getBuildId(Ctx &ctx, opt::InputArgList &args) {
  auto *arg = args.getLastArg(OPT_build_id);
  if (!arg)
    return {BuildIdKind::None, {}};

  StringRef s = arg->getValue();
  if (s == "fast")
    return {BuildIdKind::Fast, {}};
  if (s == "md5")
    return {BuildIdKind::Md5, {}};
  if (s == "sha1" || s == "tree")
    return {BuildIdKind::Sha1, {}};
  if (s == "uuid")
    return {BuildIdKind::Uuid, {}};
  if (s.starts_with("0x"))
    return {BuildIdKind::Hexstring, parseHex(s.substr(2))};

  if (s != "none")
    ErrAlways(ctx) << "unknown --build-id style: " << s;
  return {BuildIdKind::None, {}};
}

static std::pair<bool, bool> getPackDynRelocs(Ctx &ctx,
                                              opt::InputArgList &args) {
  StringRef s = args.getLastArgValue(OPT_pack_dyn_relocs, "none");
  if (s == "android")
    return {true, false};
  if (s == "relr")
    return {false, true};
  if (s == "android+relr")
    return {true, true};

  if (s != "none")
    ErrAlways(ctx) << "unknown --pack-dyn-relocs format: " << s;
  return {false, false};
}

static void readCallGraph(Ctx &ctx, MemoryBufferRef mb) {
  // Build a map from symbol name to section
  DenseMap<StringRef, Symbol *> map;
  for (ELFFileBase *file : ctx.objectFiles)
    for (Symbol *sym : file->getSymbols())
      map[sym->getName()] = sym;

  auto findSection = [&](StringRef name) -> InputSectionBase * {
    Symbol *sym = map.lookup(name);
    if (!sym) {
      if (ctx.arg.warnSymbolOrdering)
        Warn(ctx) << mb.getBufferIdentifier() << ": no such symbol: " << name;
      return nullptr;
    }
    maybeWarnUnorderableSymbol(ctx, sym);

    if (Defined *dr = dyn_cast_or_null<Defined>(sym))
      return dyn_cast_or_null<InputSectionBase>(dr->section);
    return nullptr;
  };

  for (StringRef line : args::getLines(mb)) {
    SmallVector<StringRef, 3> fields;
    line.split(fields, ' ');
    uint64_t count;

    if (fields.size() != 3 || !to_integer(fields[2], count)) {
      ErrAlways(ctx) << mb.getBufferIdentifier() << ": parse error";
      return;
    }

    if (InputSectionBase *from = findSection(fields[0]))
      if (InputSectionBase *to = findSection(fields[1]))
        ctx.arg.callGraphProfile[std::make_pair(from, to)] += count;
  }
}

// If SHT_LLVM_CALL_GRAPH_PROFILE and its relocation section exist, returns
// true and populates cgProfile and symbolIndices.
template <class ELFT>
static bool
processCallGraphRelocations(Ctx &ctx, SmallVector<uint32_t, 32> &symbolIndices,
                            ArrayRef<typename ELFT::CGProfile> &cgProfile,
                            ObjFile<ELFT> *inputObj) {
  if (inputObj->cgProfileSectionIndex == SHN_UNDEF)
    return false;

  ArrayRef<Elf_Shdr_Impl<ELFT>> objSections =
      inputObj->template getELFShdrs<ELFT>();
  symbolIndices.clear();
  const ELFFile<ELFT> &obj = inputObj->getObj();
  cgProfile =
      check(obj.template getSectionContentsAsArray<typename ELFT::CGProfile>(
          objSections[inputObj->cgProfileSectionIndex]));

  for (size_t i = 0, e = objSections.size(); i < e; ++i) {
    const Elf_Shdr_Impl<ELFT> &sec = objSections[i];
    if (sec.sh_info == inputObj->cgProfileSectionIndex) {
      if (sec.sh_type == SHT_CREL) {
        auto crels =
            CHECK(obj.crels(sec), "could not retrieve cg profile rela section");
        for (const auto &rel : crels.first)
          symbolIndices.push_back(rel.getSymbol(false));
        for (const auto &rel : crels.second)
          symbolIndices.push_back(rel.getSymbol(false));
        break;
      }
      if (sec.sh_type == SHT_RELA) {
        ArrayRef<typename ELFT::Rela> relas =
            CHECK(obj.relas(sec), "could not retrieve cg profile rela section");
        for (const typename ELFT::Rela &rel : relas)
          symbolIndices.push_back(rel.getSymbol(ctx.arg.isMips64EL));
        break;
      }
      if (sec.sh_type == SHT_REL) {
        ArrayRef<typename ELFT::Rel> rels =
            CHECK(obj.rels(sec), "could not retrieve cg profile rel section");
        for (const typename ELFT::Rel &rel : rels)
          symbolIndices.push_back(rel.getSymbol(ctx.arg.isMips64EL));
        break;
      }
    }
  }
  if (symbolIndices.empty())
    Warn(ctx)
        << "SHT_LLVM_CALL_GRAPH_PROFILE exists, but relocation section doesn't";
  return !symbolIndices.empty();
}

template <class ELFT> static void readCallGraphsFromObjectFiles(Ctx &ctx) {
  SmallVector<uint32_t, 32> symbolIndices;
  ArrayRef<typename ELFT::CGProfile> cgProfile;
  for (auto file : ctx.objectFiles) {
    auto *obj = cast<ObjFile<ELFT>>(file);
    if (!processCallGraphRelocations(ctx, symbolIndices, cgProfile, obj))
      continue;

    if (symbolIndices.size() != cgProfile.size() * 2)
      Fatal(ctx) << "number of relocations doesn't match Weights";

    for (uint32_t i = 0, size = cgProfile.size(); i < size; ++i) {
      const Elf_CGProfile_Impl<ELFT> &cgpe = cgProfile[i];
      uint32_t fromIndex = symbolIndices[i * 2];
      uint32_t toIndex = symbolIndices[i * 2 + 1];
      auto *fromSym = dyn_cast<Defined>(&obj->getSymbol(fromIndex));
      auto *toSym = dyn_cast<Defined>(&obj->getSymbol(toIndex));
      if (!fromSym || !toSym)
        continue;

      auto *from = dyn_cast_or_null<InputSectionBase>(fromSym->section);
      auto *to = dyn_cast_or_null<InputSectionBase>(toSym->section);
      if (from && to)
        ctx.arg.callGraphProfile[{from, to}] += cgpe.cgp_weight;
    }
  }
}

template <class ELFT>
static void ltoValidateAllVtablesHaveTypeInfos(Ctx &ctx,
                                               opt::InputArgList &args) {
  DenseSet<StringRef> typeInfoSymbols;
  SmallSetVector<StringRef, 0> vtableSymbols;
  auto processVtableAndTypeInfoSymbols = [&](StringRef name) {
    if (name.consume_front("_ZTI"))
      typeInfoSymbols.insert(name);
    else if (name.consume_front("_ZTV"))
      vtableSymbols.insert(name);
  };

  // Examine all native symbol tables.
  for (ELFFileBase *f : ctx.objectFiles) {
    using Elf_Sym = typename ELFT::Sym;
    for (const Elf_Sym &s : f->template getGlobalELFSyms<ELFT>()) {
      if (s.st_shndx != SHN_UNDEF) {
        StringRef name = check(s.getName(f->getStringTable()));
        processVtableAndTypeInfoSymbols(name);
      }
    }
  }

  for (SharedFile *f : ctx.sharedFiles) {
    using Elf_Sym = typename ELFT::Sym;
    for (const Elf_Sym &s : f->template getELFSyms<ELFT>()) {
      if (s.st_shndx != SHN_UNDEF) {
        StringRef name = check(s.getName(f->getStringTable()));
        processVtableAndTypeInfoSymbols(name);
      }
    }
  }

  SmallSetVector<StringRef, 0> vtableSymbolsWithNoRTTI;
  for (StringRef s : vtableSymbols)
    if (!typeInfoSymbols.count(s))
      vtableSymbolsWithNoRTTI.insert(s);

  // Remove known safe symbols.
  for (auto *arg : args.filtered(OPT_lto_known_safe_vtables)) {
    StringRef knownSafeName = arg->getValue();
    if (!knownSafeName.consume_front("_ZTV"))
      ErrAlways(ctx)
          << "--lto-known-safe-vtables=: expected symbol to start with _ZTV, "
             "but got "
          << knownSafeName;
    Expected<GlobPattern> pat = GlobPattern::create(knownSafeName);
    if (!pat)
      ErrAlways(ctx) << "--lto-known-safe-vtables=: " << pat.takeError();
    vtableSymbolsWithNoRTTI.remove_if(
        [&](StringRef s) { return pat->match(s); });
  }

  ctx.ltoAllVtablesHaveTypeInfos = vtableSymbolsWithNoRTTI.empty();
  // Check for unmatched RTTI symbols
  for (StringRef s : vtableSymbolsWithNoRTTI) {
    Msg(ctx) << "--lto-validate-all-vtables-have-type-infos: RTTI missing for "
                "vtable "
                "_ZTV"
             << s << ", --lto-whole-program-visibility disabled";
  }
}

static CGProfileSortKind getCGProfileSortKind(Ctx &ctx,
                                              opt::InputArgList &args) {
  StringRef s = args.getLastArgValue(OPT_call_graph_profile_sort, "cdsort");
  if (s == "hfsort")
    return CGProfileSortKind::Hfsort;
  if (s == "cdsort")
    return CGProfileSortKind::Cdsort;
  if (s != "none")
    ErrAlways(ctx) << "unknown --call-graph-profile-sort= value: " << s;
  return CGProfileSortKind::None;
}

static void parseBPOrdererOptions(Ctx &ctx, opt::InputArgList &args) {
  if (auto *arg = args.getLastArg(OPT_bp_compression_sort)) {
    StringRef s = arg->getValue();
    if (s == "function") {
      ctx.arg.bpFunctionOrderForCompression = true;
    } else if (s == "data") {
      ctx.arg.bpDataOrderForCompression = true;
    } else if (s == "both") {
      ctx.arg.bpFunctionOrderForCompression = true;
      ctx.arg.bpDataOrderForCompression = true;
    } else if (s != "none") {
      ErrAlways(ctx) << arg->getSpelling()
                     << ": expected [none|function|data|both]";
    }
    if (s != "none" && args.hasArg(OPT_call_graph_ordering_file))
      ErrAlways(ctx) << "--bp-compression-sort is incompatible with "
                        "--call-graph-ordering-file";
  }
  if (auto *arg = args.getLastArg(OPT_bp_startup_sort)) {
    StringRef s = arg->getValue();
    if (s == "function") {
      ctx.arg.bpStartupFunctionSort = true;
    } else if (s != "none") {
      ErrAlways(ctx) << arg->getSpelling() << ": expected [none|function]";
    }
    if (s != "none" && args.hasArg(OPT_call_graph_ordering_file))
      ErrAlways(ctx) << "--bp-startup-sort=function is incompatible with "
                        "--call-graph-ordering-file";
  }

  ctx.arg.bpCompressionSortStartupFunctions =
      args.hasFlag(OPT_bp_compression_sort_startup_functions,
                   OPT_no_bp_compression_sort_startup_functions, false);
  ctx.arg.bpVerboseSectionOrderer = args.hasArg(OPT_verbose_bp_section_orderer);

  ctx.arg.irpgoProfilePath = args.getLastArgValue(OPT_irpgo_profile);
  if (ctx.arg.irpgoProfilePath.empty()) {
    if (ctx.arg.bpStartupFunctionSort)
      ErrAlways(ctx) << "--bp-startup-sort=function must be used with "
                        "--irpgo-profile";
    if (ctx.arg.bpCompressionSortStartupFunctions)
      ErrAlways(ctx)
          << "--bp-compression-sort-startup-functions must be used with "
             "--irpgo-profile";
  }
}

static DebugCompressionType getCompressionType(Ctx &ctx, StringRef s,
                                               StringRef option) {
  DebugCompressionType type = StringSwitch<DebugCompressionType>(s)
                                  .Case("zlib", DebugCompressionType::Zlib)
                                  .Case("zstd", DebugCompressionType::Zstd)
                                  .Default(DebugCompressionType::None);
  if (type == DebugCompressionType::None) {
    if (s != "none")
      ErrAlways(ctx) << "unknown " << option << " value: " << s;
  } else if (const char *reason = compression::getReasonIfUnsupported(
                 compression::formatFor(type))) {
    ErrAlways(ctx) << option << ": " << reason;
  }
  return type;
}

static StringRef getAliasSpelling(opt::Arg *arg) {
  if (const opt::Arg *alias = arg->getAlias())
    return alias->getSpelling();
  return arg->getSpelling();
}

static std::pair<StringRef, StringRef>
getOldNewOptions(Ctx &ctx, opt::InputArgList &args, unsigned id) {
  auto *arg = args.getLastArg(id);
  if (!arg)
    return {"", ""};

  StringRef s = arg->getValue();
  std::pair<StringRef, StringRef> ret = s.split(';');
  if (ret.second.empty())
    ErrAlways(ctx) << getAliasSpelling(arg)
                   << " expects 'old;new' format, but got " << s;
  return ret;
}

// Parse options of the form "old;new[;extra]".
static std::tuple<StringRef, StringRef, StringRef>
getOldNewOptionsExtra(Ctx &ctx, opt::InputArgList &args, unsigned id) {
  auto [oldDir, second] = getOldNewOptions(ctx, args, id);
  auto [newDir, extraDir] = second.split(';');
  return {oldDir, newDir, extraDir};
}

// Parse the symbol ordering file and warn for any duplicate entries.
static SmallVector<StringRef, 0> getSymbolOrderingFile(Ctx &ctx,
                                                       MemoryBufferRef mb) {
  SetVector<StringRef, SmallVector<StringRef, 0>> names;
  for (StringRef s : args::getLines(mb))
    if (!names.insert(s) && ctx.arg.warnSymbolOrdering)
      Warn(ctx) << mb.getBufferIdentifier()
                << ": duplicate ordered symbol: " << s;

  return names.takeVector();
}

static bool getIsRela(Ctx &ctx, opt::InputArgList &args) {
  // The psABI specifies the default relocation entry format.
  bool rela = is_contained({EM_AARCH64, EM_AMDGPU, EM_HEXAGON, EM_LOONGARCH,
                            EM_PPC, EM_PPC64, EM_RISCV, EM_S390, EM_X86_64},
                           ctx.arg.emachine);
  // If -z rel or -z rela is specified, use the last option.
  for (auto *arg : args.filtered(OPT_z)) {
    StringRef s(arg->getValue());
    if (s == "rel")
      rela = false;
    else if (s == "rela")
      rela = true;
    else
      continue;
    arg->claim();
  }
  return rela;
}

static void parseClangOption(Ctx &ctx, StringRef opt, const Twine &msg) {
  std::string err;
  raw_string_ostream os(err);

  const char *argv[] = {ctx.arg.progName.data(), opt.data()};
  if (cl::ParseCommandLineOptions(2, argv, "", &os))
    return;
  ErrAlways(ctx) << msg << ": " << StringRef(err).trim();
}

// Process a remap pattern 'from-glob=to-file'.
static bool remapInputs(Ctx &ctx, StringRef line, const Twine &location) {
  SmallVector<StringRef, 0> fields;
  line.split(fields, '=');
  if (fields.size() != 2 || fields[1].empty()) {
    ErrAlways(ctx) << location << ": parse error, not 'from-glob=to-file'";
    return true;
  }
  if (!hasWildcard(fields[0]))
    ctx.arg.remapInputs[fields[0]] = fields[1];
  else if (Expected<GlobPattern> pat = GlobPattern::create(fields[0]))
    ctx.arg.remapInputsWildcards.emplace_back(std::move(*pat), fields[1]);
  else {
    ErrAlways(ctx) << location << ": " << pat.takeError() << ": " << fields[0];
    return true;
  }
  return false;
}

// Initializes Config members by the command line options.
static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
  ctx.e.verbose = args.hasArg(OPT_verbose);
  ctx.e.vsDiagnostics =
      args.hasArg(OPT_visual_studio_diagnostics_format, false);

  ctx.arg.allowMultipleDefinition =
      hasZOption(args, "muldefs") ||
      args.hasFlag(OPT_allow_multiple_definition,
                   OPT_no_allow_multiple_definition, false);
  ctx.arg.androidMemtagHeap =
      args.hasFlag(OPT_android_memtag_heap, OPT_no_android_memtag_heap, false);
  ctx.arg.androidMemtagStack = args.hasFlag(OPT_android_memtag_stack,
                                            OPT_no_android_memtag_stack, false);
  ctx.arg.fatLTOObjects =
      args.hasFlag(OPT_fat_lto_objects, OPT_no_fat_lto_objects, false);
  ctx.arg.androidMemtagMode = getMemtagMode(ctx, args);
  ctx.arg.auxiliaryList = args::getStrings(args, OPT_auxiliary);
  ctx.arg.armBe8 = args.hasArg(OPT_be8);
  if (opt::Arg *arg = args.getLastArg(
          OPT_Bno_symbolic, OPT_Bsymbolic_non_weak_functions,
          OPT_Bsymbolic_functions, OPT_Bsymbolic_non_weak, OPT_Bsymbolic)) {
    if (arg->getOption().matches(OPT_Bsymbolic_non_weak_functions))
      ctx.arg.bsymbolic = BsymbolicKind::NonWeakFunctions;
    else if (arg->getOption().matches(OPT_Bsymbolic_functions))
      ctx.arg.bsymbolic = BsymbolicKind::Functions;
    else if (arg->getOption().matches(OPT_Bsymbolic_non_weak))
      ctx.arg.bsymbolic = BsymbolicKind::NonWeak;
    else if (arg->getOption().matches(OPT_Bsymbolic))
      ctx.arg.bsymbolic = BsymbolicKind::All;
  }
  ctx.arg.callGraphProfileSort = getCGProfileSortKind(ctx, args);
  parseBPOrdererOptions(ctx, args);
  ctx.arg.checkSections =
      args.hasFlag(OPT_check_sections, OPT_no_check_sections, true);
  ctx.arg.chroot = args.getLastArgValue(OPT_chroot);
  if (auto *arg = args.getLastArg(OPT_compress_debug_sections)) {
    ctx.arg.compressDebugSections =
        getCompressionType(ctx, arg->getValue(), "--compress-debug-sections");
  }
  ctx.arg.cref = args.hasArg(OPT_cref);
  ctx.arg.optimizeBBJumps =
      args.hasFlag(OPT_optimize_bb_jumps, OPT_no_optimize_bb_jumps, false);
  ctx.arg.debugNames = args.hasFlag(OPT_debug_names, OPT_no_debug_names, false);
  ctx.arg.demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true);
  ctx.arg.dependencyFile = args.getLastArgValue(OPT_dependency_file);
  ctx.arg.dependentLibraries =
      args.hasFlag(OPT_dependent_libraries, OPT_no_dependent_libraries, true);
  ctx.arg.disableVerify = args.hasArg(OPT_disable_verify);
  ctx.arg.discard = getDiscard(args);
  ctx.arg.dtltoDistributor = args.getLastArgValue(OPT_thinlto_distributor_eq);
  ctx.arg.dtltoDistributorArgs =
      args::getStrings(args, OPT_thinlto_distributor_arg);
  ctx.arg.dtltoCompiler = args.getLastArgValue(OPT_thinlto_compiler_eq);
  ctx.arg.dtltoCompilerArgs = args::getStrings(args, OPT_thinlto_compiler_arg);
  ctx.arg.dwoDir = args.getLastArgValue(OPT_plugin_opt_dwo_dir_eq);
  ctx.arg.dynamicLinker = getDynamicLinker(ctx, args);
  ctx.arg.ehFrameHdr =
      args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false);
  ctx.arg.emitLLVM = args.hasArg(OPT_lto_emit_llvm);
  ctx.arg.emitRelocs = args.hasArg(OPT_emit_relocs);
  ctx.arg.enableNewDtags =
      args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true);
  ctx.arg.enableNonContiguousRegions =
      args.hasArg(OPT_enable_non_contiguous_regions);
  ctx.arg.entry = args.getLastArgValue(OPT_entry);

  ctx.e.errorHandlingScript = args.getLastArgValue(OPT_error_handling_script);

  ctx.arg.executeOnly =
      args.hasFlag(OPT_execute_only, OPT_no_execute_only, false);
  ctx.arg.exportDynamic =
      args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false) ||
      args.hasArg(OPT_shared);
  ctx.arg.filterList = args::getStrings(args, OPT_filter);
  ctx.arg.fini = args.getLastArgValue(OPT_fini, "_fini");
  ctx.arg.fixCortexA53Errata843419 =
      args.hasArg(OPT_fix_cortex_a53_843419) && !args.hasArg(OPT_relocatable);
  ctx.arg.cmseImplib = args.hasArg(OPT_cmse_implib);
  ctx.arg.cmseInputLib = args.getLastArgValue(OPT_in_implib);
  ctx.arg.cmseOutputLib = args.getLastArgValue(OPT_out_implib);
  ctx.arg.fixCortexA8 =
      args.hasArg(OPT_fix_cortex_a8) && !args.hasArg(OPT_relocatable);
  ctx.arg.fortranCommon =
      args.hasFlag(OPT_fortran_common, OPT_no_fortran_common, false);
  ctx.arg.gcSections = args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false);
  ctx.arg.gnuUnique = args.hasFlag(OPT_gnu_unique, OPT_no_gnu_unique, true);
  ctx.arg.gdbIndex = args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false);
  ctx.arg.icf = getICF(args);
  ctx.arg.ignoreDataAddressEquality =
      args.hasArg(OPT_ignore_data_address_equality);
  ctx.arg.ignoreFunctionAddressEquality =
      args.hasArg(OPT_ignore_function_address_equality);
  ctx.arg.init = args.getLastArgValue(OPT_init, "_init");
  ctx.arg.ltoAAPipeline = args.getLastArgValue(OPT_lto_aa_pipeline);
  ctx.arg.ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate);
  ctx.arg.ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file);
  ctx.arg.ltoPGOWarnMismatch = args.hasFlag(OPT_lto_pgo_warn_mismatch,
                                            OPT_no_lto_pgo_warn_mismatch, true);
  ctx.arg.ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
  ctx.arg.ltoEmitAsm = args.hasArg(OPT_lto_emit_asm);
  ctx.arg.ltoNewPmPasses = args.getLastArgValue(OPT_lto_newpm_passes);
  ctx.arg.ltoWholeProgramVisibility =
      args.hasFlag(OPT_lto_whole_program_visibility,
                   OPT_no_lto_whole_program_visibility, false);
  ctx.arg.ltoValidateAllVtablesHaveTypeInfos =
      args.hasFlag(OPT_lto_validate_all_vtables_have_type_infos,
                   OPT_no_lto_validate_all_vtables_have_type_infos, false);
  ctx.arg.ltoo = args::getInteger(args, OPT_lto_O, 2);
  if (ctx.arg.ltoo > 3)
    ErrAlways(ctx) << "invalid optimization level for LTO: " << ctx.arg.ltoo;
  unsigned ltoCgo =
      args::getInteger(args, OPT_lto_CGO, args::getCGOptLevel(ctx.arg.ltoo));
  if (auto level = CodeGenOpt::getLevel(ltoCgo))
    ctx.arg.ltoCgo = *level;
  else
    ErrAlways(ctx) << "invalid codegen optimization level for LTO: " << ltoCgo;
  ctx.arg.ltoObjPath = args.getLastArgValue(OPT_lto_obj_path_eq);
  ctx.arg.ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
  ctx.arg.ltoSampleProfile = args.getLastArgValue(OPT_lto_sample_profile);
  ctx.arg.ltoBBAddrMap =
      args.hasFlag(OPT_lto_basic_block_address_map,
                   OPT_no_lto_basic_block_address_map, false);
  ctx.arg.ltoBasicBlockSections =
      args.getLastArgValue(OPT_lto_basic_block_sections);
  ctx.arg.ltoUniqueBasicBlockSectionNames =
      args.hasFlag(OPT_lto_unique_basic_block_section_names,
                   OPT_no_lto_unique_basic_block_section_names, false);
  ctx.arg.mapFile = args.getLastArgValue(OPT_Map);
  ctx.arg.mipsGotSize = args::getInteger(args, OPT_mips_got_size, 0xfff0);
  ctx.arg.mergeArmExidx =
      args.hasFlag(OPT_merge_exidx_entries, OPT_no_merge_exidx_entries, true);
  ctx.arg.mmapOutputFile =
      args.hasFlag(OPT_mmap_output_file, OPT_no_mmap_output_file, false);
  ctx.arg.nmagic = args.hasFlag(OPT_nmagic, OPT_no_nmagic, false);
  ctx.arg.noinhibitExec = args.hasArg(OPT_noinhibit_exec);
  ctx.arg.nostdlib = args.hasArg(OPT_nostdlib);
  ctx.arg.oFormatBinary = isOutputFormatBinary(ctx, args);
  ctx.arg.omagic = args.hasFlag(OPT_omagic, OPT_no_omagic, false);
  ctx.arg.optRemarksFilename = args.getLastArgValue(OPT_opt_remarks_filename);
  ctx.arg.optStatsFilename = args.getLastArgValue(OPT_plugin_opt_stats_file);

  // Parse remarks hotness threshold. Valid value is either integer or 'auto'.
  if (auto *arg = args.getLastArg(OPT_opt_remarks_hotness_threshold)) {
    auto resultOrErr = remarks::parseHotnessThresholdOption(arg->getValue());
    if (!resultOrErr)
      ErrAlways(ctx) << arg->getSpelling() << ": invalid argument '"
                     << arg->getValue()
                     << "', only integer or 'auto' is supported";
    else
      ctx.arg.optRemarksHotnessThreshold = *resultOrErr;
  }

  ctx.arg.optRemarksPasses = args.getLastArgValue(OPT_opt_remarks_passes);
  ctx.arg.optRemarksWithHotness = args.hasArg(OPT_opt_remarks_with_hotness);
  ctx.arg.optRemarksFormat = args.getLastArgValue(OPT_opt_remarks_format);
  ctx.arg.optimize = args::getInteger(args, OPT_O, 1);
  ctx.arg.orphanHandling = getOrphanHandling(ctx, args);
  ctx.arg.outputFile = args.getLastArgValue(OPT_o);
  if (auto *arg = args.getLastArg(OPT_package_metadata))
    parsePackageMetadata(ctx, *arg);
  ctx.arg.pie = args.hasFlag(OPT_pie, OPT_no_pie, false);
  ctx.arg.printIcfSections =
      args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false);
  ctx.arg.printGcSections =
      args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
  ctx.arg.printMemoryUsage = args.hasArg(OPT_print_memory_usage);
  ctx.arg.printArchiveStats = args.getLastArgValue(OPT_print_archive_stats);
  ctx.arg.printSymbolOrder = args.getLastArgValue(OPT_print_symbol_order);
  ctx.arg.rejectMismatch = !args.hasArg(OPT_no_warn_mismatch);
  ctx.arg.relax = args.hasFlag(OPT_relax, OPT_no_relax, true);
  ctx.arg.relaxGP = args.hasFlag(OPT_relax_gp, OPT_no_relax_gp, false);
  ctx.arg.rpath = getRpath(args);
  ctx.arg.relocatable = args.hasArg(OPT_relocatable);
  ctx.arg.resolveGroups =
      !args.hasArg(OPT_relocatable) || args.hasArg(OPT_force_group_allocation);

  if (args.hasArg(OPT_save_temps)) {
    // --save-temps implies saving all temps.
    ctx.arg.saveTempsArgs.insert_range(saveTempsValues);
  } else {
    for (auto *arg : args.filtered(OPT_save_temps_eq)) {
      StringRef s = arg->getValue();
      if (llvm::is_contained(saveTempsValues, s))
        ctx.arg.saveTempsArgs.insert(s);
      else
        ErrAlways(ctx) << "unknown --save-temps value: " << s;
    }
  }

  ctx.arg.searchPaths = args::getStrings(args, OPT_library_path);
  ctx.arg.sectionStartMap = getSectionStartMap(ctx, args);
  ctx.arg.shared = args.hasArg(OPT_shared);
  if (args.hasArg(OPT_randomize_section_padding))
    ctx.arg.randomizeSectionPadding =
        args::getInteger(args, OPT_randomize_section_padding, 0);
  ctx.arg.singleRoRx = !args.hasFlag(OPT_rosegment, OPT_no_rosegment, true);
  ctx.arg.singleXoRx = !args.hasFlag(OPT_xosegment, OPT_no_xosegment, false);
  ctx.arg.soName = args.getLastArgValue(OPT_soname);
  ctx.arg.sortSection = getSortSection(ctx, args);
  ctx.arg.splitStackAdjustSize =
      args::getInteger(args, OPT_split_stack_adjust_size, 16384);
  ctx.arg.zSectionHeader =
      getZFlag(args, "sectionheader", "nosectionheader", true);
  ctx.arg.strip = getStrip(ctx, args); // needs zSectionHeader
  ctx.arg.sysroot = args.getLastArgValue(OPT_sysroot);
  ctx.arg.target1Rel = args.hasFlag(OPT_target1_rel, OPT_target1_abs, false);
  ctx.arg.target2 = getTarget2(ctx, args);
  ctx.arg.thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir);
  ctx.arg.thinLTOCachePolicy = CHECK(
      parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)),
      "--thinlto-cache-policy: invalid cache policy");
  ctx.arg.thinLTOEmitImportsFiles = args.hasArg(OPT_thinlto_emit_imports_files);
  ctx.arg.thinLTOEmitIndexFiles = args.hasArg(OPT_thinlto_emit_index_files) ||
                                  args.hasArg(OPT_thinlto_index_only) ||
                                  args.hasArg(OPT_thinlto_index_only_eq);
  ctx.arg.thinLTOIndexOnly = args.hasArg(OPT_thinlto_index_only) ||
                             args.hasArg(OPT_thinlto_index_only_eq);
  ctx.arg.thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_eq);
  ctx.arg.thinLTOObjectSuffixReplace =
      getOldNewOptions(ctx, args, OPT_thinlto_object_suffix_replace_eq);
  std::tie(ctx.arg.thinLTOPrefixReplaceOld, ctx.arg.thinLTOPrefixReplaceNew,
           ctx.arg.thinLTOPrefixReplaceNativeObject) =
      getOldNewOptionsExtra(ctx, args, OPT_thinlto_prefix_replace_eq);
  if (ctx.arg.thinLTOEmitIndexFiles && !ctx.arg.thinLTOIndexOnly) {
    if (args.hasArg(OPT_thinlto_object_suffix_replace_eq))
      ErrAlways(ctx) << "--thinlto-object-suffix-replace is not supported with "
                        "--thinlto-emit-index-files";
    else if (args.hasArg(OPT_thinlto_prefix_replace_eq))
      ErrAlways(ctx) << "--thinlto-prefix-replace is not supported with "
                        "--thinlto-emit-index-files";
  }
  if (!ctx.arg.thinLTOPrefixReplaceNativeObject.empty() &&
      ctx.arg.thinLTOIndexOnlyArg.empty()) {
    ErrAlways(ctx)
        << "--thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with "
           "--thinlto-index-only=";
  }
  ctx.arg.thinLTOModulesToCompile =
      args::getStrings(args, OPT_thinlto_single_module_eq);
  ctx.arg.timeTraceEnabled =
      args.hasArg(OPT_time_trace_eq) && !ctx.e.disableOutput;
  ctx.arg.timeTraceGranularity =
      args::getInteger(args, OPT_time_trace_granularity, 500);
  ctx.arg.trace = args.hasArg(OPT_trace);
  ctx.arg.undefined = args::getStrings(args, OPT_undefined);
  ctx.arg.undefinedVersion =
      args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, false);
  ctx.arg.unique = args.hasArg(OPT_unique);
  ctx.arg.useAndroidRelrTags = args.hasFlag(
      OPT_use_android_relr_tags, OPT_no_use_android_relr_tags, false);
  ctx.arg.warnBackrefs =
      args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false);
  ctx.arg.warnCommon = args.hasFlag(OPT_warn_common, OPT_no_warn_common, false);
  ctx.arg.warnSymbolOrdering =
      args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true);
  ctx.arg.whyExtract = args.getLastArgValue(OPT_why_extract);
  for (opt::Arg *arg : args.filtered(OPT_why_live)) {
    StringRef value(arg->getValue());
    if (Expected<GlobPattern> pat = GlobPattern::create(arg->getValue())) {
      ctx.arg.whyLive.emplace_back(std::move(*pat));
    } else {
      ErrAlways(ctx) << arg->getSpelling() << ": " << pat.takeError();
      continue;
    }
  }
  ctx.arg.zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
  ctx.arg.zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
  ctx.arg.zForceBti = hasZOption(args, "force-bti");
  ctx.arg.zForceIbt = hasZOption(args, "force-ibt");
  ctx.arg.zZicfilp = getZZicfilp(ctx, args);
  ctx.arg.zZicfiss = getZZicfiss(ctx, args);
  ctx.arg.zGcs = getZGcs(ctx, args);
  ctx.arg.zGlobal = hasZOption(args, "global");
  ctx.arg.zGnustack = getZGnuStack(args);
  ctx.arg.zHazardplt = hasZOption(args, "hazardplt");
  ctx.arg.zIfuncNoplt = hasZOption(args, "ifunc-noplt");
  ctx.arg.zInitfirst = hasZOption(args, "initfirst");
  ctx.arg.zInterpose = hasZOption(args, "interpose");
  ctx.arg.zKeepTextSectionPrefix = getZFlag(
      args, "keep-text-section-prefix", "nokeep-text-section-prefix", false);
  ctx.arg.zLrodataAfterBss =
      getZFlag(args, "lrodata-after-bss", "nolrodata-after-bss", false);
  ctx.arg.zNoBtCfi = hasZOption(args, "nobtcfi");
  ctx.arg.zNodefaultlib = hasZOption(args, "nodefaultlib");
  ctx.arg.zNodelete = hasZOption(args, "nodelete");
  ctx.arg.zNodlopen = hasZOption(args, "nodlopen");
  ctx.arg.zNow = getZFlag(args, "now", "lazy", false);
  ctx.arg.zOrigin = hasZOption(args, "origin");
  ctx.arg.zPacPlt = getZFlag(args, "pac-plt", "nopac-plt", false);
  ctx.arg.zRelro = getZFlag(args, "relro", "norelro", true);
  ctx.arg.zRetpolineplt = hasZOption(args, "retpolineplt");
  ctx.arg.zRodynamic = hasZOption(args, "rodynamic");
  ctx.arg.zSeparate = getZSeparate(args);
  ctx.arg.zShstk = hasZOption(args, "shstk");
  ctx.arg.zStackSize = args::getZOptionValue(args, OPT_z, "stack-size", 0);
  ctx.arg.zStartStopGC =
      getZFlag(args, "start-stop-gc", "nostart-stop-gc", true);
  ctx.arg.zStartStopVisibility = getZStartStopVisibility(ctx, args);
  ctx.arg.zText = getZFlag(args, "text", "notext", true);
  ctx.arg.zWxneeded = hasZOption(args, "wxneeded");
  setUnresolvedSymbolPolicy(ctx, args);
  ctx.arg.power10Stubs = args.getLastArgValue(OPT_power10_stubs_eq) != "no";
  ctx.arg.branchToBranch = args.hasFlag(
      OPT_branch_to_branch, OPT_no_branch_to_branch, ctx.arg.optimize >= 2);

  if (opt::Arg *arg = args.getLastArg(OPT_eb, OPT_el)) {
    if (arg->getOption().matches(OPT_eb))
      ctx.arg.optEB = true;
    else
      ctx.arg.optEL = true;
  }

  for (opt::Arg *arg : args.filtered(OPT_remap_inputs)) {
    StringRef value(arg->getValue());
    remapInputs(ctx, value, arg->getSpelling());
  }
  for (opt::Arg *arg : args.filtered(OPT_remap_inputs_file)) {
    StringRef filename(arg->getValue());
    std::optional<MemoryBufferRef> buffer = readFile(ctx, filename);
    if (!buffer)
      continue;
    // Parse 'from-glob=to-file' lines, ignoring #-led comments.
    for (auto [lineno, line] : llvm::enumerate(args::getLines(*buffer)))
      if (remapInputs(ctx, line, filename + ":" + Twine(lineno + 1)))
        break;
  }

  for (opt::Arg *arg : args.filtered(OPT_shuffle_sections)) {
    constexpr StringRef errPrefix = "--shuffle-sections=: ";
    std::pair<StringRef, StringRef> kv = StringRef(arg->getValue()).split('=');
    if (kv.first.empty() || kv.second.empty()) {
      ErrAlways(ctx) << errPrefix << "expected <section_glob>=<seed>, but got '"
                     << arg->getValue() << "'";
      continue;
    }
    // Signed so that <section_glob>=-1 is allowed.
    int64_t v;
    if (!to_integer(kv.second, v))
      ErrAlways(ctx) << errPrefix << "expected an integer, but got '"
                     << kv.second << "'";
    else if (Expected<GlobPattern> pat = GlobPattern::create(kv.first))
      ctx.arg.shuffleSections.emplace_back(std::move(*pat), uint32_t(v));
    else
      ErrAlways(ctx) << errPrefix << pat.takeError() << ": " << kv.first;
  }

  auto reports = {
      std::make_pair("bti-report", &ctx.arg.zBtiReport),
      std::make_pair("cet-report", &ctx.arg.zCetReport),
      std::make_pair("execute-only-report", &ctx.arg.zExecuteOnlyReport),
      std::make_pair("gcs-report", &ctx.arg.zGcsReport),
      std::make_pair("gcs-report-dynamic", &ctx.arg.zGcsReportDynamic),
      std::make_pair("pauth-report", &ctx.arg.zPauthReport),
      std::make_pair("zicfilp-unlabeled-report",
                     &ctx.arg.zZicfilpUnlabeledReport),
      std::make_pair("zicfilp-func-sig-report", &ctx.arg.zZicfilpFuncSigReport),
      std::make_pair("zicfiss-report", &ctx.arg.zZicfissReport)};
  bool hasGcsReportDynamic = false;
  for (opt::Arg *arg : args.filtered(OPT_z)) {
    std::pair<StringRef, StringRef> option =
        StringRef(arg->getValue()).split('=');
    for (auto reportArg : reports) {
      if (option.first != reportArg.first)
        continue;
      arg->claim();
      if (option.second == "none")
        *reportArg.second = ReportPolicy::None;
      else if (option.second == "warning")
        *reportArg.second = ReportPolicy::Warning;
      else if (option.second == "error")
        *reportArg.second = ReportPolicy::Error;
      else {
        ErrAlways(ctx) << "unknown -z " << reportArg.first
                       << "= value: " << option.second;
        continue;
      }
      hasGcsReportDynamic |= option.first == "gcs-report-dynamic";
    }
  }

  // When -zgcs-report-dynamic is unspecified, it inherits -zgcs-report
  // but is capped at warning to avoid needing to rebuild the shared library
  // with GCS enabled.
  if (!hasGcsReportDynamic && ctx.arg.zGcsReport != ReportPolicy::None)
    ctx.arg.zGcsReportDynamic = ReportPolicy::Warning;

  for (opt::Arg *arg : args.filtered(OPT_compress_sections)) {
    SmallVector<StringRef, 0> fields;
    StringRef(arg->getValue()).split(fields, '=');
    if (fields.size() != 2 || fields[1].empty()) {
      ErrAlways(ctx) << arg->getSpelling()
                     << ": parse error, not 'section-glob=[none|zlib|zstd]'";
      continue;
    }
    auto [typeStr, levelStr] = fields[1].split(':');
    auto type = getCompressionType(ctx, typeStr, arg->getSpelling());
    unsigned level = 0;
    if (fields[1].size() != typeStr.size() &&
        !llvm::to_integer(levelStr, level)) {
      ErrAlways(ctx)
          << arg->getSpelling()
          << ": expected a non-negative integer compression level, but got '"
          << levelStr << "'";
    }
    if (Expected<GlobPattern> pat = GlobPattern::create(fields[0])) {
      ctx.arg.compressSections.emplace_back(std::move(*pat), type, level);
    } else {
      ErrAlways(ctx) << arg->getSpelling() << ": " << pat.takeError();
      continue;
    }
  }

  for (opt::Arg *arg : args.filtered(OPT_z)) {
    std::pair<StringRef, StringRef> option =
        StringRef(arg->getValue()).split('=');
    if (option.first != "dead-reloc-in-nonalloc")
      continue;
    arg->claim();
    constexpr StringRef errPrefix = "-z dead-reloc-in-nonalloc=: ";
    std::pair<StringRef, StringRef> kv = option.second.split('=');
    if (kv.first.empty() || kv.second.empty()) {
      ErrAlways(ctx) << errPrefix << "expected <section_glob>=<value>";
      continue;
    }
    uint64_t v;
    if (!to_integer(kv.second, v))
      ErrAlways(ctx) << errPrefix
                     << "expected a non-negative integer, but got '"
                     << kv.second << "'";
    else if (Expected<GlobPattern> pat = GlobPattern::create(kv.first))
      ctx.arg.deadRelocInNonAlloc.emplace_back(std::move(*pat), v);
    else
      ErrAlways(ctx) << errPrefix << pat.takeError() << ": " << kv.first;
  }

  cl::ResetAllOptionOccurrences();

  // Parse LTO options.
  if (auto *arg = args.getLastArg(OPT_plugin_opt_mcpu_eq))
    parseClangOption(ctx, ctx.saver.save("-mcpu=" + StringRef(arg->getValue())),
                     arg->getSpelling());

  for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq_minus))
    parseClangOption(ctx, std::string("-") + arg->getValue(),
                     arg->getSpelling());

  // GCC collect2 passes -plugin-opt=path/to/lto-wrapper with an absolute or
  // relative path. Just ignore. If not ended with "lto-wrapper" (or
  // "lto-wrapper.exe" for GCC cross-compiled for Windows), consider it an
  // unsupported LLVMgold.so option and error.
  for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq)) {
    StringRef v(arg->getValue());
    if (!v.ends_with("lto-wrapper") && !v.ends_with("lto-wrapper.exe"))
      ErrAlways(ctx) << arg->getSpelling() << ": unknown plugin option '"
                     << arg->getValue() << "'";
  }

  ctx.arg.passPlugins = args::getStrings(args, OPT_load_pass_plugins);

  // Parse -mllvm options.
  for (const auto *arg : args.filtered(OPT_mllvm)) {
    parseClangOption(ctx, arg->getValue(), arg->getSpelling());
    ctx.arg.mllvmOpts.emplace_back(arg->getValue());
  }

  ctx.arg.ltoKind = LtoKind::Default;
  if (auto *arg = args.getLastArg(OPT_lto)) {
    StringRef s = arg->getValue();
    if (s == "thin")
      ctx.arg.ltoKind = LtoKind::UnifiedThin;
    else if (s == "full")
      ctx.arg.ltoKind = LtoKind::UnifiedRegular;
    else if (s == "default")
      ctx.arg.ltoKind = LtoKind::Default;
    else
      ErrAlways(ctx) << "unknown LTO mode: " << s;
  }

  // --threads= takes a positive integer and provides the default value for
  // --thinlto-jobs=. If unspecified, cap the number of threads since
  // overhead outweighs optimization for used parallel algorithms for the
  // non-LTO parts.
  if (auto *arg = args.getLastArg(OPT_threads)) {
    StringRef v(arg->getValue());
    unsigned threads = 0;
    if (!llvm::to_integer(v, threads, 0) || threads == 0)
      ErrAlways(ctx) << arg->getSpelling()
                     << ": expected a positive integer, but got '"
                     << arg->getValue() << "'";
    parallel::strategy = hardware_concurrency(threads);
    ctx.arg.thinLTOJobs = v;
  } else if (parallel::strategy.compute_thread_count() > 16) {
    Log(ctx) << "set maximum concurrency to 16, specify --threads= to change";
    parallel::strategy = hardware_concurrency(16);
  }
  if (auto *arg = args.getLastArg(OPT_thinlto_jobs_eq))
    ctx.arg.thinLTOJobs = arg->getValue();
  ctx.arg.threadCount = parallel::strategy.compute_thread_count();

  if (ctx.arg.ltoPartitions == 0)
    ErrAlways(ctx) << "--lto-partitions: number of threads must be > 0";
  if (!get_threadpool_strategy(ctx.arg.thinLTOJobs))
    ErrAlways(ctx) << "--thinlto-jobs: invalid job count: "
                   << ctx.arg.thinLTOJobs;

  if (ctx.arg.splitStackAdjustSize < 0)
    ErrAlways(ctx) << "--split-stack-adjust-size: size must be >= 0";

  // The text segment is traditionally the first segment, whose address equals
  // the base address. However, lld places the R PT_LOAD first. -Ttext-segment
  // is an old-fashioned option that does not play well with lld's layout.
  // Suggest --image-base as a likely alternative.
  if (args.hasArg(OPT_Ttext_segment))
    ErrAlways(ctx)
        << "-Ttext-segment is not supported. Use --image-base if you "
           "intend to set the base address";

  // Parse ELF{32,64}{LE,BE} and CPU type.
  if (auto *arg = args.getLastArg(OPT_m)) {
    StringRef s = arg->getValue();
    std::tie(ctx.arg.ekind, ctx.arg.emachine, ctx.arg.osabi) =
        parseEmulation(ctx, s);
    ctx.arg.mipsN32Abi =
        (s.starts_with("elf32btsmipn32") || s.starts_with("elf32ltsmipn32"));
    ctx.arg.emulation = s;
  }

  // Parse --hash-style={sysv,gnu,both}.
  if (auto *arg = args.getLastArg(OPT_hash_style)) {
    StringRef s = arg->getValue();
    if (s == "sysv")
      ctx.arg.sysvHash = true;
    else if (s == "gnu")
      ctx.arg.gnuHash = true;
    else if (s == "both")
      ctx.arg.sysvHash = ctx.arg.gnuHash = true;
    else
      ErrAlways(ctx) << "unknown --hash-style: " << s;
  }

  if (args.hasArg(OPT_print_map))
    ctx.arg.mapFile = "-";

  // Page alignment can be disabled by the -n (--nmagic) and -N (--omagic).
  // As PT_GNU_RELRO relies on Paging, do not create it when we have disabled
  // it. Also disable RELRO for -r.
  if (ctx.arg.nmagic || ctx.arg.omagic || ctx.arg.relocatable)
    ctx.arg.zRelro = false;

  std::tie(ctx.arg.buildId, ctx.arg.buildIdVector) = getBuildId(ctx, args);

  if (getZFlag(args, "pack-relative-relocs", "nopack-relative-relocs", false)) {
    ctx.arg.relrGlibc = true;
    ctx.arg.relrPackDynRelocs = true;
  } else {
    std::tie(ctx.arg.androidPackDynRelocs, ctx.arg.relrPackDynRelocs) =
        getPackDynRelocs(ctx, args);
  }

  if (auto *arg = args.getLastArg(OPT_symbol_ordering_file)){
    if (args.hasArg(OPT_call_graph_ordering_file))
      ErrAlways(ctx) << "--symbol-ordering-file and --call-graph-order-file "
                        "may not be used together";
    if (auto buffer = readFile(ctx, arg->getValue()))
      ctx.arg.symbolOrderingFile = getSymbolOrderingFile(ctx, *buffer);
  }

  assert(ctx.arg.versionDefinitions.empty());
  ctx.arg.versionDefinitions.push_back(
      {"local", (uint16_t)VER_NDX_LOCAL, {}, {}});
  ctx.arg.versionDefinitions.push_back(
      {"global", (uint16_t)VER_NDX_GLOBAL, {}, {}});

  // If --retain-symbol-file is used, we'll keep only the symbols listed in
  // the file and discard all others.
  if (auto *arg = args.getLastArg(OPT_retain_symbols_file)) {
    ctx.arg.versionDefinitions[VER_NDX_LOCAL].nonLocalPatterns.push_back(
        {"*", /*isExternCpp=*/false, /*hasWildcard=*/true});
    if (std::optional<MemoryBufferRef> buffer = readFile(ctx, arg->getValue()))
      for (StringRef s : args::getLines(*buffer))
        ctx.arg.versionDefinitions[VER_NDX_GLOBAL].nonLocalPatterns.push_back(
            {s, /*isExternCpp=*/false, /*hasWildcard=*/false});
  }

  for (opt::Arg *arg : args.filtered(OPT_warn_backrefs_exclude)) {
    StringRef pattern(arg->getValue());
    if (Expected<GlobPattern> pat = GlobPattern::create(pattern))
      ctx.arg.warnBackrefsExclude.push_back(std::move(*pat));
    else
      ErrAlways(ctx) << arg->getSpelling() << ": " << pat.takeError() << ": "
                     << pattern;
  }

  // For -no-pie and -pie, --export-dynamic-symbol specifies defined symbols
  // which should be exported. For -shared, references to matched non-local
  // STV_DEFAULT symbols are not bound to definitions within the shared object,
  // even if other options express a symbolic intention: -Bsymbolic,
  // -Bsymbolic-functions (if STT_FUNC), --dynamic-list.
  for (auto *arg : args.filtered(OPT_export_dynamic_symbol))
    ctx.arg.dynamicList.push_back(
        {arg->getValue(), /*isExternCpp=*/false,
         /*hasWildcard=*/hasWildcard(arg->getValue())});

  // --export-dynamic-symbol-list specifies a list of --export-dynamic-symbol
  // patterns. --dynamic-list is --export-dynamic-symbol-list plus -Bsymbolic
  // like semantics.
  ctx.arg.symbolic =
      ctx.arg.bsymbolic == BsymbolicKind::All || args.hasArg(OPT_dynamic_list);
  for (auto *arg :
       args.filtered(OPT_dynamic_list, OPT_export_dynamic_symbol_list))
    if (std::optional<MemoryBufferRef> buffer = readFile(ctx, arg->getValue()))
      readDynamicList(ctx, *buffer);

  for (auto *arg : args.filtered(OPT_version_script))
    if (std::optional<std::string> path = searchScript(ctx, arg->getValue())) {
      if (std::optional<MemoryBufferRef> buffer = readFile(ctx, *path))
        readVersionScript(ctx, *buffer);
    } else {
      ErrAlways(ctx) << "cannot find version script " << arg->getValue();
    }
}

// Some Config members do not directly correspond to any particular
// command line options, but computed based on other Config values.
// This function initialize such members. See Config.h for the details
// of these values.
static void setConfigs(Ctx &ctx, opt::InputArgList &args) {
  ELFKind k = ctx.arg.ekind;
  uint16_t m = ctx.arg.emachine;

  ctx.arg.copyRelocs = (ctx.arg.relocatable || ctx.arg.emitRelocs);
  ctx.arg.is64 = (k == ELF64LEKind || k == ELF64BEKind);
  ctx.arg.isLE = (k == ELF32LEKind || k == ELF64LEKind);
  ctx.arg.endianness = ctx.arg.isLE ? endianness::little : endianness::big;
  ctx.arg.isMips64EL = (k == ELF64LEKind && m == EM_MIPS);
  ctx.arg.isPic = ctx.arg.pie || ctx.arg.shared;
  ctx.arg.picThunk = args.hasArg(OPT_pic_veneer, ctx.arg.isPic);
  ctx.arg.wordsize = ctx.arg.is64 ? 8 : 4;

  // ELF defines two different ways to store relocation addends as shown below:
  //
  //  Rel: Addends are stored to the location where relocations are applied. It
  //  cannot pack the full range of addend values for all relocation types, but
  //  this only affects relocation types that we don't support emitting as
  //  dynamic relocations (see getDynRel).
  //  Rela: Addends are stored as part of relocation entry.
  //
  // In other words, Rela makes it easy to read addends at the price of extra
  // 4 or 8 byte for each relocation entry.
  //
  // We pick the format for dynamic relocations according to the psABI for each
  // processor, but a contrary choice can be made if the dynamic loader
  // supports.
  ctx.arg.isRela = getIsRela(ctx, args);

  // If the output uses REL relocations we must store the dynamic relocation
  // addends to the output sections. We also store addends for RELA relocations
  // if --apply-dynamic-relocs is used.
  // We default to not writing the addends when using RELA relocations since
  // any standard conforming tool can find it in r_addend.
  ctx.arg.writeAddends = args.hasFlag(OPT_apply_dynamic_relocs,
                                      OPT_no_apply_dynamic_relocs, false) ||
                         !ctx.arg.isRela;
  // Validation of dynamic relocation addends is on by default for assertions
  // builds and disabled otherwise. This check is enabled when writeAddends is
  // true.
#ifndef NDEBUG
  bool checkDynamicRelocsDefault = true;
#else
  bool checkDynamicRelocsDefault = false;
#endif
  ctx.arg.checkDynamicRelocs =
      args.hasFlag(OPT_check_dynamic_relocations,
                   OPT_no_check_dynamic_relocations, checkDynamicRelocsDefault);
  ctx.arg.tocOptimize =
      args.hasFlag(OPT_toc_optimize, OPT_no_toc_optimize, m == EM_PPC64);
  ctx.arg.pcRelOptimize =
      args.hasFlag(OPT_pcrel_optimize, OPT_no_pcrel_optimize, m == EM_PPC64);

  if (!args.hasArg(OPT_hash_style)) {
    if (ctx.arg.emachine == EM_MIPS)
      ctx.arg.sysvHash = true;
    else
      ctx.arg.sysvHash = ctx.arg.gnuHash = true;
  }

  // Set default entry point and output file if not specified by command line or
  // linker scripts.
  ctx.arg.warnMissingEntry =
      (!ctx.arg.entry.empty() || (!ctx.arg.shared && !ctx.arg.relocatable));
  if (ctx.arg.entry.empty() && !ctx.arg.relocatable)
    ctx.arg.entry = ctx.arg.emachine == EM_MIPS ? "__start" : "_start";
  if (ctx.arg.outputFile.empty())
    ctx.arg.outputFile = "a.out";

  // Fail early if the output file or map file is not writable. If a user has a
  // long link, e.g. due to a large LTO link, they do not wish to run it and
  // find that it failed because there was a mistake in their command-line.
  {
    llvm::TimeTraceScope timeScope("Create output files");
    if (auto e = tryCreateFile(ctx.arg.outputFile))
      ErrAlways(ctx) << "cannot open output file " << ctx.arg.outputFile << ": "
                     << e.message();
    if (auto e = tryCreateFile(ctx.arg.mapFile))
      ErrAlways(ctx) << "cannot open map file " << ctx.arg.mapFile << ": "
                     << e.message();
    if (auto e = tryCreateFile(ctx.arg.whyExtract))
      ErrAlways(ctx) << "cannot open --why-extract= file " << ctx.arg.whyExtract
                     << ": " << e.message();
  }
}

static bool isFormatBinary(Ctx &ctx, StringRef s) {
  if (s == "binary")
    return true;
  if (s == "elf" || s == "default")
    return false;
  ErrAlways(ctx) << "unknown --format value: " << s
                 << " (supported formats: elf, default, binary)";
  return false;
}

void LinkerDriver::createFiles(opt::InputArgList &args) {
  llvm::TimeTraceScope timeScope("Load input files");
  // For --{push,pop}-state.
  std::vector<std::tuple<bool, bool, bool>> stack;

  // -r implies -Bstatic and has precedence over -Bdynamic.
  ctx.arg.isStatic = ctx.arg.relocatable;

  // Iterate over argv to process input files and positional arguments.
  std::optional<MemoryBufferRef> defaultScript;
  nextGroupId = 0;
  isInGroup = false;
  bool hasInput = false, hasScript = false;
  for (auto *arg : args) {
    switch (arg->getOption().getID()) {
    case OPT_library:
      addLibrary(arg->getValue());
      hasInput = true;
      break;
    case OPT_INPUT:
      addFile(arg->getValue(), /*withLOption=*/false);
      hasInput = true;
      break;
    case OPT_defsym: {
      readDefsym(ctx, MemoryBufferRef(arg->getValue(), "--defsym"));
      break;
    }
    case OPT_script:
    case OPT_default_script:
      if (std::optional<std::string> path =
              searchScript(ctx, arg->getValue())) {
        if (std::optional<MemoryBufferRef> mb = readFile(ctx, *path)) {
          if (arg->getOption().matches(OPT_default_script)) {
            defaultScript = mb;
          } else {
            readLinkerScript(ctx, *mb);
            hasScript = true;
          }
        }
        break;
      }
      ErrAlways(ctx) << "cannot find linker script " << arg->getValue();
      break;
    case OPT_as_needed:
      ctx.arg.asNeeded = true;
      break;
    case OPT_format:
      ctx.arg.formatBinary = isFormatBinary(ctx, arg->getValue());
      break;
    case OPT_no_as_needed:
      ctx.arg.asNeeded = false;
      break;
    case OPT_Bstatic:
    case OPT_omagic:
    case OPT_nmagic:
      ctx.arg.isStatic = true;
      break;
    case OPT_Bdynamic:
      if (!ctx.arg.relocatable)
        ctx.arg.isStatic = false;
      break;
    case OPT_whole_archive:
      inWholeArchive = true;
      break;
    case OPT_no_whole_archive:
      inWholeArchive = false;
      break;
    case OPT_just_symbols:
      if (std::optional<MemoryBufferRef> mb = readFile(ctx, arg->getValue())) {
        files.push_back(createObjFile(ctx, *mb));
        files.back()->justSymbols = true;
      }
      break;
    case OPT_in_implib:
      if (armCmseImpLib)
        ErrAlways(ctx) << "multiple CMSE import libraries not supported";
      else if (std::optional<MemoryBufferRef> mb =
                   readFile(ctx, arg->getValue()))
        armCmseImpLib = createObjFile(ctx, *mb);
      break;
    case OPT_start_group:
      if (isInGroup)
        ErrAlways(ctx) << "nested --start-group";
      isInGroup = true;
      break;
    case OPT_end_group:
      if (!isInGroup)
        ErrAlways(ctx) << "stray --end-group";
      isInGroup = false;
      ++nextGroupId;
      break;
    case OPT_start_lib:
      if (inLib)
        ErrAlways(ctx) << "nested --start-lib";
      if (isInGroup)
        ErrAlways(ctx) << "may not nest --start-lib in --start-group";
      inLib = true;
      isInGroup = true;
      break;
    case OPT_end_lib:
      if (!inLib)
        ErrAlways(ctx) << "stray --end-lib";
      inLib = false;
      isInGroup = false;
      ++nextGroupId;
      break;
    case OPT_push_state:
      stack.emplace_back(ctx.arg.asNeeded, ctx.arg.isStatic, inWholeArchive);
      break;
    case OPT_pop_state:
      if (stack.empty()) {
        ErrAlways(ctx) << "unbalanced --push-state/--pop-state";
        break;
      }
      std::tie(ctx.arg.asNeeded, ctx.arg.isStatic, inWholeArchive) =
          stack.back();
      stack.pop_back();
      break;
    }
  }

  if (defaultScript && !hasScript)
    readLinkerScript(ctx, *defaultScript);
  if (files.empty() && !hasInput && errCount(ctx) == 0)
    ErrAlways(ctx) << "no input files";
}

// If -m <machine_type> was not given, infer it from object files.
void LinkerDriver::inferMachineType() {
  if (ctx.arg.ekind != ELFNoneKind)
    return;

  bool inferred = false;
  for (auto &f : files) {
    if (f->ekind == ELFNoneKind)
      continue;
    if (!inferred) {
      inferred = true;
      ctx.arg.ekind = f->ekind;
      ctx.arg.emachine = f->emachine;
      ctx.arg.mipsN32Abi = ctx.arg.emachine == EM_MIPS && isMipsN32Abi(ctx, *f);
    }
    ctx.arg.osabi = f->osabi;
    if (f->osabi != ELFOSABI_NONE)
      return;
  }
  if (!inferred)
    ErrAlways(ctx)
        << "target emulation unknown: -m or at least one .o file required";
}

// Parse -z max-page-size=<value>. The default value is defined by
// each target.
static uint64_t getMaxPageSize(Ctx &ctx, opt::InputArgList &args) {
  uint64_t val = args::getZOptionValue(args, OPT_z, "max-page-size",
                                       ctx.target->defaultMaxPageSize);
  if (!isPowerOf2_64(val)) {
    ErrAlways(ctx) << "max-page-size: value isn't a power of 2";
    return ctx.target->defaultMaxPageSize;
  }
  if (ctx.arg.nmagic || ctx.arg.omagic) {
    if (val != ctx.target->defaultMaxPageSize)
      Warn(ctx)
          << "-z max-page-size set, but paging disabled by omagic or nmagic";
    return 1;
  }
  return val;
}

// Parse -z common-page-size=<value>. The default value is defined by
// each target.
static uint64_t getCommonPageSize(Ctx &ctx, opt::InputArgList &args) {
  uint64_t val = args::getZOptionValue(args, OPT_z, "common-page-size",
                                       ctx.target->defaultCommonPageSize);
  if (!isPowerOf2_64(val)) {
    ErrAlways(ctx) << "common-page-size: value isn't a power of 2";
    return ctx.target->defaultCommonPageSize;
  }
  if (ctx.arg.nmagic || ctx.arg.omagic) {
    if (val != ctx.target->defaultCommonPageSize)
      Warn(ctx)
          << "-z common-page-size set, but paging disabled by omagic or nmagic";
    return 1;
  }
  // commonPageSize can't be larger than maxPageSize.
  if (val > ctx.arg.maxPageSize)
    val = ctx.arg.maxPageSize;
  return val;
}

// Parses --image-base option.
static std::optional<uint64_t> getImageBase(Ctx &ctx, opt::InputArgList &args) {
  // Because we are using `ctx.arg.maxPageSize` here, this function has to be
  // called after the variable is initialized.
  auto *arg = args.getLastArg(OPT_image_base);
  if (!arg)
    return std::nullopt;

  StringRef s = arg->getValue();
  uint64_t v;
  if (!to_integer(s, v)) {
    ErrAlways(ctx) << "--image-base: number expected, but got " << s;
    return 0;
  }
  if ((v % ctx.arg.maxPageSize) != 0)
    Warn(ctx) << "--image-base: address isn't multiple of page size: " << s;
  return v;
}

// Parses `--exclude-libs=lib,lib,...`.
// The library names may be delimited by commas or colons.
static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &args) {
  DenseSet<StringRef> ret;
  for (auto *arg : args.filtered(OPT_exclude_libs)) {
    StringRef s = arg->getValue();
    for (;;) {
      size_t pos = s.find_first_of(",:");
      if (pos == StringRef::npos)
        break;
      ret.insert(s.substr(0, pos));
      s = s.substr(pos + 1);
    }
    ret.insert(s);
  }
  return ret;
}

// Handles the --exclude-libs option. If a static library file is specified
// by the --exclude-libs option, all public symbols from the archive become
// private unless otherwise specified by version scripts or something.
// A special library name "ALL" means all archive files.
//
// This is not a popular option, but some programs such as bionic libc use it.
static void excludeLibs(Ctx &ctx, opt::InputArgList &args) {
  DenseSet<StringRef> libs = getExcludeLibs(args);
  bool all = libs.count("ALL");

  auto visit = [&](InputFile *file) {
    if (file->archiveName.empty() ||
        !(all || libs.count(path::filename(file->archiveName))))
      return;
    ArrayRef<Symbol *> symbols = file->getSymbols();
    if (isa<ELFFileBase>(file))
      symbols = cast<ELFFileBase>(file)->getGlobalSymbols();
    for (Symbol *sym : symbols) {
      if (!sym->isUndefined() && sym->file == file) {
        sym->versionId = VER_NDX_LOCAL;
        sym->isExported = false;
      }
    }
  };

  for (ELFFileBase *file : ctx.objectFiles)
    visit(file);

  for (BitcodeFile *file : ctx.bitcodeFiles)
    visit(file);
}

// Force Sym to be entered in the output.
static void handleUndefined(Ctx &ctx, Symbol *sym, const char *option) {
  // Since a symbol may not be used inside the program, LTO may
  // eliminate it. Mark the symbol as "used" to prevent it.
  sym->isUsedInRegularObj = true;

  if (!sym->isLazy())
    return;
  sym->extract(ctx);
  if (!ctx.arg.whyExtract.empty())
    ctx.whyExtractRecords.emplace_back(option, sym->file, *sym);
}

// As an extension to GNU linkers, lld supports a variant of `-u`
// which accepts wildcard patterns. All symbols that match a given
// pattern are handled as if they were given by `-u`.
static void handleUndefinedGlob(Ctx &ctx, StringRef arg) {
  Expected<GlobPattern> pat = GlobPattern::create(arg);
  if (!pat) {
    ErrAlways(ctx) << "--undefined-glob: " << pat.takeError() << ": " << arg;
    return;
  }

  // Calling sym->extract() in the loop is not safe because it may add new
  // symbols to the symbol table, invalidating the current iterator.
  SmallVector<Symbol *, 0> syms;
  for (Symbol *sym : ctx.symtab->getSymbols())
    if (!sym->isPlaceholder() && pat->match(sym->getName()))
      syms.push_back(sym);

  for (Symbol *sym : syms)
    handleUndefined(ctx, sym, "--undefined-glob");
}

static void handleLibcall(Ctx &ctx, StringRef name) {
  Symbol *sym = ctx.symtab->find(name);
  if (sym && sym->isLazy() && isa<BitcodeFile>(sym->file)) {
    if (!ctx.arg.whyExtract.empty())
      ctx.whyExtractRecords.emplace_back("<libcall>", sym->file, *sym);
    sym->extract(ctx);
  }
}

static void writeArchiveStats(Ctx &ctx) {
  if (ctx.arg.printArchiveStats.empty())
    return;

  std::error_code ec;
  raw_fd_ostream os = ctx.openAuxiliaryFile(ctx.arg.printArchiveStats, ec);
  if (ec) {
    ErrAlways(ctx) << "--print-archive-stats=: cannot open "
                   << ctx.arg.printArchiveStats << ": " << ec.message();
    return;
  }

  os << "members\textracted\tarchive\n";

  DenseMap<CachedHashStringRef, unsigned> extracted;
  for (ELFFileBase *file : ctx.objectFiles)
    if (file->archiveName.size())
      ++extracted[CachedHashStringRef(file->archiveName)];
  for (BitcodeFile *file : ctx.bitcodeFiles)
    if (file->archiveName.size())
      ++extracted[CachedHashStringRef(file->archiveName)];
  for (std::pair<StringRef, unsigned> f : ctx.driver.archiveFiles) {
    unsigned &v = extracted[CachedHashString(f.first)];
    os << f.second << '\t' << v << '\t' << f.first << '\n';
    // If the archive occurs multiple times, other instances have a count of 0.
    v = 0;
  }
}

static void writeWhyExtract(Ctx &ctx) {
  if (ctx.arg.whyExtract.empty())
    return;

  std::error_code ec;
  raw_fd_ostream os = ctx.openAuxiliaryFile(ctx.arg.whyExtract, ec);
  if (ec) {
    ErrAlways(ctx) << "cannot open --why-extract= file " << ctx.arg.whyExtract
                   << ": " << ec.message();
    return;
  }

  os << "reference\textracted\tsymbol\n";
  for (auto &entry : ctx.whyExtractRecords) {
    os << std::get<0>(entry) << '\t' << toStr(ctx, std::get<1>(entry)) << '\t'
       << toStr(ctx, std::get<2>(entry)) << '\n';
  }
}

static void reportBackrefs(Ctx &ctx) {
  for (auto &ref : ctx.backwardReferences) {
    const Symbol &sym = *ref.first;
    std::string to = toStr(ctx, ref.second.second);
    // Some libraries have known problems and can cause noise. Filter them out
    // with --warn-backrefs-exclude=. The value may look like (for --start-lib)
    // *.o or (archive member) *.a(*.o).
    bool exclude = false;
    for (const llvm::GlobPattern &pat : ctx.arg.warnBackrefsExclude)
      if (pat.match(to)) {
        exclude = true;
        break;
      }
    if (!exclude)
      Warn(ctx) << "backward reference detected: " << sym.getName() << " in "
                << ref.second.first << " refers to " << to;
  }
}

// Handle --dependency-file=<path>. If that option is given, lld creates a
// file at a given path with the following contents:
//
//   <output-file>: <input-file> ...
//
//   <input-file>:
//
// where <output-file> is a pathname of an output file and <input-file>
// ... is a list of pathnames of all input files. `make` command can read a
// file in the above format and interpret it as a dependency info. We write
// phony targets for every <input-file> to avoid an error when that file is
// removed.
//
// This option is useful if you want to make your final executable to depend
// on all input files including system libraries. Here is why.
//
// When you write a Makefile, you usually write it so that the final
// executable depends on all user-generated object files. Normally, you
// don't make your executable to depend on system libraries (such as libc)
// because you don't know the exact paths of libraries, even though system
// libraries that are linked to your executable statically are technically a
// part of your program. By using --dependency-file option, you can make
// lld to dump dependency info so that you can maintain exact dependencies
// easily.
static void writeDependencyFile(Ctx &ctx) {
  std::error_code ec;
  raw_fd_ostream os = ctx.openAuxiliaryFile(ctx.arg.dependencyFile, ec);
  if (ec) {
    ErrAlways(ctx) << "cannot open " << ctx.arg.dependencyFile << ": "
                   << ec.message();
    return;
  }

  // We use the same escape rules as Clang/GCC which are accepted by Make/Ninja:
  // * A space is escaped by a backslash which itself must be escaped.
  // * A hash sign is escaped by a single backslash.
  // * $ is escapes as $$.
  auto printFilename = [](raw_fd_ostream &os, StringRef filename) {
    llvm::SmallString<256> nativePath;
    llvm::sys::path::native(filename.str(), nativePath);
    llvm::sys::path::remove_dots(nativePath, /*remove_dot_dot=*/true);
    for (unsigned i = 0, e = nativePath.size(); i != e; ++i) {
      if (nativePath[i] == '#') {
        os << '\\';
      } else if (nativePath[i] == ' ') {
        os << '\\';
        unsigned j = i;
        while (j > 0 && nativePath[--j] == '\\')
          os << '\\';
      } else if (nativePath[i] == '$') {
        os << '$';
      }
      os << nativePath[i];
    }
  };

  os << ctx.arg.outputFile << ":";
  for (StringRef path : ctx.arg.dependencyFiles) {
    os << " \\\n ";
    printFilename(os, path);
  }
  os << "\n";

  for (StringRef path : ctx.arg.dependencyFiles) {
    os << "\n";
    printFilename(os, path);
    os << ":\n";
  }
}

// Replaces common symbols with defined symbols reside in .bss sections.
// This function is called after all symbol names are resolved. As a
// result, the passes after the symbol resolution won't see any
// symbols of type CommonSymbol.
static void replaceCommonSymbols(Ctx &ctx) {
  llvm::TimeTraceScope timeScope("Replace common symbols");
  for (ELFFileBase *file : ctx.objectFiles) {
    if (!file->hasCommonSyms)
      continue;
    for (Symbol *sym : file->getGlobalSymbols()) {
      auto *s = dyn_cast<CommonSymbol>(sym);
      if (!s)
        continue;

      auto *bss = make<BssSection>(ctx, "COMMON", s->size, s->alignment);
      bss->file = s->file;
      ctx.inputSections.push_back(bss);
      Defined(ctx, s->file, StringRef(), s->binding, s->stOther, s->type,
              /*value=*/0, s->size, bss)
          .overwrite(*s);
    }
  }
}

// The section referred to by `s` is considered address-significant. Set the
// keepUnique flag on the section if appropriate.
static void markAddrsig(bool icfSafe, Symbol *s) {
  // We don't need to keep text sections unique under --icf=all even if they
  // are address-significant.
  if (auto *d = dyn_cast_or_null<Defined>(s))
    if (auto *sec = dyn_cast_or_null<InputSectionBase>(d->section))
      if (icfSafe || !(sec->flags & SHF_EXECINSTR))
        sec->keepUnique = true;
}

// Record sections that define symbols mentioned in --keep-unique <symbol>
// and symbols referred to by address-significance tables. These sections are
// ineligible for ICF.
template <class ELFT>
static void findKeepUniqueSections(Ctx &ctx, opt::InputArgList &args) {
  for (auto *arg : args.filtered(OPT_keep_unique)) {
    StringRef name = arg->getValue();
    auto *d = dyn_cast_or_null<Defined>(ctx.symtab->find(name));
    if (!d || !d->section) {
      Warn(ctx) << "could not find symbol " << name << " to keep unique";
      continue;
    }
    if (auto *sec = dyn_cast<InputSectionBase>(d->section))
      sec->keepUnique = true;
  }

  // --icf=all --ignore-data-address-equality means that we can ignore
  // the dynsym and address-significance tables entirely.
  if (ctx.arg.icf == ICFLevel::All && ctx.arg.ignoreDataAddressEquality)
    return;

  // Symbols in the dynsym could be address-significant in other executables
  // or DSOs, so we conservatively mark them as address-significant.
  bool icfSafe = ctx.arg.icf == ICFLevel::Safe;
  for (Symbol *sym : ctx.symtab->getSymbols())
    if (sym->isExported)
      markAddrsig(icfSafe, sym);

  // Visit the address-significance table in each object file and mark each
  // referenced symbol as address-significant.
  for (InputFile *f : ctx.objectFiles) {
    auto *obj = cast<ObjFile<ELFT>>(f);
    ArrayRef<Symbol *> syms = obj->getSymbols();
    if (obj->addrsigSec) {
      ArrayRef<uint8_t> contents =
          check(obj->getObj().getSectionContents(*obj->addrsigSec));
      const uint8_t *cur = contents.begin();
      while (cur != contents.end()) {
        unsigned size;
        const char *err = nullptr;
        uint64_t symIndex = decodeULEB128(cur, &size, contents.end(), &err);
        if (err) {
          Err(ctx) << f << ": could not decode addrsig section: " << err;
          break;
        }
        markAddrsig(icfSafe, syms[symIndex]);
        cur += size;
      }
    } else {
      // If an object file does not have an address-significance table,
      // conservatively mark all of its symbols as address-significant.
      for (Symbol *s : syms)
        markAddrsig(icfSafe, s);
    }
  }
}

// This function reads a symbol partition specification section. These sections
// are used to control which partition a symbol is allocated to. See
// https://lld.llvm.org/Partitions.html for more details on partitions.
template <typename ELFT>
static void readSymbolPartitionSection(Ctx &ctx, InputSectionBase *s) {
  // Read the relocation that refers to the partition's entry point symbol.
  Symbol *sym;
  const RelsOrRelas<ELFT> rels = s->template relsOrRelas<ELFT>();
  auto readEntry = [](InputFile *file, const auto &rels) -> Symbol * {
    for (const auto &rel : rels)
      return &file->getRelocTargetSym(rel);
    return nullptr;
  };
  if (rels.areRelocsCrel())
    sym = readEntry(s->file, rels.crels);
  else if (rels.areRelocsRel())
    sym = readEntry(s->file, rels.rels);
  else
    sym = readEntry(s->file, rels.relas);
  if (!isa_and_nonnull<Defined>(sym) || !sym->isExported)
    return;

  StringRef partName = reinterpret_cast<const char *>(s->content().data());
  for (Partition &part : ctx.partitions) {
    if (part.name == partName) {
      sym->partition = part.getNumber(ctx);
      return;
    }
  }

  // Forbid partitions from being used on incompatible targets, and forbid them
  // from being used together with various linker features that assume a single
  // set of output sections.
  if (ctx.script->hasSectionsCommand)
    ErrAlways(ctx) << s->file
                   << ": partitions cannot be used with the SECTIONS command";
  if (ctx.script->hasPhdrsCommands())
    ErrAlways(ctx) << s->file
                   << ": partitions cannot be used with the PHDRS command";
  if (!ctx.arg.sectionStartMap.empty())
    ErrAlways(ctx) << s->file
                   << ": partitions cannot be used with "
                      "--section-start, -Ttext, -Tdata or -Tbss";
  if (ctx.arg.emachine == EM_MIPS)
    ErrAlways(ctx) << s->file << ": partitions cannot be used on this target";

  // Impose a limit of no more than 254 partitions. This limit comes from the
  // sizes of the Partition fields in InputSectionBase and Symbol, as well as
  // the amount of space devoted to the partition number in RankFlags.
  if (ctx.partitions.size() == 254)
    Fatal(ctx) << "may not have more than 254 partitions";

  ctx.partitions.emplace_back(ctx);
  Partition &newPart = ctx.partitions.back();
  newPart.name = partName;
  sym->partition = newPart.getNumber(ctx);
}

static void markBuffersAsDontNeed(Ctx &ctx, bool skipLinkedOutput) {
  // With --thinlto-index-only, all buffers are nearly unused from now on
  // (except symbol/section names used by infrequent passes). Mark input file
  // buffers as MADV_DONTNEED so that these pages can be reused by the expensive
  // thin link, saving memory.
  if (skipLinkedOutput) {
    for (MemoryBuffer &mb : llvm::make_pointee_range(ctx.memoryBuffers))
      mb.dontNeedIfMmap();
    return;
  }

  // Otherwise, just mark MemoryBuffers backing BitcodeFiles.
  DenseSet<const char *> bufs;
  for (BitcodeFile *file : ctx.bitcodeFiles)
    bufs.insert(file->mb.getBufferStart());
  for (BitcodeFile *file : ctx.lazyBitcodeFiles)
    bufs.insert(file->mb.getBufferStart());
  for (MemoryBuffer &mb : llvm::make_pointee_range(ctx.memoryBuffers))
    if (bufs.count(mb.getBufferStart()))
      mb.dontNeedIfMmap();
}

// This function is where all the optimizations of link-time
// optimization takes place. When LTO is in use, some input files are
// not in native object file format but in the LLVM bitcode format.
// This function compiles bitcode files into a few big native files
// using LLVM functions and replaces bitcode symbols with the results.
// Because all bitcode files that the program consists of are passed to
// the compiler at once, it can do a whole-program optimization.
template <class ELFT>
void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) {
  llvm::TimeTraceScope timeScope("LTO");
  // Compile bitcode files and replace bitcode symbols.
  lto.reset(new BitcodeCompiler(ctx));
  for (BitcodeFile *file : ctx.bitcodeFiles)
    lto->add(*file);

  if (!ctx.bitcodeFiles.empty())
    markBuffersAsDontNeed(ctx, skipLinkedOutput);

  ltoObjectFiles = lto->compile();
  for (auto &file : ltoObjectFiles) {
    auto *obj = cast<ObjFile<ELFT>>(file.get());
    obj->parse(/*ignoreComdats=*/true);

    // This is only needed for AArch64 PAuth to set correct key in AUTH GOT
    // entry based on symbol type (STT_FUNC or not).
    // TODO: check if PAuth is actually used.
    if (ctx.arg.emachine == EM_AARCH64) {
      for (typename ELFT::Sym elfSym : obj->template getGlobalELFSyms<ELFT>()) {
        StringRef elfSymName = check(elfSym.getName(obj->getStringTable()));
        if (Symbol *sym = ctx.symtab->find(elfSymName))
          if (sym->type == STT_NOTYPE)
            sym->type = elfSym.getType();
      }
    }

    // For defined symbols in non-relocatable output,
    // compute isExported and parse '@'.
    if (!ctx.arg.relocatable)
      for (Symbol *sym : obj->getGlobalSymbols()) {
        if (!sym->isDefined())
          continue;
        if (ctx.arg.exportDynamic && sym->computeBinding(ctx) != STB_LOCAL)
          sym->isExported = true;
        if (sym->hasVersionSuffix)
          sym->parseSymbolVersion(ctx);
      }
    ctx.objectFiles.push_back(obj);
  }
}

// The --wrap option is a feature to rename symbols so that you can write
// wrappers for existing functions. If you pass `--wrap=foo`, all
// occurrences of symbol `foo` are resolved to `__wrap_foo` (so, you are
// expected to write `__wrap_foo` function as a wrapper). The original
// symbol becomes accessible as `__real_foo`, so you can call that from your
// wrapper.
//
// This data structure is instantiated for each --wrap option.
struct WrappedSymbol {
  Symbol *sym;
  Symbol *real;
  Symbol *wrap;
};

// Handles --wrap option.
//
// This function instantiates wrapper symbols. At this point, they seem
// like they are not being used at all, so we explicitly set some flags so
// that LTO won't eliminate them.
static std::vector<WrappedSymbol> addWrappedSymbols(Ctx &ctx,
                                                    opt::InputArgList &args) {
  std::vector<WrappedSymbol> v;
  DenseSet<StringRef> seen;
  auto &ss = ctx.saver;
  for (auto *arg : args.filtered(OPT_wrap)) {
    StringRef name = arg->getValue();
    if (!seen.insert(name).second)
      continue;

    Symbol *sym = ctx.symtab->find(name);
    if (!sym)
      continue;

    Symbol *wrap =
        ctx.symtab->addUnusedUndefined(ss.save("__wrap_" + name), sym->binding);

    // If __real_ is referenced, pull in the symbol if it is lazy. Do this after
    // processing __wrap_ as that may have referenced __real_.
    StringRef realName = ctx.saver.save("__real_" + name);
    if (Symbol *real = ctx.symtab->find(realName)) {
      ctx.symtab->addUnusedUndefined(name, sym->binding);
      // Update sym's binding, which will replace real's later in
      // SymbolTable::wrap.
      sym->binding = real->binding;
    }

    Symbol *real = ctx.symtab->addUnusedUndefined(realName);
    v.push_back({sym, real, wrap});

    // We want to tell LTO not to inline symbols to be overwritten
    // because LTO doesn't know the final symbol contents after renaming.
    real->scriptDefined = true;
    sym->scriptDefined = true;

    // If a symbol is referenced in any object file, bitcode file or shared
    // object, mark its redirection target (foo for __real_foo and __wrap_foo
    // for foo) as referenced after redirection, which will be used to tell LTO
    // to not eliminate the redirection target. If the object file defining the
    // symbol also references it, we cannot easily distinguish the case from
    // cases where the symbol is not referenced. Retain the redirection target
    // in this case because we choose to wrap symbol references regardless of
    // whether the symbol is defined
    // (https://sourceware.org/bugzilla/show_bug.cgi?id=26358).
    if (real->referenced || real->isDefined())
      sym->referencedAfterWrap = true;
    if (sym->referenced || sym->isDefined())
      wrap->referencedAfterWrap = true;
  }
  return v;
}

static void combineVersionedSymbol(Ctx &ctx, Symbol &sym,
                                   DenseMap<Symbol *, Symbol *> &map) {
  const char *suffix1 = sym.getVersionSuffix();
  if (suffix1[0] != '@' || suffix1[1] == '@')
    return;

  // Check the existing symbol foo. We have two special cases to handle:
  //
  // * There is a definition of foo@v1 and foo@@v1.
  // * There is a definition of foo@v1 and foo.
  Defined *sym2 = dyn_cast_or_null<Defined>(ctx.symtab->find(sym.getName()));
  if (!sym2)
    return;
  const char *suffix2 = sym2->getVersionSuffix();
  if (suffix2[0] == '@' && suffix2[1] == '@' &&
      strcmp(suffix1 + 1, suffix2 + 2) == 0) {
    // foo@v1 and foo@@v1 should be merged, so redirect foo@v1 to foo@@v1.
    map.try_emplace(&sym, sym2);
    // If both foo@v1 and foo@@v1 are defined and non-weak, report a
    // duplicate definition error.
    if (sym.isDefined()) {
      sym2->checkDuplicate(ctx, cast<Defined>(sym));
      sym2->resolve(ctx, cast<Defined>(sym));
    } else if (sym.isUndefined()) {
      sym2->resolve(ctx, cast<Undefined>(sym));
    } else {
      sym2->resolve(ctx, cast<SharedSymbol>(sym));
    }
    // Eliminate foo@v1 from the symbol table.
    sym.symbolKind = Symbol::PlaceholderKind;
    sym.isUsedInRegularObj = false;
  } else if (auto *sym1 = dyn_cast<Defined>(&sym)) {
    if (sym2->versionId > VER_NDX_GLOBAL
            ? ctx.arg.versionDefinitions[sym2->versionId].name == suffix1 + 1
            : sym1->section == sym2->section && sym1->value == sym2->value) {
      // Due to an assembler design flaw, if foo is defined, .symver foo,
      // foo@v1 defines both foo and foo@v1. Unless foo is bound to a
      // different version, GNU ld makes foo@v1 canonical and eliminates
      // foo. Emulate its behavior, otherwise we would have foo or foo@@v1
      // beside foo@v1. foo@v1 and foo combining does not apply if they are
      // not defined in the same place.
      map.try_emplace(sym2, &sym);
      sym2->symbolKind = Symbol::PlaceholderKind;
      sym2->isUsedInRegularObj = false;
    }
  }
}

// Do renaming for --wrap and foo@v1 by updating pointers to symbols.
//
// When this function is executed, only InputFiles and symbol table
// contain pointers to symbol objects. We visit them to replace pointers,
// so that wrapped symbols are swapped as instructed by the command line.
static void redirectSymbols(Ctx &ctx, ArrayRef<WrappedSymbol> wrapped) {
  llvm::TimeTraceScope timeScope("Redirect symbols");
  DenseMap<Symbol *, Symbol *> map;
  for (const WrappedSymbol &w : wrapped) {
    map[w.sym] = w.wrap;
    map[w.real] = w.sym;
  }

  // If there are version definitions (versionDefinitions.size() > 2), enumerate
  // symbols with a non-default version (foo@v1) and check whether it should be
  // combined with foo or foo@@v1.
  if (ctx.arg.versionDefinitions.size() > 2)
    for (Symbol *sym : ctx.symtab->getSymbols())
      if (sym->hasVersionSuffix)
        combineVersionedSymbol(ctx, *sym, map);

  if (map.empty())
    return;

  // Update pointers in input files.
  parallelForEach(ctx.objectFiles, [&](ELFFileBase *file) {
    for (Symbol *&sym : file->getMutableGlobalSymbols())
      if (Symbol *s = map.lookup(sym))
        sym = s;
  });

  // Update pointers in the symbol table.
  for (const WrappedSymbol &w : wrapped)
    ctx.symtab->wrap(w.sym, w.real, w.wrap);
}

// To enable CET (x86's hardware-assisted control flow enforcement), each
// source file must be compiled with -fcf-protection. Object files compiled
// with the flag contain feature flags indicating that they are compatible
// with CET. We enable the feature only when all object files are compatible
// with CET.
//
// This is also the case with AARCH64's BTI and PAC which use the similar
// GNU_PROPERTY_AARCH64_FEATURE_1_AND mechanism.
//
// For AArch64 PAuth-enabled object files, the core info of all of them must
// match. Missing info for some object files with matching info for remaining
// ones can be allowed (see -z pauth-report).
//
// RISC-V Zicfilp/Zicfiss extension also use the same mechanism to record
// enabled features in the GNU_PROPERTY_RISCV_FEATURE_1_AND bit mask.
static void readSecurityNotes(Ctx &ctx) {
  if (ctx.arg.emachine != EM_386 && ctx.arg.emachine != EM_X86_64 &&
      ctx.arg.emachine != EM_AARCH64 && ctx.arg.emachine != EM_RISCV)
    return;

  ctx.arg.andFeatures = -1;

  StringRef referenceFileName;
  if (ctx.arg.emachine == EM_AARCH64) {
    auto it = llvm::find_if(ctx.objectFiles, [](const ELFFileBase *f) {
      return f->aarch64PauthAbiCoreInfo.has_value();
    });
    if (it != ctx.objectFiles.end()) {
      ctx.aarch64PauthAbiCoreInfo = (*it)->aarch64PauthAbiCoreInfo;
      referenceFileName = (*it)->getName();
    }
  }
  bool hasValidPauthAbiCoreInfo =
      ctx.aarch64PauthAbiCoreInfo && ctx.aarch64PauthAbiCoreInfo->isValid();

  auto report = [&](ReportPolicy policy) -> ELFSyncStream {
    return {ctx, toDiagLevel(policy)};
  };
  auto reportUnless = [&](ReportPolicy policy, bool cond) -> ELFSyncStream {
    if (cond)
      return {ctx, DiagLevel::None};
    return {ctx, toDiagLevel(policy)};
  };
  for (ELFFileBase *f : ctx.objectFiles) {
    uint32_t features = f->andFeatures;

    reportUnless(ctx.arg.zBtiReport,
                 features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
        << f
        << ": -z bti-report: file does not have "
           "GNU_PROPERTY_AARCH64_FEATURE_1_BTI property";

    reportUnless(ctx.arg.zGcsReport,
                 features & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)
        << f
        << ": -z gcs-report: file does not have "
           "GNU_PROPERTY_AARCH64_FEATURE_1_GCS property";

    reportUnless(ctx.arg.zCetReport, features & GNU_PROPERTY_X86_FEATURE_1_IBT)
        << f
        << ": -z cet-report: file does not have "
           "GNU_PROPERTY_X86_FEATURE_1_IBT property";

    reportUnless(ctx.arg.zCetReport,
                 features & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
        << f
        << ": -z cet-report: file does not have "
           "GNU_PROPERTY_X86_FEATURE_1_SHSTK property";

    if (ctx.arg.emachine == EM_RISCV) {
      reportUnless(ctx.arg.zZicfilpUnlabeledReport,
                   features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED)
          << f
          << ": -z zicfilp-unlabeled-report: file does not have "
             "GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED property";

      reportUnless(ctx.arg.zZicfilpFuncSigReport,
                   features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG)
          << f
          << ": -z zicfilp-func-sig-report: file does not have "
             "GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG property";

      if ((features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED) &&
          (features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG))
        Err(ctx) << f
                 << ": file has conflicting properties: "
                    "GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED and "
                    "GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG";

      reportUnless(ctx.arg.zZicfissReport,
                   features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS)
          << f
          << ": -z zicfiss-report: file does not have "
             "GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS property";

      if (ctx.arg.zZicfilp == ZicfilpPolicy::Unlabeled &&
          (features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG))
        Warn(ctx) << f
                  << ": -z zicfilp=unlabeled: file has conflicting property: "
                     "GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG";

      if (ctx.arg.zZicfilp == ZicfilpPolicy::FuncSig &&
          (features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED))
        Warn(ctx) << f
                  << ": -z zicfilp=func-sig: file has conflicting property: "
                     "GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED";
    }

    if (ctx.arg.zForceBti && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) {
      features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
      if (ctx.arg.zBtiReport == ReportPolicy::None)
        Warn(ctx) << f
                  << ": -z force-bti: file does not have "
                     "GNU_PROPERTY_AARCH64_FEATURE_1_BTI property";
    } else if (ctx.arg.zForceIbt &&
               !(features & GNU_PROPERTY_X86_FEATURE_1_IBT)) {
      if (ctx.arg.zCetReport == ReportPolicy::None)
        Warn(ctx) << f
                  << ": -z force-ibt: file does not have "
                     "GNU_PROPERTY_X86_FEATURE_1_IBT property";
      features |= GNU_PROPERTY_X86_FEATURE_1_IBT;
    }
    if (ctx.arg.zPacPlt && !(hasValidPauthAbiCoreInfo ||
                             (features & GNU_PROPERTY_AARCH64_FEATURE_1_PAC))) {
      Warn(ctx) << f
                << ": -z pac-plt: file does not have "
                   "GNU_PROPERTY_AARCH64_FEATURE_1_PAC property and no valid "
                   "PAuth core info present for this link job";
      features |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
    }
    ctx.arg.andFeatures &= features;

    if (!ctx.aarch64PauthAbiCoreInfo)
      continue;

    if (!f->aarch64PauthAbiCoreInfo) {
      report(ctx.arg.zPauthReport)
          << f
          << ": -z pauth-report: file does not have AArch64 "
             "PAuth core info while '"
          << referenceFileName << "' has one";
      continue;
    }

    if (ctx.aarch64PauthAbiCoreInfo != f->aarch64PauthAbiCoreInfo)
      Err(ctx)
          << "incompatible values of AArch64 PAuth core info found\n"
          << "platform:\n"
          << ">>> " << referenceFileName << ": 0x"
          << toHex(ctx.aarch64PauthAbiCoreInfo->platform, /*LowerCase=*/true)
          << "\n>>> " << f << ": 0x"
          << toHex(f->aarch64PauthAbiCoreInfo->platform, /*LowerCase=*/true)
          << "\nversion:\n"
          << ">>> " << referenceFileName << ": 0x"
          << toHex(ctx.aarch64PauthAbiCoreInfo->version, /*LowerCase=*/true)
          << "\n>>> " << f << ": 0x"
          << toHex(f->aarch64PauthAbiCoreInfo->version, /*LowerCase=*/true);
  }

  // Force enable Shadow Stack.
  if (ctx.arg.zShstk)
    ctx.arg.andFeatures |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;

  // Force enable/disable GCS
  if (ctx.arg.zGcs == GcsPolicy::Always)
    ctx.arg.andFeatures |= GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
  else if (ctx.arg.zGcs == GcsPolicy::Never)
    ctx.arg.andFeatures &= ~GNU_PROPERTY_AARCH64_FEATURE_1_GCS;

  if (ctx.arg.emachine == EM_RISCV) {
    // Force enable/disable Zicfilp.
    if (ctx.arg.zZicfilp == ZicfilpPolicy::Unlabeled) {
      ctx.arg.andFeatures |= GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED;
      ctx.arg.andFeatures &= ~GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG;
    } else if (ctx.arg.zZicfilp == ZicfilpPolicy::FuncSig) {
      ctx.arg.andFeatures |= GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG;
      ctx.arg.andFeatures &= ~GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED;
    } else if (ctx.arg.zZicfilp == ZicfilpPolicy::Never)
      ctx.arg.andFeatures &= ~(GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED |
                               GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG);

    // Force enable/disable Zicfiss.
    if (ctx.arg.zZicfiss == ZicfissPolicy::Always)
      ctx.arg.andFeatures |= GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS;
    else if (ctx.arg.zZicfiss == ZicfissPolicy::Never)
      ctx.arg.andFeatures &= ~GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS;
  }

  // If we are utilising GCS at any stage, the sharedFiles should be checked to
  // ensure they also support this feature. The gcs-report-dynamic option is
  // used to indicate if the user wants information relating to this, and will
  // be set depending on the user's input, or warning if gcs-report is set to
  // either `warning` or `error`.
  if (ctx.arg.andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)
    for (SharedFile *f : ctx.sharedFiles)
      reportUnless(ctx.arg.zGcsReportDynamic,
                   f->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)
          << f
          << ": GCS is required by -z gcs, but this shared library lacks the "
             "necessary property note. The "
          << "dynamic loader might not enable GCS or refuse to load the "
             "program unless all shared library "
          << "dependencies have the GCS marking.";
}

static void initSectionsAndLocalSyms(ELFFileBase *file, bool ignoreComdats) {
  switch (file->ekind) {
  case ELF32LEKind:
    cast<ObjFile<ELF32LE>>(file)->initSectionsAndLocalSyms(ignoreComdats);
    break;
  case ELF32BEKind:
    cast<ObjFile<ELF32BE>>(file)->initSectionsAndLocalSyms(ignoreComdats);
    break;
  case ELF64LEKind:
    cast<ObjFile<ELF64LE>>(file)->initSectionsAndLocalSyms(ignoreComdats);
    break;
  case ELF64BEKind:
    cast<ObjFile<ELF64BE>>(file)->initSectionsAndLocalSyms(ignoreComdats);
    break;
  default:
    llvm_unreachable("");
  }
}

static void postParseObjectFile(ELFFileBase *file) {
  switch (file->ekind) {
  case ELF32LEKind:
    cast<ObjFile<ELF32LE>>(file)->postParse();
    break;
  case ELF32BEKind:
    cast<ObjFile<ELF32BE>>(file)->postParse();
    break;
  case ELF64LEKind:
    cast<ObjFile<ELF64LE>>(file)->postParse();
    break;
  case ELF64BEKind:
    cast<ObjFile<ELF64BE>>(file)->postParse();
    break;
  default:
    llvm_unreachable("");
  }
}

// Do actual linking. Note that when this function is called,
// all linker scripts have already been parsed.
template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
  llvm::TimeTraceScope timeScope("Link", StringRef("LinkerDriver::Link"));

  // Handle --trace-symbol.
  for (auto *arg : args.filtered(OPT_trace_symbol))
    ctx.symtab->insert(arg->getValue())->traced = true;

  ctx.internalFile = createInternalFile(ctx, "<internal>");

  // Handle -u/--undefined before input files. If both a.a and b.so define foo,
  // -u foo a.a b.so will extract a.a.
  for (StringRef name : ctx.arg.undefined)
    ctx.symtab->addUnusedUndefined(name)->referenced = true;

  parseFiles(ctx, files);

  // Create dynamic sections for dynamic linking and static PIE.
  ctx.hasDynsym = !ctx.sharedFiles.empty() || ctx.arg.isPic;
  ctx.arg.exportDynamic &= ctx.hasDynsym;

  // Preemptibility of undefined symbols when ctx.hasDynsym is true. Default is
  // true for dynamic linking.
  ctx.arg.zDynamicUndefined =
      getZFlag(args, "dynamic-undefined-weak", "nodynamic-undefined-weak",
               ctx.sharedFiles.size() || ctx.arg.shared) &&
      ctx.hasDynsym;

  // If an entry symbol is in a static archive, pull out that file now.
  if (Symbol *sym = ctx.symtab->find(ctx.arg.entry))
    handleUndefined(ctx, sym, "--entry");

  // Handle the `--undefined-glob <pattern>` options.
  for (StringRef pat : args::getStrings(args, OPT_undefined_glob))
    handleUndefinedGlob(ctx, pat);

  // After potential archive member extraction involving ENTRY and
  // -u/--undefined-glob, check whether PROVIDE symbols should be defined (the
  // RHS may refer to definitions in just extracted object files).
  ctx.script->addScriptReferencedSymbolsToSymTable();

  // Prevent LTO from removing any definition referenced by -u.
  for (StringRef name : ctx.arg.undefined)
    if (Defined *sym = dyn_cast_or_null<Defined>(ctx.symtab->find(name)))
      sym->isUsedInRegularObj = true;

  // Mark -init and -fini symbols so that the LTO doesn't eliminate them.
  if (Symbol *sym = dyn_cast_or_null<Defined>(ctx.symtab->find(ctx.arg.init)))
    sym->isUsedInRegularObj = true;
  if (Symbol *sym = dyn_cast_or_null<Defined>(ctx.symtab->find(ctx.arg.fini)))
    sym->isUsedInRegularObj = true;

  // If any of our inputs are bitcode files, the LTO code generator may create
  // references to certain library functions that might not be explicit in the
  // bitcode file's symbol table. If any of those library functions are defined
  // in a bitcode file in an archive member, we need to arrange to use LTO to
  // compile those archive members by adding them to the link beforehand.
  //
  // However, adding all libcall symbols to the link can have undesired
  // consequences. For example, the libgcc implementation of
  // __sync_val_compare_and_swap_8 on 32-bit ARM pulls in an .init_array entry
  // that aborts the program if the Linux kernel does not support 64-bit
  // atomics, which would prevent the program from running even if it does not
  // use 64-bit atomics.
  //
  // Therefore, we only add libcall symbols to the link before LTO if we have
  // to, i.e. if the symbol's definition is in bitcode. Any other required
  // libcall symbols will be added to the link after LTO when we add the LTO
  // object file to the link.
  if (!ctx.bitcodeFiles.empty()) {
    llvm::Triple TT(ctx.bitcodeFiles.front()->obj->getTargetTriple());
    for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT))
      handleLibcall(ctx, s);
  }

  // Archive members defining __wrap symbols may be extracted.
  std::vector<WrappedSymbol> wrapped = addWrappedSymbols(ctx, args);

  // No more lazy bitcode can be extracted at this point. Do post parse work
  // like checking duplicate symbols.
  parallelForEach(ctx.objectFiles, [](ELFFileBase *file) {
    initSectionsAndLocalSyms(file, /*ignoreComdats=*/false);
  });
  parallelForEach(ctx.objectFiles, postParseObjectFile);
  parallelForEach(ctx.bitcodeFiles,
                  [](BitcodeFile *file) { file->postParse(); });
  for (auto &it : ctx.nonPrevailingSyms) {
    Symbol &sym = *it.first;
    Undefined(sym.file, sym.getName(), sym.binding, sym.stOther, sym.type,
              it.second)
        .overwrite(sym);
    cast<Undefined>(sym).nonPrevailing = true;
  }
  ctx.nonPrevailingSyms.clear();
  for (const DuplicateSymbol &d : ctx.duplicates)
    reportDuplicate(ctx, *d.sym, d.file, d.section, d.value);
  ctx.duplicates.clear();

  // Return if there were name resolution errors.
  if (errCount(ctx))
    return;

  // We want to declare linker script's symbols early,
  // so that we can version them.
  // They also might be exported if referenced by DSOs.
  ctx.script->declareSymbols();

  // Handle --exclude-libs. This is before scanVersionScript() due to a
  // workaround for Android ndk: for a defined versioned symbol in an archive
  // without a version node in the version script, Android does not expect a
  // 'has undefined version' error in -shared --exclude-libs=ALL mode (PR36295).
  // GNU ld errors in this case.
  if (args.hasArg(OPT_exclude_libs))
    excludeLibs(ctx, args);

  // Create elfHeader early. We need a dummy section in
  // addReservedSymbols to mark the created symbols as not absolute.
  ctx.out.elfHeader = std::make_unique<OutputSection>(ctx, "", 0, SHF_ALLOC);

  // We need to create some reserved symbols such as _end. Create them.
  if (!ctx.arg.relocatable)
    addReservedSymbols(ctx);

  // Apply version scripts.
  //
  // For a relocatable output, version scripts don't make sense, and
  // parsing a symbol version string (e.g. dropping "@ver1" from a symbol
  // name "foo@ver1") rather do harm, so we don't call this if -r is given.
  if (!ctx.arg.relocatable) {
    llvm::TimeTraceScope timeScope("Process symbol versions");
    ctx.symtab->scanVersionScript();

    parseVersionAndComputeIsPreemptible(ctx);
  }

  // Skip the normal linked output if some LTO options are specified.
  //
  // For --thinlto-index-only, index file creation is performed in
  // compileBitcodeFiles, so we are done afterwards. --plugin-opt=emit-llvm and
  // --plugin-opt=emit-asm create output files in bitcode or assembly code,
  // respectively. When only certain thinLTO modules are specified for
  // compilation, the intermediate object file are the expected output.
  const bool skipLinkedOutput = ctx.arg.thinLTOIndexOnly || ctx.arg.emitLLVM ||
                                ctx.arg.ltoEmitAsm ||
                                !ctx.arg.thinLTOModulesToCompile.empty();

  // Handle --lto-validate-all-vtables-have-type-infos.
  if (ctx.arg.ltoValidateAllVtablesHaveTypeInfos)
    ltoValidateAllVtablesHaveTypeInfos<ELFT>(ctx, args);

  // Do link-time optimization if given files are LLVM bitcode files.
  // This compiles bitcode files into real object files.
  //
  // With this the symbol table should be complete. After this, no new names
  // except a few linker-synthesized ones will be added to the symbol table.
  const size_t numObjsBeforeLTO = ctx.objectFiles.size();
  const size_t numInputFilesBeforeLTO = ctx.driver.files.size();
  compileBitcodeFiles<ELFT>(skipLinkedOutput);

  // Symbol resolution finished. Report backward reference problems,
  // --print-archive-stats=, and --why-extract=.
  reportBackrefs(ctx);
  writeArchiveStats(ctx);
  writeWhyExtract(ctx);
  if (errCount(ctx))
    return;

  // Bail out if normal linked output is skipped due to LTO.
  if (skipLinkedOutput)
    return;

  // compileBitcodeFiles may have produced lto.tmp object files. After this, no
  // more file will be added.
  auto newObjectFiles = ArrayRef(ctx.objectFiles).slice(numObjsBeforeLTO);
  parallelForEach(newObjectFiles, [](ELFFileBase *file) {
    initSectionsAndLocalSyms(file, /*ignoreComdats=*/true);
  });
  parallelForEach(newObjectFiles, postParseObjectFile);
  for (const DuplicateSymbol &d : ctx.duplicates)
    reportDuplicate(ctx, *d.sym, d.file, d.section, d.value);

  // ELF dependent libraries may have introduced new input files after LTO has
  // completed. This is an error if the files haven't already been parsed, since
  // changing the symbol table could break the semantic assumptions of LTO.
  auto newInputFiles = ArrayRef(ctx.driver.files).slice(numInputFilesBeforeLTO);
  if (!newInputFiles.empty()) {
    DenseSet<StringRef> oldFilenames;
    for (auto &f : ArrayRef(ctx.driver.files).slice(0, numInputFilesBeforeLTO))
      oldFilenames.insert(f->getName());
    for (auto &newFile : newInputFiles)
      if (!oldFilenames.contains(newFile->getName()))
        Err(ctx) << "input file '" << newFile->getName() << "' added after LTO";
  }

  // Handle --exclude-libs again because lto.tmp may reference additional
  // libcalls symbols defined in an excluded archive. This may override
  // versionId set by scanVersionScript() and isExported.
  if (args.hasArg(OPT_exclude_libs))
    excludeLibs(ctx, args);

  // Record [__acle_se_<sym>, <sym>] pairs for later processing.
  processArmCmseSymbols(ctx);

  // Apply symbol renames for --wrap and combine foo@v1 and foo@@v1.
  redirectSymbols(ctx, wrapped);

  // Replace common symbols with regular symbols.
  replaceCommonSymbols(ctx);

  {
    llvm::TimeTraceScope timeScope("Aggregate sections");
    // Now that we have a complete list of input files.
    // Beyond this point, no new files are added.
    // Aggregate all input sections into one place.
    for (InputFile *f : ctx.objectFiles) {
      for (InputSectionBase *s : f->getSections()) {
        if (!s || s == &InputSection::discarded)
          continue;
        if (LLVM_UNLIKELY(isa<EhInputSection>(s)))
          ctx.ehInputSections.push_back(cast<EhInputSection>(s));
        else
          ctx.inputSections.push_back(s);
      }
    }
    for (BinaryFile *f : ctx.binaryFiles)
      for (InputSectionBase *s : f->getSections())
        ctx.inputSections.push_back(cast<InputSection>(s));
  }

  {
    llvm::TimeTraceScope timeScope("Strip sections");
    if (ctx.hasSympart.load(std::memory_order_relaxed)) {
      llvm::erase_if(ctx.inputSections, [&ctx = ctx](InputSectionBase *s) {
        if (s->type != SHT_LLVM_SYMPART)
          return false;
        readSymbolPartitionSection<ELFT>(ctx, s);
        return true;
      });
    }
    // We do not want to emit debug sections if --strip-all
    // or --strip-debug are given.
    if (ctx.arg.strip != StripPolicy::None) {
      llvm::erase_if(ctx.inputSections, [](InputSectionBase *s) {
        if (isDebugSection(*s))
          return true;
        if (auto *isec = dyn_cast<InputSection>(s))
          if (InputSectionBase *rel = isec->getRelocatedSection())
            if (isDebugSection(*rel))
              return true;

        return false;
      });
    }
  }

  // Since we now have a complete set of input files, we can create
  // a .d file to record build dependencies.
  if (!ctx.arg.dependencyFile.empty())
    writeDependencyFile(ctx);

  // Now that the number of partitions is fixed, save a pointer to the main
  // partition.
  ctx.mainPart = &ctx.partitions[0];

  // Read .note.gnu.property sections from input object files which
  // contain a hint to tweak linker's and loader's behaviors.
  readSecurityNotes(ctx);

  // The Target instance handles target-specific stuff, such as applying
  // relocations or writing a PLT section. It also contains target-dependent
  // values such as a default image base address.
  setTarget(ctx);

  ctx.arg.eflags = ctx.target->calcEFlags();
  // maxPageSize (sometimes called abi page size) is the maximum page size that
  // the output can be run on. For example if the OS can use 4k or 64k page
  // sizes then maxPageSize must be 64k for the output to be useable on both.
  // All important alignment decisions must use this value.
  ctx.arg.maxPageSize = getMaxPageSize(ctx, args);
  // commonPageSize is the most common page size that the output will be run on.
  // For example if an OS can use 4k or 64k page sizes and 4k is more common
  // than 64k then commonPageSize is set to 4k. commonPageSize can be used for
  // optimizations such as DATA_SEGMENT_ALIGN in linker scripts. LLD's use of it
  // is limited to writing trap instructions on the last executable segment.
  ctx.arg.commonPageSize = getCommonPageSize(ctx, args);

  ctx.arg.imageBase = getImageBase(ctx, args);

  // This adds a .comment section containing a version string.
  if (!ctx.arg.relocatable)
    ctx.inputSections.push_back(createCommentSection(ctx));

  // Split SHF_MERGE and .eh_frame sections into pieces in preparation for garbage collection.
  splitSections<ELFT>(ctx);

  // Garbage collection and removal of shared symbols from unused shared objects.
  markLive<ELFT>(ctx);

  // Make copies of any input sections that need to be copied into each
  // partition.
  copySectionsIntoPartitions(ctx);

  if (canHaveMemtagGlobals(ctx)) {
    llvm::TimeTraceScope timeScope("Process memory tagged symbols");
    createTaggedSymbols(ctx);
  }

  // Create synthesized sections such as .got and .plt. This is called before
  // processSectionCommands() so that they can be placed by SECTIONS commands.
  createSyntheticSections<ELFT>(ctx);

  // Some input sections that are used for exception handling need to be moved
  // into synthetic sections. Do that now so that they aren't assigned to
  // output sections in the usual way.
  if (!ctx.arg.relocatable)
    combineEhSections(ctx);

  // Merge .riscv.attributes sections.
  if (ctx.arg.emachine == EM_RISCV)
    mergeRISCVAttributesSections(ctx);

  {
    llvm::TimeTraceScope timeScope("Assign sections");

    // Create output sections described by SECTIONS commands.
    ctx.script->processSectionCommands();

    // Linker scripts control how input sections are assigned to output
    // sections. Input sections that were not handled by scripts are called
    // "orphans", and they are assigned to output sections by the default rule.
    // Process that.
    ctx.script->addOrphanSections();
  }

  {
    llvm::TimeTraceScope timeScope("Merge/finalize input sections");

    // Migrate InputSectionDescription::sectionBases to sections. This includes
    // merging MergeInputSections into a single MergeSyntheticSection. From this
    // point onwards InputSectionDescription::sections should be used instead of
    // sectionBases.
    for (SectionCommand *cmd : ctx.script->sectionCommands)
      if (auto *osd = dyn_cast<OutputDesc>(cmd))
        osd->osec.finalizeInputSections();
  }

  // Two input sections with different output sections should not be folded.
  // ICF runs after processSectionCommands() so that we know the output sections.
  if (ctx.arg.icf != ICFLevel::None) {
    findKeepUniqueSections<ELFT>(ctx, args);
    doIcf<ELFT>(ctx);
  }

  // Read the callgraph now that we know what was gced or icfed
  if (ctx.arg.callGraphProfileSort != CGProfileSortKind::None) {
    if (auto *arg = args.getLastArg(OPT_call_graph_ordering_file)) {
      if (std::optional<MemoryBufferRef> buffer =
              readFile(ctx, arg->getValue()))
        readCallGraph(ctx, *buffer);
    } else
      readCallGraphsFromObjectFiles<ELFT>(ctx);
  }

  // Write the result to the file.
  writeResult<ELFT>(ctx);
}
