//===- 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 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 "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/Driver.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Filesystem.h"
#include "lld/Common/Memory.h"
#include "lld/Common/Strings.h"
#include "lld/Common/TargetOptionsCommandFlags.h"
#include "lld/Common/Threads.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TarWriter.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#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;

Configuration *elf::Config;
LinkerDriver *elf::Driver;

static void setConfigs(opt::InputArgList &Args);
static void readConfigs(opt::InputArgList &Args);

bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
               raw_ostream &Error) {
  errorHandler().LogName = args::getFilenameWithoutExe(Args[0]);
  errorHandler().ErrorLimitExceededMsg =
      "too many errors emitted, stopping now (use "
      "-error-limit=0 to see all errors)";
  errorHandler().ErrorOS = &Error;
  errorHandler().ExitEarly = CanExitEarly;
  errorHandler().ColorDiagnostics = Error.has_colors();

  InputSections.clear();
  OutputSections.clear();
  BinaryFiles.clear();
  BitcodeFiles.clear();
  ObjectFiles.clear();
  SharedFiles.clear();

  Config = make<Configuration>();
  Driver = make<LinkerDriver>();
  Script = make<LinkerScript>();
  Symtab = make<SymbolTable>();

  Tar = nullptr;
  memset(&In, 0, sizeof(In));

  Partitions = {Partition()};

  SharedFile::VernauxNum = 0;

  Config->ProgName = Args[0];

  Driver->main(Args);

  // Exit immediately if we don't need to return to the caller.
  // This saves time because the overhead of calling destructors
  // for all globally-allocated objects is not negligible.
  if (CanExitEarly)
    exitLld(errorCount() ? 1 : 0);

  freeArena();
  return !errorCount();
}

// Parses a linker -m option.
static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) {
  uint8_t OSABI = 0;
  StringRef S = Emul;
  if (S.endswith("_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", "aarch64_elf64_le_vec",
                 {ELF64LEKind, EM_AARCH64})
          .Cases("armelf", "armelf_linux_eabi", {ELF32LEKind, 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})
          .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})
          .Default({ELFNoneKind, EM_NONE});

  if (Ret.first == ELFNoneKind)
    error("unknown emulation: " + Emul);
  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(
    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() && Tar;
  for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) {
    Archive::Child C =
        CHECK(COrErr, MB.getBufferIdentifier() +
                          ": could not get the child of the archive");
    MemoryBufferRef MBRef =
        CHECK(C.getMemoryBufferRef(),
              MB.getBufferIdentifier() +
                  ": could not get the buffer for a child of the archive");
    if (AddToTar)
      Tar->append(relativeToRoot(check(C.getFullName())), MBRef.getBuffer());
    V.push_back(std::make_pair(MBRef, C.getChildOffset()));
  }
  if (Err)
    fatal(MB.getBufferIdentifier() + ": Archive::children failed: " +
          toString(std::move(Err)));

  // Take ownership of memory buffers created for members of thin archives.
  for (std::unique_ptr<MemoryBuffer> &MB : File->takeThinBuffers())
    make<std::unique_ptr<MemoryBuffer>>(std::move(MB));

  return V;
}

// 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;

  Optional<MemoryBufferRef> Buffer = readFile(Path);
  if (!Buffer.hasValue())
    return;
  MemoryBufferRef MBRef = *Buffer;

  if (Config->FormatBinary) {
    Files.push_back(make<BinaryFile>(MBRef));
    return;
  }

  switch (identify_magic(MBRef.getBuffer())) {
  case file_magic::unknown:
    readLinkerScript(MBRef);
    return;
  case file_magic::archive: {
    // Handle -whole-archive.
    if (InWholeArchive) {
      for (const auto &P : getArchiveMembers(MBRef))
        Files.push_back(createObjectFile(P.first, Path, P.second));
      return;
    }

    std::unique_ptr<Archive> File =
        CHECK(Archive::create(MBRef), Path + ": failed to parse archive");

    // If an archive file has no symbol table, it is likely that a user
    // is attempting LTO and using a default ar command that doesn't
    // understand the LLVM bitcode file. It is a pretty common error, so
    // we'll handle it as if it had a symbol table.
    if (!File->isEmpty() && !File->hasSymbolTable()) {
      // Check if all members are bitcode files. If not, ignore, which is the
      // default action without the LTO hack described above.
      for (const std::pair<MemoryBufferRef, uint64_t> &P :
           getArchiveMembers(MBRef))
        if (identify_magic(P.first.getBuffer()) != file_magic::bitcode)
          return;

      for (const std::pair<MemoryBufferRef, uint64_t> &P :
           getArchiveMembers(MBRef))
        Files.push_back(make<LazyObjFile>(P.first, Path, P.second));
      return;
    }

    // Handle the regular case.
    Files.push_back(make<ArchiveFile>(std::move(File)));
    return;
  }
  case file_magic::elf_shared_object:
    if (Config->Static || Config->Relocatable) {
      error("attempted static link of dynamic object " + Path);
      return;
    }

    // DSOs usually have DT_SONAME tags in their ELF headers, and the
    // sonames are used to identify DSOs. But if they are missing,
    // they are identified by filenames. We don't know whether the new
    // file has a DT_SONAME or not because we haven't parsed it yet.
    // Here, we set the default soname for the file because we might
    // need it later.
    //
    // If a file was specified by -lfoo, the directory part is not
    // significant, as a user did not specify it. This behavior is
    // compatible with GNU.
    Files.push_back(
        make<SharedFile>(MBRef, WithLOption ? path::filename(Path) : Path));
    return;
  case file_magic::bitcode:
  case file_magic::elf_relocatable:
    if (InLib)
      Files.push_back(make<LazyObjFile>(MBRef, "", 0));
    else
      Files.push_back(createObjectFile(MBRef));
    break;
  default:
    error(Path + ": unknown file type");
  }
}

// Add a given library by searching it from input search paths.
void LinkerDriver::addLibrary(StringRef Name) {
  if (Optional<std::string> Path = searchLibrary(Name))
    addFile(*Path, /*WithLOption=*/true);
  else
    error("unable to find library -l" + 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() {
  // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup
  // table which is a relatively new feature.
  if (Config->EMachine == EM_MIPS && Config->GnuHash)
    error("the .gnu.hash section is not compatible with the MIPS target");

  if (Config->FixCortexA53Errata843419 && Config->EMachine != EM_AARCH64)
    error("--fix-cortex-a53-843419 is only supported on AArch64 targets");

  if (Config->TocOptimize && Config->EMachine != EM_PPC64)
    error("--toc-optimize is only supported on the PowerPC64 target");

  if (Config->Pie && Config->Shared)
    error("-shared and -pie may not be used together");

  if (!Config->Shared && !Config->FilterList.empty())
    error("-F may not be used without -shared");

  if (!Config->Shared && !Config->AuxiliaryList.empty())
    error("-f may not be used without -shared");

  if (!Config->Relocatable && !Config->DefineCommon)
    error("-no-define-common not supported in non relocatable output");

  if (Config->ZText && Config->ZIfuncNoplt)
    error("-z text and -z ifunc-noplt may not be used together");

  if (Config->Relocatable) {
    if (Config->Shared)
      error("-r and -shared may not be used together");
    if (Config->GcSections)
      error("-r and --gc-sections may not be used together");
    if (Config->GdbIndex)
      error("-r and --gdb-index may not be used together");
    if (Config->ICF != ICFLevel::None)
      error("-r and --icf may not be used together");
    if (Config->Pie)
      error("-r and -pie may not be used together");
  }

  if (Config->ExecuteOnly) {
    if (Config->EMachine != EM_AARCH64)
      error("-execute-only is only supported on AArch64 targets");

    if (Config->SingleRoRx && !Script->HasSectionsCommand)
      error("-execute-only and -no-rosegment cannot be used together");
  }

  if (Config->ZRetpolineplt && Config->RequireCET)
    error("--require-cet 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) {
  for (auto *Arg : Args.filtered(OPT_z))
    if (Key == Arg->getValue())
      return true;
  return false;
}

static bool getZFlag(opt::InputArgList &Args, StringRef K1, StringRef K2,
                     bool Default) {
  for (auto *Arg : Args.filtered_reverse(OPT_z)) {
    if (K1 == Arg->getValue())
      return true;
    if (K2 == Arg->getValue())
      return false;
  }
  return Default;
}

static bool isKnownZFlag(StringRef S) {
  return S == "combreloc" || S == "copyreloc" || S == "defs" ||
         S == "execstack" || S == "global" || S == "hazardplt" ||
         S == "ifunc-noplt" || S == "initfirst" || S == "interpose" ||
         S == "keep-text-section-prefix" || S == "lazy" || S == "muldefs" ||
         S == "nocombreloc" || S == "nocopyreloc" || S == "nodefaultlib" ||
         S == "nodelete" || S == "nodlopen" || S == "noexecstack" ||
         S == "nokeep-text-section-prefix" || S == "norelro" || S == "notext" ||
         S == "now" || S == "origin" || S == "relro" || S == "retpolineplt" ||
         S == "rodynamic" || S == "text" || S == "wxneeded" ||
         S.startswith("common-page-size") || S.startswith("max-page-size=") ||
         S.startswith("stack-size=");
}

// Report an error for an unknown -z option.
static void checkZOptions(opt::InputArgList &Args) {
  for (auto *Arg : Args.filtered(OPT_z))
    if (!isKnownZFlag(Arg->getValue()))
      error("unknown -z value: " + StringRef(Arg->getValue()));
}

void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
  ELFOptTable Parser;
  opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));

  // Interpret this flag early because error() depends on them.
  errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20);
  checkZOptions(Args);

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

  // Handle -v or -version.
  //
  // A note about "compatible with GNU linkers" message: this is a hack for
  // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and
  // still the newest version in March 2017) or earlier to recognize LLD as
  // a GNU compatible linker. As long as an output for the -v option
  // contains "GNU" or "with BFD", they recognize us as GNU-compatible.
  //
  // 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))
    message(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) {
      Tar = std::move(*ErrOrWriter);
      Tar->append("response.txt", createResponseFile(Args));
      Tar->append("version.txt", getLLDVersion() + "\n");
    } else {
      error("--reproduce: " + toString(ErrOrWriter.takeError()));
    }
  }

  readConfigs(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;

  initLLVM();
  createFiles(Args);
  if (errorCount())
    return;

  inferMachineType();
  setConfigs(Args);
  checkOptions();
  if (errorCount())
    return;

  // 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.
  Target = getTarget();

  switch (Config->EKind) {
  case ELF32LEKind:
    link<ELF32LE>(Args);
    return;
  case ELF32BEKind:
    link<ELF32BE>(Args);
    return;
  case ELF64LEKind:
    link<ELF64LE>(Args);
    return;
  case ELF64BEKind:
    link<ELF64BE>(Args);
    return;
  default:
    llvm_unreachable("unknown Config->EKind");
  }
}

static std::string getRpath(opt::InputArgList &Args) {
  std::vector<StringRef> 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 UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &Args) {
  UnresolvedPolicy ErrorOrWarn = Args.hasFlag(OPT_error_unresolved_symbols,
                                              OPT_warn_unresolved_symbols, true)
                                     ? UnresolvedPolicy::ReportError
                                     : UnresolvedPolicy::Warn;

  // Process the last of -unresolved-symbols, -no-undefined or -z defs.
  for (auto *Arg : llvm::reverse(Args)) {
    switch (Arg->getOption().getID()) {
    case OPT_unresolved_symbols: {
      StringRef S = Arg->getValue();
      if (S == "ignore-all" || S == "ignore-in-object-files")
        return UnresolvedPolicy::Ignore;
      if (S == "ignore-in-shared-libs" || S == "report-all")
        return ErrorOrWarn;
      error("unknown --unresolved-symbols value: " + S);
      continue;
    }
    case OPT_no_undefined:
      return ErrorOrWarn;
    case OPT_z:
      if (StringRef(Arg->getValue()) == "defs")
        return ErrorOrWarn;
      continue;
    }
  }

  // -shared implies -unresolved-symbols=ignore-all because missing
  // symbols are likely to be resolved at runtime using other DSOs.
  if (Config->Shared)
    return UnresolvedPolicy::Ignore;
  return ErrorOrWarn;
}

static Target2Policy getTarget2(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;
  error("unknown --target2 option: " + S);
  return Target2Policy::GotRel;
}

static bool isOutputFormatBinary(opt::InputArgList &Args) {
  StringRef S = Args.getLastArgValue(OPT_oformat, "elf");
  if (S == "binary")
    return true;
  if (!S.startswith("elf"))
    error("unknown --oformat value: " + S);
  return false;
}

static DiscardPolicy getDiscard(opt::InputArgList &Args) {
  if (Args.hasArg(OPT_relocatable))
    return DiscardPolicy::None;

  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(opt::InputArgList &Args) {
  auto *Arg = Args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker);
  if (!Arg || Arg->getOption().getID() == OPT_no_dynamic_linker)
    return "";
  return Arg->getValue();
}

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 StripPolicy getStrip(opt::InputArgList &Args) {
  if (Args.hasArg(OPT_relocatable))
    return StripPolicy::None;

  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(StringRef S, const opt::Arg &Arg) {
  uint64_t VA = 0;
  if (S.startswith("0x"))
    S = S.drop_front(2);
  if (!to_integer(S, VA, 16))
    error("invalid argument: " + toString(Arg));
  return VA;
}

static StringMap<uint64_t> getSectionStartMap(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(Addr, *Arg);
  }

  if (auto *Arg = Args.getLastArg(OPT_Ttext))
    Ret[".text"] = parseSectionAddress(Arg->getValue(), *Arg);
  if (auto *Arg = Args.getLastArg(OPT_Tdata))
    Ret[".data"] = parseSectionAddress(Arg->getValue(), *Arg);
  if (auto *Arg = Args.getLastArg(OPT_Tbss))
    Ret[".bss"] = parseSectionAddress(Arg->getValue(), *Arg);
  return Ret;
}

static SortSectionPolicy getSortSection(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())
    error("unknown --sort-section rule: " + S);
  return SortSectionPolicy::Default;
}

static OrphanHandlingPolicy getOrphanHandling(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")
    error("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, std::vector<uint8_t>>
getBuildId(opt::InputArgList &Args) {
  auto *Arg = Args.getLastArg(OPT_build_id, OPT_build_id_eq);
  if (!Arg)
    return {BuildIdKind::None, {}};

  if (Arg->getOption().getID() == OPT_build_id)
    return {BuildIdKind::Fast, {}};

  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.startswith("0x"))
    return {BuildIdKind::Hexstring, parseHex(S.substr(2))};

  if (S != "none")
    error("unknown --build-id style: " + S);
  return {BuildIdKind::None, {}};
}

static std::pair<bool, bool> getPackDynRelocs(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")
    error("unknown -pack-dyn-relocs format: " + S);
  return {false, false};
}

static void readCallGraph(MemoryBufferRef MB) {
  // Build a map from symbol name to section
  DenseMap<StringRef, Symbol *> Map;
  for (InputFile *File : ObjectFiles)
    for (Symbol *Sym : File->getSymbols())
      Map[Sym->getName()] = Sym;

  auto FindSection = [&](StringRef Name) -> InputSectionBase * {
    Symbol *Sym = Map.lookup(Name);
    if (!Sym) {
      if (Config->WarnSymbolOrdering)
        warn(MB.getBufferIdentifier() + ": no such symbol: " + Name);
      return nullptr;
    }
    maybeWarnUnorderableSymbol(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)) {
      error(MB.getBufferIdentifier() + ": parse error");
      return;
    }

    if (InputSectionBase *From = FindSection(Fields[0]))
      if (InputSectionBase *To = FindSection(Fields[1]))
        Config->CallGraphProfile[std::make_pair(From, To)] += Count;
  }
}

template <class ELFT> static void readCallGraphsFromObjectFiles() {
  for (auto File : ObjectFiles) {
    auto *Obj = cast<ObjFile<ELFT>>(File);

    for (const Elf_CGProfile_Impl<ELFT> &CGPE : Obj->CGProfile) {
      auto *FromSym = dyn_cast<Defined>(&Obj->getSymbol(CGPE.cgp_from));
      auto *ToSym = dyn_cast<Defined>(&Obj->getSymbol(CGPE.cgp_to));
      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)
        Config->CallGraphProfile[{From, To}] += CGPE.cgp_weight;
    }
  }
}

static bool getCompressDebugSections(opt::InputArgList &Args) {
  StringRef S = Args.getLastArgValue(OPT_compress_debug_sections, "none");
  if (S == "none")
    return false;
  if (S != "zlib")
    error("unknown --compress-debug-sections value: " + S);
  if (!zlib::isAvailable())
    error("--compress-debug-sections: zlib is not available");
  return true;
}

static std::pair<StringRef, StringRef> getOldNewOptions(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())
    error(Arg->getSpelling() + " expects 'old;new' format, but got " + S);
  return Ret;
}

// Parse the symbol ordering file and warn for any duplicate entries.
static std::vector<StringRef> getSymbolOrderingFile(MemoryBufferRef MB) {
  SetVector<StringRef> Names;
  for (StringRef S : args::getLines(MB))
    if (!Names.insert(S) && Config->WarnSymbolOrdering)
      warn(MB.getBufferIdentifier() + ": duplicate ordered symbol: " + S);

  return Names.takeVector();
}

static void parseClangOption(StringRef Opt, const Twine &Msg) {
  std::string Err;
  raw_string_ostream OS(Err);

  const char *Argv[] = {Config->ProgName.data(), Opt.data()};
  if (cl::ParseCommandLineOptions(2, Argv, "", &OS))
    return;
  OS.flush();
  error(Msg + ": " + StringRef(Err).trim());
}

// Initializes Config members by the command line options.
static void readConfigs(opt::InputArgList &Args) {
  errorHandler().Verbose = Args.hasArg(OPT_verbose);
  errorHandler().FatalWarnings =
      Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
  ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true);

  Config->AllowMultipleDefinition =
      Args.hasFlag(OPT_allow_multiple_definition,
                   OPT_no_allow_multiple_definition, false) ||
      hasZOption(Args, "muldefs");
  Config->AllowShlibUndefined =
      Args.hasFlag(OPT_allow_shlib_undefined, OPT_no_allow_shlib_undefined,
                   Args.hasArg(OPT_shared));
  Config->AuxiliaryList = args::getStrings(Args, OPT_auxiliary);
  Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
  Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);
  Config->CheckSections =
      Args.hasFlag(OPT_check_sections, OPT_no_check_sections, true);
  Config->Chroot = Args.getLastArgValue(OPT_chroot);
  Config->CompressDebugSections = getCompressDebugSections(Args);
  Config->Cref = Args.hasFlag(OPT_cref, OPT_no_cref, false);
  Config->DefineCommon = Args.hasFlag(OPT_define_common, OPT_no_define_common,
                                      !Args.hasArg(OPT_relocatable));
  Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true);
  Config->DependentLibraries = Args.hasFlag(OPT_dependent_libraries, OPT_no_dependent_libraries, true);
  Config->DisableVerify = Args.hasArg(OPT_disable_verify);
  Config->Discard = getDiscard(Args);
  Config->DwoDir = Args.getLastArgValue(OPT_plugin_opt_dwo_dir_eq);
  Config->DynamicLinker = getDynamicLinker(Args);
  Config->EhFrameHdr =
      Args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false);
  Config->EmitLLVM = Args.hasArg(OPT_plugin_opt_emit_llvm, false);
  Config->EmitRelocs = Args.hasArg(OPT_emit_relocs);
  Config->CallGraphProfileSort = Args.hasFlag(
      OPT_call_graph_profile_sort, OPT_no_call_graph_profile_sort, true);
  Config->EnableNewDtags =
      Args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true);
  Config->Entry = Args.getLastArgValue(OPT_entry);
  Config->ExecuteOnly =
      Args.hasFlag(OPT_execute_only, OPT_no_execute_only, false);
  Config->ExportDynamic =
      Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false);
  Config->FilterList = args::getStrings(Args, OPT_filter);
  Config->Fini = Args.getLastArgValue(OPT_fini, "_fini");
  Config->FixCortexA53Errata843419 = Args.hasArg(OPT_fix_cortex_a53_843419);
  Config->RequireCET = Args.hasArg(OPT_require_cet);
  Config->GcSections = Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false);
  Config->GnuUnique = Args.hasFlag(OPT_gnu_unique, OPT_no_gnu_unique, true);
  Config->GdbIndex = Args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false);
  Config->ICF = getICF(Args);
  Config->IgnoreDataAddressEquality =
      Args.hasArg(OPT_ignore_data_address_equality);
  Config->IgnoreFunctionAddressEquality =
      Args.hasArg(OPT_ignore_function_address_equality);
  Config->Init = Args.getLastArgValue(OPT_init, "_init");
  Config->LTOAAPipeline = Args.getLastArgValue(OPT_lto_aa_pipeline);
  Config->LTOCSProfileGenerate = Args.hasArg(OPT_lto_cs_profile_generate);
  Config->LTOCSProfileFile = Args.getLastArgValue(OPT_lto_cs_profile_file);
  Config->LTODebugPassManager = Args.hasArg(OPT_lto_debug_pass_manager);
  Config->LTONewPassManager = Args.hasArg(OPT_lto_new_pass_manager);
  Config->LTONewPmPasses = Args.getLastArgValue(OPT_lto_newpm_passes);
  Config->LTOO = args::getInteger(Args, OPT_lto_O, 2);
  Config->LTOObjPath = Args.getLastArgValue(OPT_plugin_opt_obj_path_eq);
  Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1);
  Config->LTOSampleProfile = Args.getLastArgValue(OPT_lto_sample_profile);
  Config->MapFile = Args.getLastArgValue(OPT_Map);
  Config->MipsGotSize = args::getInteger(Args, OPT_mips_got_size, 0xfff0);
  Config->MergeArmExidx =
      Args.hasFlag(OPT_merge_exidx_entries, OPT_no_merge_exidx_entries, true);
  Config->Nmagic = Args.hasFlag(OPT_nmagic, OPT_no_nmagic, false);
  Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec);
  Config->Nostdlib = Args.hasArg(OPT_nostdlib);
  Config->OFormatBinary = isOutputFormatBinary(Args);
  Config->Omagic = Args.hasFlag(OPT_omagic, OPT_no_omagic, false);
  Config->OptRemarksFilename = Args.getLastArgValue(OPT_opt_remarks_filename);
  Config->OptRemarksPasses = Args.getLastArgValue(OPT_opt_remarks_passes);
  Config->OptRemarksWithHotness = Args.hasArg(OPT_opt_remarks_with_hotness);
  Config->Optimize = args::getInteger(Args, OPT_O, 1);
  Config->OrphanHandling = getOrphanHandling(Args);
  Config->OutputFile = Args.getLastArgValue(OPT_o);
  Config->Pie = Args.hasFlag(OPT_pie, OPT_no_pie, false);
  Config->PrintIcfSections =
      Args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false);
  Config->PrintGcSections =
      Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
  Config->PrintSymbolOrder =
      Args.getLastArgValue(OPT_print_symbol_order);
  Config->Rpath = getRpath(Args);
  Config->Relocatable = Args.hasArg(OPT_relocatable);
  Config->SaveTemps = Args.hasArg(OPT_save_temps);
  Config->SearchPaths = args::getStrings(Args, OPT_library_path);
  Config->SectionStartMap = getSectionStartMap(Args);
  Config->Shared = Args.hasArg(OPT_shared);
  Config->SingleRoRx = Args.hasArg(OPT_no_rosegment);
  Config->SoName = Args.getLastArgValue(OPT_soname);
  Config->SortSection = getSortSection(Args);
  Config->SplitStackAdjustSize = args::getInteger(Args, OPT_split_stack_adjust_size, 16384);
  Config->Strip = getStrip(Args);
  Config->Sysroot = Args.getLastArgValue(OPT_sysroot);
  Config->Target1Rel = Args.hasFlag(OPT_target1_rel, OPT_target1_abs, false);
  Config->Target2 = getTarget2(Args);
  Config->ThinLTOCacheDir = Args.getLastArgValue(OPT_thinlto_cache_dir);
  Config->ThinLTOCachePolicy = CHECK(
      parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)),
      "--thinlto-cache-policy: invalid cache policy");
  Config->ThinLTOEmitImportsFiles =
      Args.hasArg(OPT_plugin_opt_thinlto_emit_imports_files);
  Config->ThinLTOIndexOnly = Args.hasArg(OPT_plugin_opt_thinlto_index_only) ||
                             Args.hasArg(OPT_plugin_opt_thinlto_index_only_eq);
  Config->ThinLTOIndexOnlyArg =
      Args.getLastArgValue(OPT_plugin_opt_thinlto_index_only_eq);
  Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u);
  Config->ThinLTOObjectSuffixReplace =
      getOldNewOptions(Args, OPT_plugin_opt_thinlto_object_suffix_replace_eq);
  Config->ThinLTOPrefixReplace =
      getOldNewOptions(Args, OPT_plugin_opt_thinlto_prefix_replace_eq);
  Config->Trace = Args.hasArg(OPT_trace);
  Config->Undefined = args::getStrings(Args, OPT_undefined);
  Config->UndefinedVersion =
      Args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, true);
  Config->UseAndroidRelrTags = Args.hasFlag(
      OPT_use_android_relr_tags, OPT_no_use_android_relr_tags, false);
  Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args);
  Config->WarnBackrefs =
      Args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false);
  Config->WarnCommon = Args.hasFlag(OPT_warn_common, OPT_no_warn_common, false);
  Config->WarnIfuncTextrel =
      Args.hasFlag(OPT_warn_ifunc_textrel, OPT_no_warn_ifunc_textrel, false);
  Config->WarnSymbolOrdering =
      Args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true);
  Config->ZCombreloc = getZFlag(Args, "combreloc", "nocombreloc", true);
  Config->ZCopyreloc = getZFlag(Args, "copyreloc", "nocopyreloc", true);
  Config->ZExecstack = getZFlag(Args, "execstack", "noexecstack", false);
  Config->ZGlobal = hasZOption(Args, "global");
  Config->ZHazardplt = hasZOption(Args, "hazardplt");
  Config->ZIfuncNoplt = hasZOption(Args, "ifunc-noplt");
  Config->ZInitfirst = hasZOption(Args, "initfirst");
  Config->ZInterpose = hasZOption(Args, "interpose");
  Config->ZKeepTextSectionPrefix = getZFlag(
      Args, "keep-text-section-prefix", "nokeep-text-section-prefix", false);
  Config->ZNodefaultlib = hasZOption(Args, "nodefaultlib");
  Config->ZNodelete = hasZOption(Args, "nodelete");
  Config->ZNodlopen = hasZOption(Args, "nodlopen");
  Config->ZNow = getZFlag(Args, "now", "lazy", false);
  Config->ZOrigin = hasZOption(Args, "origin");
  Config->ZRelro = getZFlag(Args, "relro", "norelro", true);
  Config->ZRetpolineplt = hasZOption(Args, "retpolineplt");
  Config->ZRodynamic = hasZOption(Args, "rodynamic");
  Config->ZStackSize = args::getZOptionValue(Args, OPT_z, "stack-size", 0);
  Config->ZText = getZFlag(Args, "text", "notext", true);
  Config->ZWxneeded = hasZOption(Args, "wxneeded");

  // Parse LTO options.
  if (auto *Arg = Args.getLastArg(OPT_plugin_opt_mcpu_eq))
    parseClangOption(Saver.save("-mcpu=" + StringRef(Arg->getValue())),
                     Arg->getSpelling());

  for (auto *Arg : Args.filtered(OPT_plugin_opt))
    parseClangOption(Arg->getValue(), Arg->getSpelling());

  // Parse -mllvm options.
  for (auto *Arg : Args.filtered(OPT_mllvm))
    parseClangOption(Arg->getValue(), Arg->getSpelling());

  if (Config->LTOO > 3)
    error("invalid optimization level for LTO: " + Twine(Config->LTOO));
  if (Config->LTOPartitions == 0)
    error("--lto-partitions: number of threads must be > 0");
  if (Config->ThinLTOJobs == 0)
    error("--thinlto-jobs: number of threads must be > 0");

  if (Config->SplitStackAdjustSize < 0)
    error("--split-stack-adjust-size: size must be >= 0");

  // Parse ELF{32,64}{LE,BE} and CPU type.
  if (auto *Arg = Args.getLastArg(OPT_m)) {
    StringRef S = Arg->getValue();
    std::tie(Config->EKind, Config->EMachine, Config->OSABI) =
        parseEmulation(S);
    Config->MipsN32Abi = (S == "elf32btsmipn32" || S == "elf32ltsmipn32");
    Config->Emulation = S;
  }

  // Parse -hash-style={sysv,gnu,both}.
  if (auto *Arg = Args.getLastArg(OPT_hash_style)) {
    StringRef S = Arg->getValue();
    if (S == "sysv")
      Config->SysvHash = true;
    else if (S == "gnu")
      Config->GnuHash = true;
    else if (S == "both")
      Config->SysvHash = Config->GnuHash = true;
    else
      error("unknown -hash-style: " + S);
  }

  if (Args.hasArg(OPT_print_map))
    Config->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.
  if (Config->Nmagic || Config->Omagic)
    Config->ZRelro = false;

  std::tie(Config->BuildId, Config->BuildIdVector) = getBuildId(Args);

  std::tie(Config->AndroidPackDynRelocs, Config->RelrPackDynRelocs) =
      getPackDynRelocs(Args);

  if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file)){
    if (Args.hasArg(OPT_call_graph_ordering_file))
      error("--symbol-ordering-file and --call-graph-order-file "
            "may not be used together");
    if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())){
      Config->SymbolOrderingFile = getSymbolOrderingFile(*Buffer);
      // Also need to disable CallGraphProfileSort to prevent
      // LLD order symbols with CGProfile
      Config->CallGraphProfileSort = false;
    }
  }

  // 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)) {
    Config->DefaultSymbolVersion = VER_NDX_LOCAL;
    if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
      for (StringRef S : args::getLines(*Buffer))
        Config->VersionScriptGlobals.push_back(
            {S, /*IsExternCpp*/ false, /*HasWildcard*/ false});
  }

  bool HasExportDynamic =
      Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false);

  // Parses -dynamic-list and -export-dynamic-symbol. They make some
  // symbols private. Note that -export-dynamic takes precedence over them
  // as it says all symbols should be exported.
  if (!HasExportDynamic) {
    for (auto *Arg : Args.filtered(OPT_dynamic_list))
      if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
        readDynamicList(*Buffer);

    for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol))
      Config->DynamicList.push_back(
          {Arg->getValue(), /*IsExternCpp*/ false, /*HasWildcard*/ false});
  }

  // If --export-dynamic-symbol=foo is given and symbol foo is defined in
  // an object file in an archive file, that object file should be pulled
  // out and linked. (It doesn't have to behave like that from technical
  // point of view, but this is needed for compatibility with GNU.)
  for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol))
    Config->Undefined.push_back(Arg->getValue());

  for (auto *Arg : Args.filtered(OPT_version_script))
    if (Optional<std::string> Path = searchScript(Arg->getValue())) {
      if (Optional<MemoryBufferRef> Buffer = readFile(*Path))
        readVersionScript(*Buffer);
    } else {
      error(Twine("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(opt::InputArgList &Args) {
  ELFKind K = Config->EKind;
  uint16_t M = Config->EMachine;

  Config->CopyRelocs = (Config->Relocatable || Config->EmitRelocs);
  Config->Is64 = (K == ELF64LEKind || K == ELF64BEKind);
  Config->IsLE = (K == ELF32LEKind || K == ELF64LEKind);
  Config->Endianness = Config->IsLE ? endianness::little : endianness::big;
  Config->IsMips64EL = (K == ELF64LEKind && M == EM_MIPS);
  Config->Pic = Config->Pie || Config->Shared;
  Config->PicThunk = Args.hasArg(OPT_pic_veneer, Config->Pic);
  Config->Wordsize = Config->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.
  //  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 don't know why ELF defined two
  // different mechanisms in the first place, but this is how the spec is
  // defined.
  //
  // You cannot choose which one, Rel or Rela, you want to use. Instead each
  // ABI defines which one you need to use. The following expression expresses
  // that.
  Config->IsRela = M == EM_AARCH64 || M == EM_AMDGPU || M == EM_HEXAGON ||
                   M == EM_PPC || M == EM_PPC64 || M == EM_RISCV ||
                   M == EM_X86_64;

  // 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.
  Config->WriteAddends = Args.hasFlag(OPT_apply_dynamic_relocs,
                                      OPT_no_apply_dynamic_relocs, false) ||
                         !Config->IsRela;

  Config->TocOptimize =
      Args.hasFlag(OPT_toc_optimize, OPT_no_toc_optimize, M == EM_PPC64);
}

// Returns a value of "-format" option.
static bool isFormatBinary(StringRef S) {
  if (S == "binary")
    return true;
  if (S == "elf" || S == "default")
    return false;
  error("unknown -format value: " + S +
        " (supported formats: elf, default, binary)");
  return false;
}

void LinkerDriver::createFiles(opt::InputArgList &Args) {
  // For --{push,pop}-state.
  std::vector<std::tuple<bool, bool, bool>> Stack;

  // Iterate over argv to process input files and positional arguments.
  for (auto *Arg : Args) {
    switch (Arg->getOption().getUnaliasedOption().getID()) {
    case OPT_library:
      addLibrary(Arg->getValue());
      break;
    case OPT_INPUT:
      addFile(Arg->getValue(), /*WithLOption=*/false);
      break;
    case OPT_defsym: {
      StringRef From;
      StringRef To;
      std::tie(From, To) = StringRef(Arg->getValue()).split('=');
      if (From.empty() || To.empty())
        error("-defsym: syntax error: " + StringRef(Arg->getValue()));
      else
        readDefsym(From, MemoryBufferRef(To, "-defsym"));
      break;
    }
    case OPT_script:
      if (Optional<std::string> Path = searchScript(Arg->getValue())) {
        if (Optional<MemoryBufferRef> MB = readFile(*Path))
          readLinkerScript(*MB);
        break;
      }
      error(Twine("cannot find linker script ") + Arg->getValue());
      break;
    case OPT_as_needed:
      Config->AsNeeded = true;
      break;
    case OPT_format:
      Config->FormatBinary = isFormatBinary(Arg->getValue());
      break;
    case OPT_no_as_needed:
      Config->AsNeeded = false;
      break;
    case OPT_Bstatic:
    case OPT_omagic:
    case OPT_nmagic:
      Config->Static = true;
      break;
    case OPT_Bdynamic:
      Config->Static = false;
      break;
    case OPT_whole_archive:
      InWholeArchive = true;
      break;
    case OPT_no_whole_archive:
      InWholeArchive = false;
      break;
    case OPT_just_symbols:
      if (Optional<MemoryBufferRef> MB = readFile(Arg->getValue())) {
        Files.push_back(createObjectFile(*MB));
        Files.back()->JustSymbols = true;
      }
      break;
    case OPT_start_group:
      if (InputFile::IsInGroup)
        error("nested --start-group");
      InputFile::IsInGroup = true;
      break;
    case OPT_end_group:
      if (!InputFile::IsInGroup)
        error("stray --end-group");
      InputFile::IsInGroup = false;
      ++InputFile::NextGroupId;
      break;
    case OPT_start_lib:
      if (InLib)
        error("nested --start-lib");
      if (InputFile::IsInGroup)
        error("may not nest --start-lib in --start-group");
      InLib = true;
      InputFile::IsInGroup = true;
      break;
    case OPT_end_lib:
      if (!InLib)
        error("stray --end-lib");
      InLib = false;
      InputFile::IsInGroup = false;
      ++InputFile::NextGroupId;
      break;
    case OPT_push_state:
      Stack.emplace_back(Config->AsNeeded, Config->Static, InWholeArchive);
      break;
    case OPT_pop_state:
      if (Stack.empty()) {
        error("unbalanced --push-state/--pop-state");
        break;
      }
      std::tie(Config->AsNeeded, Config->Static, InWholeArchive) = Stack.back();
      Stack.pop_back();
      break;
    }
  }

  if (Files.empty() && errorCount() == 0)
    error("no input files");
}

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

  for (InputFile *F : Files) {
    if (F->EKind == ELFNoneKind)
      continue;
    Config->EKind = F->EKind;
    Config->EMachine = F->EMachine;
    Config->OSABI = F->OSABI;
    Config->MipsN32Abi = Config->EMachine == EM_MIPS && isMipsN32Abi(F);
    return;
  }
  error("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(opt::InputArgList &Args) {
  uint64_t Val = args::getZOptionValue(Args, OPT_z, "max-page-size",
                                       Target->DefaultMaxPageSize);
  if (!isPowerOf2_64(Val))
    error("max-page-size: value isn't a power of 2");
  if (Config->Nmagic || Config->Omagic) {
    if (Val != Target->DefaultMaxPageSize)
      warn("-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(opt::InputArgList &Args) {
  uint64_t Val = args::getZOptionValue(Args, OPT_z, "common-page-size",
                                       Target->DefaultCommonPageSize);
  if (!isPowerOf2_64(Val))
    error("common-page-size: value isn't a power of 2");
  if (Config->Nmagic || Config->Omagic) {
    if (Val != Target->DefaultCommonPageSize)
      warn("-z common-page-size set, but paging disabled by omagic or nmagic");
    return 1;
  }
  // CommonPageSize can't be larger than MaxPageSize.
  if (Val > Config->MaxPageSize)
    Val = Config->MaxPageSize;
  return Val;
}

// Parses -image-base option.
static Optional<uint64_t> getImageBase(opt::InputArgList &Args) {
  // Because we are using "Config->MaxPageSize" here, this function has to be
  // called after the variable is initialized.
  auto *Arg = Args.getLastArg(OPT_image_base);
  if (!Arg)
    return None;

  StringRef S = Arg->getValue();
  uint64_t V;
  if (!to_integer(S, V)) {
    error("-image-base: number expected, but got " + S);
    return 0;
  }
  if ((V % Config->MaxPageSize) != 0)
    warn("-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(opt::InputArgList &Args) {
  DenseSet<StringRef> Libs = getExcludeLibs(Args);
  bool All = Libs.count("ALL");

  auto Visit = [&](InputFile *File) {
    if (!File->ArchiveName.empty())
      if (All || Libs.count(path::filename(File->ArchiveName)))
        for (Symbol *Sym : File->getSymbols())
          if (!Sym->isLocal() && Sym->File == File)
            Sym->VersionId = VER_NDX_LOCAL;
  };

  for (InputFile *File : ObjectFiles)
    Visit(File);

  for (BitcodeFile *File : BitcodeFiles)
    Visit(File);
}

// Force Sym to be entered in the output. Used for -u or equivalent.
static void handleUndefined(StringRef Name) {
  Symbol *Sym = Symtab->find(Name);
  if (!Sym)
    return;

  // Since symbol S 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())
    Sym->fetch();
}

static void handleLibcall(StringRef Name) {
  Symbol *Sym = Symtab->find(Name);
  if (!Sym || !Sym->isLazy())
    return;

  MemoryBufferRef MB;
  if (auto *LO = dyn_cast<LazyObject>(Sym))
    MB = LO->File->MB;
  else
    MB = cast<LazyArchive>(Sym)->getMemberBuffer();

  if (isBitcode(MB))
    Sym->fetch();
}

// 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() {
  Symtab->forEachSymbol([](Symbol *Sym) {
    auto *S = dyn_cast<CommonSymbol>(Sym);
    if (!S)
      return;

    auto *Bss = make<BssSection>("COMMON", S->Size, S->Alignment);
    Bss->File = S->File;
    Bss->markDead();
    InputSections.push_back(Bss);
    S->replace(Defined{S->File, S->getName(), S->Binding, S->StOther, S->Type,
                       /*Value=*/0, S->Size, Bss});
  });
}

// If all references to a DSO happen to be weak, the DSO is not added
// to DT_NEEDED. If that happens, we need to eliminate shared symbols
// created from the DSO. Otherwise, they become dangling references
// that point to a non-existent DSO.
static void demoteSharedSymbols() {
  Symtab->forEachSymbol([](Symbol *Sym) {
    auto *S = dyn_cast<SharedSymbol>(Sym);
    if (!S || S->getFile().IsNeeded)
      return;

    bool Used = S->Used;
    S->replace(Undefined{nullptr, S->getName(), STB_WEAK, S->StOther, S->Type});
    S->Used = Used;
  });
}

// The section referred to by S is considered address-significant. Set the
// KeepUnique flag on the section if appropriate.
static void markAddrsig(Symbol *S) {
  if (auto *D = dyn_cast_or_null<Defined>(S))
    if (D->Section)
      // We don't need to keep text sections unique under --icf=all even if they
      // are address-significant.
      if (Config->ICF == ICFLevel::Safe || !(D->Section->Flags & SHF_EXECINSTR))
        D->Section->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(opt::InputArgList &Args) {
  for (auto *Arg : Args.filtered(OPT_keep_unique)) {
    StringRef Name = Arg->getValue();
    auto *D = dyn_cast_or_null<Defined>(Symtab->find(Name));
    if (!D || !D->Section) {
      warn("could not find symbol " + Name + " to keep unique");
      continue;
    }
    D->Section->KeepUnique = true;
  }

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

  // Symbols in the dynsym could be address-significant in other executables
  // or DSOs, so we conservatively mark them as address-significant.
  Symtab->forEachSymbol([&](Symbol *Sym) {
    if (Sym->includeInDynsym())
      markAddrsig(Sym);
  });

  // Visit the address-significance table in each object file and mark each
  // referenced symbol as address-significant.
  for (InputFile *F : 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;
        uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err);
        if (Err)
          fatal(toString(F) + ": could not decode addrsig section: " + Err);
        markAddrsig(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(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(InputSectionBase *S) {
  // Read the relocation that refers to the partition's entry point symbol.
  Symbol *Sym;
  if (S->AreRelocsRela)
    Sym = &S->getFile<ELFT>()->getRelocTargetSym(S->template relas<ELFT>()[0]);
  else
    Sym = &S->getFile<ELFT>()->getRelocTargetSym(S->template rels<ELFT>()[0]);
  if (!isa<Defined>(Sym) || !Sym->includeInDynsym())
    return;

  StringRef PartName = reinterpret_cast<const char *>(S->data().data());
  for (Partition &Part : Partitions) {
    if (Part.Name == PartName) {
      Sym->Partition = Part.getNumber();
      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 (Script->HasSectionsCommand)
    error(toString(S->File) +
          ": partitions cannot be used with the SECTIONS command");
  if (Script->hasPhdrsCommands())
    error(toString(S->File) +
          ": partitions cannot be used with the PHDRS command");
  if (!Config->SectionStartMap.empty())
    error(toString(S->File) + ": partitions cannot be used with "
                              "--section-start, -Ttext, -Tdata or -Tbss");
  if (Config->EMachine == EM_MIPS)
    error(toString(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 (Partitions.size() == 254)
    fatal("may not have more than 254 partitions");

  Partitions.emplace_back();
  Partition &NewPart = Partitions.back();
  NewPart.Name = PartName;
  Sym->Partition = NewPart.getNumber();
}

static Symbol *addUndefined(StringRef Name) {
  return Symtab->addSymbol(
      Undefined{nullptr, Name, STB_GLOBAL, STV_DEFAULT, 0});
}

// 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() {
  // Compile bitcode files and replace bitcode symbols.
  LTO.reset(new BitcodeCompiler);
  for (BitcodeFile *File : BitcodeFiles)
    LTO->add(*File);

  for (InputFile *File : LTO->compile()) {
    DenseMap<CachedHashStringRef, const InputFile *> DummyGroups;
    auto *Obj = cast<ObjFile<ELFT>>(File);
    Obj->parse(DummyGroups);
    for (Symbol *Sym : Obj->getGlobalSymbols())
      Sym->parseSymbolVersion();
    ObjectFiles.push_back(File);
  }
}

// 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(opt::InputArgList &Args) {
  std::vector<WrappedSymbol> V;
  DenseSet<StringRef> Seen;

  for (auto *Arg : Args.filtered(OPT_wrap)) {
    StringRef Name = Arg->getValue();
    if (!Seen.insert(Name).second)
      continue;

    Symbol *Sym = Symtab->find(Name);
    if (!Sym)
      continue;

    Symbol *Real = addUndefined(Saver.save("__real_" + Name));
    Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name));
    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->CanInline = false;
    Sym->CanInline = false;

    // Tell LTO not to eliminate these symbols.
    Sym->IsUsedInRegularObj = true;
    Wrap->IsUsedInRegularObj = true;
  }
  return V;
}

// Do renaming for -wrap 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 wrapSymbols(ArrayRef<WrappedSymbol> Wrapped) {
  DenseMap<Symbol *, Symbol *> Map;
  for (const WrappedSymbol &W : Wrapped) {
    Map[W.Sym] = W.Wrap;
    Map[W.Real] = W.Sym;
  }

  // Update pointers in input files.
  parallelForEach(ObjectFiles, [&](InputFile *File) {
    MutableArrayRef<Symbol *> Syms = File->getMutableSymbols();
    for (size_t I = 0, E = Syms.size(); I != E; ++I)
      if (Symbol *S = Map.lookup(Syms[I]))
        Syms[I] = S;
  });

  // Update pointers in the symbol table.
  for (const WrappedSymbol &W : Wrapped)
    Symtab->wrap(W.Sym, W.Real, W.Wrap);
}

// To enable CET (x86's hardware-assited 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 function returns the merged feature flags. If 0, we cannot enable CET.
//
// Note that the CET-aware PLT is not implemented yet. We do error
// check only.
template <class ELFT> static uint32_t getAndFeatures() {
  if (Config->EMachine != EM_386 && Config->EMachine != EM_X86_64)
    return 0;

  uint32_t Ret = -1;
  for (InputFile *F : ObjectFiles) {
    uint32_t Features = cast<ObjFile<ELFT>>(F)->AndFeatures;
    if (!Features && Config->RequireCET)
      error(toString(F) + ": --require-cet: file is not compatible with CET");
    Ret &= Features;
  }
  return Ret;
}

static const char *LibcallRoutineNames[] = {
#define HANDLE_LIBCALL(code, name) name,
#include "llvm/IR/RuntimeLibcalls.def"
#undef HANDLE_LIBCALL
};

// 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) {
  // If a -hash-style option was not given, set to a default value,
  // which varies depending on the target.
  if (!Args.hasArg(OPT_hash_style)) {
    if (Config->EMachine == EM_MIPS)
      Config->SysvHash = true;
    else
      Config->SysvHash = Config->GnuHash = true;
  }

  // Default output filename is "a.out" by the Unix tradition.
  if (Config->OutputFile.empty())
    Config->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.
  if (auto E = tryCreateFile(Config->OutputFile))
    error("cannot open output file " + Config->OutputFile + ": " + E.message());
  if (auto E = tryCreateFile(Config->MapFile))
    error("cannot open map file " + Config->MapFile + ": " + E.message());
  if (errorCount())
    return;

  // Use default entry point name if no name was given via the command
  // line nor linker scripts. For some reason, MIPS entry point name is
  // different from others.
  Config->WarnMissingEntry =
      (!Config->Entry.empty() || (!Config->Shared && !Config->Relocatable));
  if (Config->Entry.empty() && !Config->Relocatable)
    Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start";

  // Handle --trace-symbol.
  for (auto *Arg : Args.filtered(OPT_trace_symbol))
    Symtab->insert(Arg->getValue())->Traced = true;

  // Add all files to the symbol table. This will add almost all
  // symbols that we need to the symbol table. This process might
  // add files to the link, via autolinking, these files are always
  // appended to the Files vector.
  for (size_t I = 0; I < Files.size(); ++I)
    parseFile(Files[I]);

  // Now that we have every file, we can decide if we will need a
  // dynamic symbol table.
  // We need one if we were asked to export dynamic symbols or if we are
  // producing a shared library.
  // We also need one if any shared libraries are used and for pie executables
  // (probably because the dynamic linker needs it).
  Config->HasDynSymTab =
      !SharedFiles.empty() || Config->Pic || Config->ExportDynamic;

  // Some symbols (such as __ehdr_start) are defined lazily only when there
  // are undefined symbols for them, so we add these to trigger that logic.
  for (StringRef Name : Script->ReferencedSymbols)
    addUndefined(Name);

  // Handle the `--undefined <sym>` options.
  for (StringRef S : Config->Undefined)
    handleUndefined(S);

  // If an entry symbol is in a static archive, pull out that file now.
  handleUndefined(Config->Entry);

  // 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 (!BitcodeFiles.empty())
    for (const char *S : LibcallRoutineNames)
      handleLibcall(S);

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

  // Now when we read all script files, we want to finalize order of linker
  // script commands, which can be not yet final because of INSERT commands.
  Script->processInsertCommands();

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

  // Handle the -exclude-libs option.
  if (Args.hasArg(OPT_exclude_libs))
    excludeLibs(Args);

  // Create ElfHeader early. We need a dummy section in
  // addReservedSymbols to mark the created symbols as not absolute.
  Out::ElfHeader = make<OutputSection>("", 0, SHF_ALLOC);
  Out::ElfHeader->Size = sizeof(typename ELFT::Ehdr);

  // Create wrapped symbols for -wrap option.
  std::vector<WrappedSymbol> Wrapped = addWrappedSymbols(Args);

  // We need to create some reserved symbols such as _end. Create them.
  if (!Config->Relocatable)
    addReservedSymbols();

  // 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 (!Config->Relocatable)
    Symtab->scanVersionScript();

  // 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.
  compileBitcodeFiles<ELFT>();
  if (errorCount())
    return;

  // If -thinlto-index-only is given, we should create only "index
  // files" and not object files. Index file creation is already done
  // in addCombinedLTOObject, so we are done if that's the case.
  if (Config->ThinLTOIndexOnly)
    return;

  // Likewise, --plugin-opt=emit-llvm is an option to make LTO create
  // an output file in bitcode and exit, so that you can just get a
  // combined bitcode file.
  if (Config->EmitLLVM)
    return;

  // Apply symbol renames for -wrap.
  if (!Wrapped.empty())
    wrapSymbols(Wrapped);

  // 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 : ObjectFiles)
    for (InputSectionBase *S : F->getSections())
      if (S && S != &InputSection::Discarded)
        InputSections.push_back(S);
  for (BinaryFile *F : BinaryFiles)
    for (InputSectionBase *S : F->getSections())
      InputSections.push_back(cast<InputSection>(S));

  llvm::erase_if(InputSections, [](InputSectionBase *S) {
    if (S->Type == SHT_LLVM_SYMPART) {
      readSymbolPartitionSection<ELFT>(S);
      return true;
    }

    // We do not want to emit debug sections if --strip-all
    // or -strip-debug are given.
    return Config->Strip != StripPolicy::None &&
           (S->Name.startswith(".debug") || S->Name.startswith(".zdebug"));
  });

  // Read .note.gnu.property sections from input object files which
  // contain a hint to tweak linker's and loader's behaviors.
  Config->AndFeatures = getAndFeatures<ELFT>();

  Config->EFlags = 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 64 for the output to be useable on both.
  // All important alignment decisions must use this value.
  Config->MaxPageSize = getMaxPageSize(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.
  Config->CommonPageSize = getCommonPageSize(Args);

  Config->ImageBase = getImageBase(Args);

  if (Config->EMachine == EM_ARM) {
    // FIXME: These warnings can be removed when lld only uses these features
    // when the input objects have been compiled with an architecture that
    // supports them.
    if (Config->ARMHasBlx == false)
      warn("lld uses blx instruction, no object with architecture supporting "
           "feature detected");
  }

  // This adds a .comment section containing a version string. We have to add it
  // before mergeSections because the .comment section is a mergeable section.
  if (!Config->Relocatable)
    InputSections.push_back(createCommentSection());

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

  // Do size optimizations: garbage collection, merging of SHF_MERGE sections
  // and identical code folding.
  splitSections<ELFT>();
  markLive<ELFT>();
  demoteSharedSymbols();
  mergeSections();
  if (Config->ICF != ICFLevel::None) {
    findKeepUniqueSections<ELFT>(Args);
    doIcf<ELFT>();
  }

  // Read the callgraph now that we know what was gced or icfed
  if (Config->CallGraphProfileSort) {
    if (auto *Arg = Args.getLastArg(OPT_call_graph_ordering_file))
      if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
        readCallGraph(*Buffer);
    readCallGraphsFromObjectFiles<ELFT>();
  }

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