//===- SyntheticSections.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
//
//===----------------------------------------------------------------------===//
//
// This file contains linker-synthesized sections. Currently,
// synthetic sections are created either output sections or input sections,
// but we are rewriting code so that all synthetic sections are created as
// input sections.
//
//===----------------------------------------------------------------------===//

#include "SyntheticSections.h"
#include "Config.h"
#include "DWARF.h"
#include "EhFrame.h"
#include "InputFiles.h"
#include "LinkerScript.h"
#include "OutputSections.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "Target.h"
#include "Thunks.h"
#include "Writer.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/TimeProfiler.h"
#include <cinttypes>
#include <cstdlib>

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

using llvm::support::endian::read32le;
using llvm::support::endian::write32le;
using llvm::support::endian::write64le;

static uint64_t readUint(Ctx &ctx, uint8_t *buf) {
  return ctx.arg.is64 ? read64(ctx, buf) : read32(ctx, buf);
}

static void writeUint(Ctx &ctx, uint8_t *buf, uint64_t val) {
  if (ctx.arg.is64)
    write64(ctx, buf, val);
  else
    write32(ctx, buf, val);
}

// Returns an LLD version string.
static ArrayRef<uint8_t> getVersion(Ctx &ctx) {
  // Check LLD_VERSION first for ease of testing.
  // You can get consistent output by using the environment variable.
  // This is only for testing.
  StringRef s = getenv("LLD_VERSION");
  if (s.empty())
    s = ctx.saver.save(Twine("Linker: ") + getLLDVersion());

  // +1 to include the terminating '\0'.
  return {(const uint8_t *)s.data(), s.size() + 1};
}

// Creates a .comment section containing LLD version info.
// With this feature, you can identify LLD-generated binaries easily
// by "readelf --string-dump .comment <file>".
// The returned object is a mergeable string section.
MergeInputSection *elf::createCommentSection(Ctx &ctx) {
  auto *sec =
      make<MergeInputSection>(ctx, ".comment", SHT_PROGBITS,
                              SHF_MERGE | SHF_STRINGS, 1, getVersion(ctx));
  sec->splitIntoPieces();
  return sec;
}

InputSection *elf::createInterpSection(Ctx &ctx) {
  // StringSaver guarantees that the returned string ends with '\0'.
  StringRef s = ctx.saver.save(ctx.arg.dynamicLinker);
  ArrayRef<uint8_t> contents = {(const uint8_t *)s.data(), s.size() + 1};

  return make<InputSection>(ctx.internalFile, ".interp", SHT_PROGBITS,
                            SHF_ALLOC,
                            /*addralign=*/1, /*entsize=*/0, contents);
}

Defined *elf::addSyntheticLocal(Ctx &ctx, StringRef name, uint8_t type,
                                uint64_t value, uint64_t size,
                                InputSectionBase &section) {
  Defined *s = makeDefined(ctx, section.file, name, STB_LOCAL, STV_DEFAULT,
                           type, value, size, &section);
  if (ctx.in.symTab)
    ctx.in.symTab->addSymbol(s);

  if (ctx.arg.emachine == EM_ARM && !ctx.arg.isLE && ctx.arg.armBe8 &&
      (section.flags & SHF_EXECINSTR))
    // Adding Linker generated mapping symbols to the arm specific mapping
    // symbols list.
    addArmSyntheticSectionMappingSymbol(s);

  return s;
}

static size_t getHashSize(Ctx &ctx) {
  switch (ctx.arg.buildId) {
  case BuildIdKind::Fast:
    return 8;
  case BuildIdKind::Md5:
  case BuildIdKind::Uuid:
    return 16;
  case BuildIdKind::Sha1:
    return 20;
  case BuildIdKind::Hexstring:
    return ctx.arg.buildIdVector.size();
  default:
    llvm_unreachable("unknown BuildIdKind");
  }
}

// This class represents a linker-synthesized .note.gnu.property section.
//
// In x86 and AArch64, object files may contain feature flags indicating the
// features that they have used. The flags are stored in a .note.gnu.property
// section.
//
// lld reads the sections from input files and merges them by computing AND of
// the flags. The result is written as a new .note.gnu.property section.
//
// If the flag is zero (which indicates that the intersection of the feature
// sets is empty, or some input files didn't have .note.gnu.property sections),
// we don't create this section.
GnuPropertySection::GnuPropertySection(Ctx &ctx)
    : SyntheticSection(ctx, ".note.gnu.property", SHT_NOTE, SHF_ALLOC,
                       ctx.arg.wordsize) {}

void GnuPropertySection::writeTo(uint8_t *buf) {
  uint32_t featureAndType;
  switch (ctx.arg.emachine) {
  case EM_386:
  case EM_X86_64:
    featureAndType = GNU_PROPERTY_X86_FEATURE_1_AND;
    break;
  case EM_AARCH64:
    featureAndType = GNU_PROPERTY_AARCH64_FEATURE_1_AND;
    break;
  case EM_RISCV:
    featureAndType = GNU_PROPERTY_RISCV_FEATURE_1_AND;
    break;
  default:
    llvm_unreachable(
        "target machine does not support .note.gnu.property section");
  }

  write32(ctx, buf, 4);                          // Name size
  write32(ctx, buf + 4, getSize() - 16);         // Content size
  write32(ctx, buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type
  memcpy(buf + 12, "GNU", 4);               // Name string

  unsigned offset = 16;
  if (ctx.arg.andFeatures != 0) {
    write32(ctx, buf + offset + 0, featureAndType);      // Feature type
    write32(ctx, buf + offset + 4, 4);                   // Feature size
    write32(ctx, buf + offset + 8, ctx.arg.andFeatures); // Feature flags
    if (ctx.arg.is64)
      write32(ctx, buf + offset + 12, 0); // Padding
    offset += 16;
  }

  if (ctx.aarch64PauthAbiCoreInfo) {
    write32(ctx, buf + offset + 0, GNU_PROPERTY_AARCH64_FEATURE_PAUTH);
    write32(ctx, buf + offset + 4, AArch64PauthAbiCoreInfo::size());
    write64(ctx, buf + offset + 8, ctx.aarch64PauthAbiCoreInfo->platform);
    write64(ctx, buf + offset + 16, ctx.aarch64PauthAbiCoreInfo->version);
  }
}

size_t GnuPropertySection::getSize() const {
  uint32_t contentSize = 0;
  if (ctx.arg.andFeatures != 0)
    contentSize += ctx.arg.is64 ? 16 : 12;
  if (ctx.aarch64PauthAbiCoreInfo)
    contentSize += 4 + 4 + AArch64PauthAbiCoreInfo::size();
  assert(contentSize != 0);
  return contentSize + 16;
}

BuildIdSection::BuildIdSection(Ctx &ctx)
    : SyntheticSection(ctx, ".note.gnu.build-id", SHT_NOTE, SHF_ALLOC, 4),
      hashSize(getHashSize(ctx)) {}

void BuildIdSection::writeTo(uint8_t *buf) {
  write32(ctx, buf, 4);                   // Name size
  write32(ctx, buf + 4, hashSize);        // Content size
  write32(ctx, buf + 8, NT_GNU_BUILD_ID); // Type
  memcpy(buf + 12, "GNU", 4);           // Name string
  hashBuf = buf + 16;
}

void BuildIdSection::writeBuildId(ArrayRef<uint8_t> buf) {
  assert(buf.size() == hashSize);
  memcpy(hashBuf, buf.data(), hashSize);
}

BssSection::BssSection(Ctx &ctx, StringRef name, uint64_t size,
                       uint32_t alignment)
    : SyntheticSection(ctx, name, SHT_NOBITS, SHF_ALLOC | SHF_WRITE,
                       alignment) {
  this->bss = true;
  this->size = size;
}

EhFrameSection::EhFrameSection(Ctx &ctx)
    : SyntheticSection(ctx, ".eh_frame", SHT_PROGBITS, SHF_ALLOC, 1) {}

// Search for an existing CIE record or create a new one.
// CIE records from input object files are uniquified by their contents
// and where their relocations point to.
CieRecord *EhFrameSection::addCie(EhSectionPiece &cie,
                                  ArrayRef<Relocation> rels) {
  Symbol *personality = nullptr;
  unsigned firstRelI = cie.firstRelocation;
  if (firstRelI != (unsigned)-1)
    personality = rels[firstRelI].sym;

  // Search for an existing CIE by CIE contents/relocation target pair.
  CieRecord *&rec = cieMap[{cie.data(), personality}];

  // If not found, create a new one.
  if (!rec) {
    rec = make<CieRecord>();
    rec->cie = &cie;
    cieRecords.push_back(rec);
  }
  return rec;
}

// There is one FDE per function. Returns a non-null pointer to the function
// symbol if the given FDE points to a live function.
Defined *EhFrameSection::isFdeLive(EhSectionPiece &fde,
                                   ArrayRef<Relocation> rels) {
  // An FDE should point to some function because FDEs are to describe
  // functions. That's however not always the case due to an issue of
  // ld.gold with -r. ld.gold may discard only functions and leave their
  // corresponding FDEs, which results in creating bad .eh_frame sections.
  // To deal with that, we ignore such FDEs.
  unsigned firstRelI = fde.firstRelocation;
  if (firstRelI == (unsigned)-1)
    return nullptr;

  // FDEs for garbage-collected or merged-by-ICF sections, or sections in
  // another partition, are dead.
  if (auto *d = dyn_cast<Defined>(rels[firstRelI].sym))
    if (!d->folded && d->section && d->section->partition == partition)
      return d;
  return nullptr;
}

// .eh_frame is a sequence of CIE or FDE records. In general, there
// is one CIE record per input object file which is followed by
// a list of FDEs. This function searches an existing CIE or create a new
// one and associates FDEs to the CIE.
template <endianness e> void EhFrameSection::addRecords(EhInputSection *sec) {
  auto rels = sec->rels;
  offsetToCie.clear();
  for (EhSectionPiece &cie : sec->cies)
    offsetToCie[cie.inputOff] = addCie(cie, rels);
  for (EhSectionPiece &fde : sec->fdes) {
    uint32_t id = endian::read32<e>(fde.data().data() + 4);
    CieRecord *rec = offsetToCie[fde.inputOff + 4 - id];
    if (!rec)
      Fatal(ctx) << sec << ": invalid CIE reference";

    if (!isFdeLive(fde, rels))
      continue;
    rec->fdes.push_back(&fde);
    numFdes++;
  }
}

// Used by ICF<ELFT>::handleLSDA(). This function is very similar to
// EhFrameSection::addRecords().
template <class ELFT>
void EhFrameSection::iterateFDEWithLSDAAux(
    EhInputSection &sec, DenseSet<size_t> &ciesWithLSDA,
    llvm::function_ref<void(InputSection &)> fn) {
  for (EhSectionPiece &cie : sec.cies)
    if (hasLSDA(cie))
      ciesWithLSDA.insert(cie.inputOff);
  for (EhSectionPiece &fde : sec.fdes) {
    uint32_t id = endian::read32<ELFT::Endianness>(fde.data().data() + 4);
    if (!ciesWithLSDA.contains(fde.inputOff + 4 - id))
      continue;

    // The CIE has a LSDA argument. Call fn with d's section.
    if (Defined *d = isFdeLive(fde, sec.rels))
      if (auto *s = dyn_cast_or_null<InputSection>(d->section))
        fn(*s);
  }
}

template <class ELFT>
void EhFrameSection::iterateFDEWithLSDA(
    llvm::function_ref<void(InputSection &)> fn) {
  DenseSet<size_t> ciesWithLSDA;
  for (EhInputSection *sec : sections) {
    ciesWithLSDA.clear();
    iterateFDEWithLSDAAux<ELFT>(*sec, ciesWithLSDA, fn);
  }
}

static void writeCieFde(Ctx &ctx, uint8_t *buf, ArrayRef<uint8_t> d) {
  memcpy(buf, d.data(), d.size());
  // Fix the size field. -4 since size does not include the size field itself.
  write32(ctx, buf, d.size() - 4);
}

void EhFrameSection::finalizeContents() {
  assert(!this->size); // Not finalized.

  switch (ctx.arg.ekind) {
  case ELFNoneKind:
    llvm_unreachable("invalid ekind");
  case ELF32LEKind:
  case ELF64LEKind:
    for (EhInputSection *sec : sections)
      if (sec->isLive())
        addRecords<endianness::little>(sec);
    break;
  case ELF32BEKind:
  case ELF64BEKind:
    for (EhInputSection *sec : sections)
      if (sec->isLive())
        addRecords<endianness::big>(sec);
    break;
  }

  size_t off = 0;
  for (CieRecord *rec : cieRecords) {
    rec->cie->outputOff = off;
    off += rec->cie->size;

    for (EhSectionPiece *fde : rec->fdes) {
      fde->outputOff = off;
      off += fde->size;
    }
  }

  // The LSB standard does not allow a .eh_frame section with zero
  // Call Frame Information records. glibc unwind-dw2-fde.c
  // classify_object_over_fdes expects there is a CIE record length 0 as a
  // terminator. Thus we add one unconditionally.
  off += 4;

  this->size = off;
}

void EhFrameSection::writeTo(uint8_t *buf) {
  // Write CIE and FDE records.
  for (CieRecord *rec : cieRecords) {
    size_t cieOffset = rec->cie->outputOff;
    writeCieFde(ctx, buf + cieOffset, rec->cie->data());

    for (EhSectionPiece *fde : rec->fdes) {
      size_t off = fde->outputOff;
      writeCieFde(ctx, buf + off, fde->data());

      // FDE's second word should have the offset to an associated CIE.
      // Write it.
      write32(ctx, buf + off + 4, off + 4 - cieOffset);
    }
  }

  // Apply relocations to .eh_frame entries. This includes CIE personality
  // pointers, FDE initial_location fields, and LSDA pointers.
  for (EhInputSection *s : sections)
    ctx.target->relocateEh(*s, buf);

  EhFrameHeader *hdr = getPartition(ctx).ehFrameHdr.get();
  if (!hdr || !hdr->getParent())
    return;

  // Write the .eh_frame_hdr section using cached FDE data from updateAllocSize.
  bool large = hdr->large;
  int64_t ehFramePtr = getParent()->addr - hdr->getVA() - 4;
  auto writeField = [&](uint8_t *buf, uint64_t val) {
    large ? write64(ctx, buf, val) : write32(ctx, buf, val);
  };

  uint8_t *hdrBuf = ctx.bufferStart + hdr->getParent()->offset + hdr->outSecOff;
  // version
  hdrBuf[0] = 1;
  // eh_frame_ptr_enc
  hdrBuf[1] = DW_EH_PE_pcrel | (large ? DW_EH_PE_sdata8 : DW_EH_PE_sdata4);
  // fde_count_enc
  hdrBuf[2] = DW_EH_PE_udata4;
  // table_enc
  hdrBuf[3] = DW_EH_PE_datarel | (large ? DW_EH_PE_sdata8 : DW_EH_PE_sdata4);
  hdrBuf += 4;
  writeField(hdrBuf, ehFramePtr);
  hdrBuf += large ? 8 : 4;
  write32(ctx, hdrBuf, hdr->fdes.size());
  hdrBuf += 4;
  for (const FdeData &fde : hdr->fdes) {
    writeField(hdrBuf, fde.pcRel);
    writeField(hdrBuf + (large ? 8 : 4), fde.fdeVARel);
    hdrBuf += large ? 16 : 8;
  }
}

EhFrameHeader::EhFrameHeader(Ctx &ctx)
    : SyntheticSection(ctx, ".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 4) {}

void EhFrameHeader::writeTo(uint8_t *buf) {
  // The section content is written during EhFrameSection::writeTo.
}

bool EhFrameHeader::isNeeded() const {
  return isLive() && getPartition(ctx).ehFrame->isNeeded();
}

void EhFrameHeader::finalizeContents() {
  // Compute size: 4-byte header + eh_frame_ptr + fde_count + FDE table.
  // Initially `large` is false; updateAllocSize may set it to true if addresses
  // exceed the 32-bit range, then call finalizeContents again.
  auto numFdes = getPartition(ctx).ehFrame->numFdes;
  size = 4 + (large ? 8 : 4) + 4 + numFdes * (large ? 16 : 8);
}

bool EhFrameHeader::updateAllocSize(Ctx &ctx) {
  // This is called after `finalizeSynthetic`, so in the typical case without
  // .relr.dyn, this function will not change the size and assignAddresses
  // will not need another iteration.
  EhFrameSection *ehFrame = getPartition(ctx).ehFrame.get();
  uint64_t hdrVA = getVA();
  int64_t ehFramePtr = ehFrame->getParent()->addr - hdrVA - 4;
  // Determine if 64-bit encodings are needed.
  bool newLarge = !isInt<32>(ehFramePtr);

  // Collect FDE entries. For each FDE, compute pcRel and fdeVARel relative to
  // .eh_frame_hdr's VA.
  fdes.clear();
  for (CieRecord *rec : ehFrame->getCieRecords()) {
    uint8_t enc = getFdeEncoding(rec->cie);
    if ((enc & 0x70) != DW_EH_PE_absptr && (enc & 0x70) != DW_EH_PE_pcrel) {
      Err(ctx) << "unknown FDE size encoding";
      continue;
    }
    for (EhSectionPiece *fde : rec->fdes) {
      // The FDE has passed `isFdeLive`, so the first relocation's symbol is a
      // live Defined.
      auto *isec = cast<EhInputSection>(fde->sec);
      auto &reloc = isec->rels[fde->firstRelocation];
      assert(isa<Defined>(reloc.sym) && "isFdeLive should have checked this");
      int64_t pcRel = reloc.sym->getVA(ctx) + reloc.addend - hdrVA;
      int64_t fdeVARel = ehFrame->getParent()->addr + fde->outputOff - hdrVA;
      fdes.push_back({pcRel, fdeVARel});
      newLarge |= !isInt<32>(pcRel) || !isInt<32>(fdeVARel);
    }
  }

  // Sort the FDE list by their PC and uniquify. Usually there is only one FDE
  // at an address, but there can be more than one FDEs pointing to the address.
  llvm::stable_sort(
      fdes, [](const EhFrameSection::FdeData &a,
               const EhFrameSection::FdeData &b) { return a.pcRel < b.pcRel; });
  fdes.erase(llvm::unique(fdes,
                          [](const EhFrameSection::FdeData &a,
                             const EhFrameSection::FdeData &b) {
                            return a.pcRel == b.pcRel;
                          }),
             fdes.end());
  ehFrame->numFdes = fdes.size();

  large = newLarge;

  // Compute size.
  size_t oldSize = size;
  finalizeContents();
  return size != oldSize;
}

GotSection::GotSection(Ctx &ctx)
    : SyntheticSection(ctx, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE,
                       ctx.target->gotEntrySize) {
  numEntries = ctx.target->gotHeaderEntriesNum;
}

void GotSection::addEntry(const Symbol &sym) {
  assert(sym.auxIdx == ctx.symAux.size() - 1);
  ctx.symAux.back().gotIdx = numEntries++;
}

void GotSection::addAuthEntry(const Symbol &sym) {
  authEntries.push_back(
      {(numEntries - 1) * ctx.target->gotEntrySize, sym.isFunc()});
}

bool GotSection::addTlsDescEntry(const Symbol &sym) {
  assert(sym.auxIdx == ctx.symAux.size() - 1);
  ctx.symAux.back().tlsDescIdx = numEntries;
  numEntries += 2;
  return true;
}

void GotSection::addTlsDescAuthEntry() {
  authEntries.push_back({(numEntries - 2) * ctx.target->gotEntrySize, true});
  authEntries.push_back({(numEntries - 1) * ctx.target->gotEntrySize, false});
}

bool GotSection::addDynTlsEntry(const Symbol &sym) {
  assert(sym.auxIdx == ctx.symAux.size() - 1);
  ctx.symAux.back().tlsGdIdx = numEntries;
  // Global Dynamic TLS entries take two GOT slots.
  numEntries += 2;
  return true;
}

// Reserves TLS entries for a TLS module ID and a TLS block offset.
// In total it takes two GOT slots.
bool GotSection::addTlsIndex() {
  if (tlsIndexOff != uint32_t(-1))
    return false;
  tlsIndexOff = numEntries * ctx.target->gotEntrySize;
  numEntries += 2;
  return true;
}

uint32_t GotSection::getTlsDescOffset(const Symbol &sym) const {
  return sym.getTlsDescIdx(ctx) * ctx.target->gotEntrySize;
}

uint64_t GotSection::getTlsDescAddr(const Symbol &sym) const {
  return getVA() + getTlsDescOffset(sym);
}

uint64_t GotSection::getGlobalDynAddr(const Symbol &b) const {
  return this->getVA() + b.getTlsGdIdx(ctx) * ctx.target->gotEntrySize;
}

uint64_t GotSection::getGlobalDynOffset(const Symbol &b) const {
  return b.getTlsGdIdx(ctx) * ctx.target->gotEntrySize;
}

void GotSection::finalizeContents() {
  if (ctx.arg.emachine == EM_PPC64 &&
      numEntries <= ctx.target->gotHeaderEntriesNum &&
      !ctx.sym.globalOffsetTable)
    size = 0;
  else
    size = numEntries * ctx.target->gotEntrySize;
}

bool GotSection::isNeeded() const {
  // Needed if the GOT symbol is used or the number of entries is more than just
  // the header. A GOT with just the header may not be needed.
  return hasGotOffRel || numEntries > ctx.target->gotHeaderEntriesNum;
}

void GotSection::writeTo(uint8_t *buf) {
  // On PPC64 .got may be needed but empty. Skip the write.
  if (size == 0)
    return;
  ctx.target->writeGotHeader(buf);
  ctx.target->relocateAlloc(*this, buf);
  for (const AuthEntryInfo &authEntry : authEntries) {
    // https://github.com/ARM-software/abi-aa/blob/2024Q3/pauthabielf64/pauthabielf64.rst#default-signing-schema
    //   Signed GOT entries use the IA key for symbols of type STT_FUNC and the
    //   DA key for all other symbol types, with the address of the GOT entry as
    //   the modifier. The static linker must encode the signing schema into the
    //   GOT slot.
    //
    // https://github.com/ARM-software/abi-aa/blob/2024Q3/pauthabielf64/pauthabielf64.rst#encoding-the-signing-schema
    //   If address diversity is set and the discriminator
    //   is 0 then modifier = Place
    uint8_t *dest = buf + authEntry.offset;
    uint64_t key = authEntry.isSymbolFunc ? /*IA=*/0b00 : /*DA=*/0b10;
    uint64_t addrDiversity = 1;
    write64(ctx, dest, (addrDiversity << 63) | (key << 60));
  }
}

static uint64_t getMipsPageCount(uint64_t size) {
  return (size + 0xfffe) / 0xffff + 1;
}

MipsGotSection::MipsGotSection(Ctx &ctx)
    : SyntheticSection(ctx, ".got", SHT_PROGBITS,
                       SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, 16) {}

void MipsGotSection::addConstant(const Relocation &r) {
  relocations.push_back(r);
}

void MipsGotSection::addEntry(InputFile &file, Symbol &sym, int64_t addend,
                              RelExpr expr) {
  FileGot &g = getGot(file);
  if (expr == RE_MIPS_GOT_LOCAL_PAGE) {
    if (const OutputSection *os = sym.getOutputSection())
      g.pagesMap.insert({os, {&sym}});
    else
      g.local16.insert({{nullptr, getMipsPageAddr(sym.getVA(ctx, addend))}, 0});
  } else if (sym.isTls())
    g.tls.insert({&sym, 0});
  else if (sym.isPreemptible && expr == R_ABS)
    g.relocs.insert({&sym, 0});
  else if (sym.isPreemptible)
    g.global.insert({&sym, 0});
  else if (expr == RE_MIPS_GOT_OFF32)
    g.local32.insert({{&sym, addend}, 0});
  else
    g.local16.insert({{&sym, addend}, 0});
}

void MipsGotSection::addDynTlsEntry(InputFile &file, Symbol &sym) {
  getGot(file).dynTlsSymbols.insert({&sym, 0});
}

void MipsGotSection::addTlsIndex(InputFile &file) {
  getGot(file).dynTlsSymbols.insert({nullptr, 0});
}

size_t MipsGotSection::FileGot::getEntriesNum() const {
  return getPageEntriesNum() + local16.size() + global.size() + relocs.size() +
         tls.size() + dynTlsSymbols.size() * 2;
}

size_t MipsGotSection::FileGot::getPageEntriesNum() const {
  size_t num = 0;
  for (const std::pair<const OutputSection *, FileGot::PageBlock> &p : pagesMap)
    num += p.second.count;
  return num;
}

size_t MipsGotSection::FileGot::getIndexedEntriesNum() const {
  size_t count = getPageEntriesNum() + local16.size() + global.size();
  // If there are relocation-only entries in the GOT, TLS entries
  // are allocated after them. TLS entries should be addressable
  // by 16-bit index so count both reloc-only and TLS entries.
  if (!tls.empty() || !dynTlsSymbols.empty())
    count += relocs.size() + tls.size() + dynTlsSymbols.size() * 2;
  return count;
}

MipsGotSection::FileGot &MipsGotSection::getGot(InputFile &f) {
  if (f.mipsGotIndex == uint32_t(-1)) {
    gots.emplace_back();
    gots.back().file = &f;
    f.mipsGotIndex = gots.size() - 1;
  }
  return gots[f.mipsGotIndex];
}

uint64_t MipsGotSection::getPageEntryOffset(const InputFile *f,
                                            const Symbol &sym,
                                            int64_t addend) const {
  const FileGot &g = gots[f->mipsGotIndex];
  uint64_t index = 0;
  if (const OutputSection *outSec = sym.getOutputSection()) {
    uint64_t secAddr = getMipsPageAddr(outSec->addr);
    uint64_t symAddr = getMipsPageAddr(sym.getVA(ctx, addend));
    index = g.pagesMap.lookup(outSec).firstIndex + (symAddr - secAddr) / 0xffff;
  } else {
    index =
        g.local16.lookup({nullptr, getMipsPageAddr(sym.getVA(ctx, addend))});
  }
  return index * ctx.arg.wordsize;
}

uint64_t MipsGotSection::getSymEntryOffset(const InputFile *f, const Symbol &s,
                                           int64_t addend) const {
  const FileGot &g = gots[f->mipsGotIndex];
  Symbol *sym = const_cast<Symbol *>(&s);
  if (sym->isTls())
    return g.tls.lookup(sym) * ctx.arg.wordsize;
  if (sym->isPreemptible)
    return g.global.lookup(sym) * ctx.arg.wordsize;
  return g.local16.lookup({sym, addend}) * ctx.arg.wordsize;
}

uint64_t MipsGotSection::getTlsIndexOffset(const InputFile *f) const {
  const FileGot &g = gots[f->mipsGotIndex];
  return g.dynTlsSymbols.lookup(nullptr) * ctx.arg.wordsize;
}

uint64_t MipsGotSection::getGlobalDynOffset(const InputFile *f,
                                            const Symbol &s) const {
  const FileGot &g = gots[f->mipsGotIndex];
  Symbol *sym = const_cast<Symbol *>(&s);
  return g.dynTlsSymbols.lookup(sym) * ctx.arg.wordsize;
}

const Symbol *MipsGotSection::getFirstGlobalEntry() const {
  if (gots.empty())
    return nullptr;
  const FileGot &primGot = gots.front();
  if (!primGot.global.empty())
    return primGot.global.front().first;
  if (!primGot.relocs.empty())
    return primGot.relocs.front().first;
  return nullptr;
}

unsigned MipsGotSection::getLocalEntriesNum() const {
  if (gots.empty())
    return headerEntriesNum;
  return headerEntriesNum + gots.front().getPageEntriesNum() +
         gots.front().local16.size();
}

bool MipsGotSection::tryMergeGots(FileGot &dst, FileGot &src, bool isPrimary) {
  FileGot tmp = dst;
  set_union(tmp.pagesMap, src.pagesMap);
  set_union(tmp.local16, src.local16);
  set_union(tmp.global, src.global);
  set_union(tmp.relocs, src.relocs);
  set_union(tmp.tls, src.tls);
  set_union(tmp.dynTlsSymbols, src.dynTlsSymbols);

  size_t count = isPrimary ? headerEntriesNum : 0;
  count += tmp.getIndexedEntriesNum();

  if (count * ctx.arg.wordsize > ctx.arg.mipsGotSize)
    return false;

  std::swap(tmp, dst);
  return true;
}

void MipsGotSection::finalizeContents() { updateAllocSize(ctx); }

bool MipsGotSection::updateAllocSize(Ctx &ctx) {
  size = headerEntriesNum * ctx.arg.wordsize;
  for (const FileGot &g : gots)
    size += g.getEntriesNum() * ctx.arg.wordsize;
  return false;
}

void MipsGotSection::build() {
  if (gots.empty())
    return;

  std::vector<FileGot> mergedGots(1);

  // For each GOT move non-preemptible symbols from the `Global`
  // to `Local16` list. Preemptible symbol might become non-preemptible
  // one if, for example, it gets a related copy relocation.
  for (FileGot &got : gots) {
    for (auto &p: got.global)
      if (!p.first->isPreemptible)
        got.local16.insert({{p.first, 0}, 0});
    got.global.remove_if([&](const std::pair<Symbol *, size_t> &p) {
      return !p.first->isPreemptible;
    });
  }

  // For each GOT remove "reloc-only" entry if there is "global"
  // entry for the same symbol. And add local entries which indexed
  // using 32-bit value at the end of 16-bit entries.
  for (FileGot &got : gots) {
    got.relocs.remove_if([&](const std::pair<Symbol *, size_t> &p) {
      return got.global.contains(p.first);
    });
    set_union(got.local16, got.local32);
    got.local32.clear();
  }

  // Evaluate number of "reloc-only" entries in the resulting GOT.
  // To do that put all unique "reloc-only" and "global" entries
  // from all GOTs to the future primary GOT.
  FileGot *primGot = &mergedGots.front();
  for (FileGot &got : gots) {
    set_union(primGot->relocs, got.global);
    set_union(primGot->relocs, got.relocs);
    got.relocs.clear();
  }

  // Evaluate number of "page" entries in each GOT.
  for (FileGot &got : gots) {
    for (std::pair<const OutputSection *, FileGot::PageBlock> &p :
         got.pagesMap) {
      const OutputSection *os = p.first;
      uint64_t secSize = 0;
      for (SectionCommand *cmd : os->commands) {
        if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
          for (InputSection *isec : isd->sections) {
            uint64_t off = alignToPowerOf2(secSize, isec->addralign);
            secSize = off + isec->getSize();
          }
      }
      p.second.count = getMipsPageCount(secSize);
    }
  }

  // Merge GOTs. Try to join as much as possible GOTs but do not exceed
  // maximum GOT size. At first, try to fill the primary GOT because
  // the primary GOT can be accessed in the most effective way. If it
  // is not possible, try to fill the last GOT in the list, and finally
  // create a new GOT if both attempts failed.
  for (FileGot &srcGot : gots) {
    InputFile *file = srcGot.file;
    if (tryMergeGots(mergedGots.front(), srcGot, true)) {
      file->mipsGotIndex = 0;
    } else {
      // If this is the first time we failed to merge with the primary GOT,
      // MergedGots.back() will also be the primary GOT. We must make sure not
      // to try to merge again with isPrimary=false, as otherwise, if the
      // inputs are just right, we could allow the primary GOT to become 1 or 2
      // words bigger due to ignoring the header size.
      if (mergedGots.size() == 1 ||
          !tryMergeGots(mergedGots.back(), srcGot, false)) {
        mergedGots.emplace_back();
        std::swap(mergedGots.back(), srcGot);
      }
      file->mipsGotIndex = mergedGots.size() - 1;
    }
  }
  std::swap(gots, mergedGots);

  // Reduce number of "reloc-only" entries in the primary GOT
  // by subtracting "global" entries in the primary GOT.
  primGot = &gots.front();
  primGot->relocs.remove_if([&](const std::pair<Symbol *, size_t> &p) {
    return primGot->global.contains(p.first);
  });

  // Calculate indexes for each GOT entry.
  size_t index = headerEntriesNum;
  for (FileGot &got : gots) {
    got.startIndex = &got == primGot ? 0 : index;
    for (std::pair<const OutputSection *, FileGot::PageBlock> &p :
         got.pagesMap) {
      // For each output section referenced by GOT page relocations calculate
      // and save into pagesMap an upper bound of MIPS GOT entries required
      // to store page addresses of local symbols. We assume the worst case -
      // each 64kb page of the output section has at least one GOT relocation
      // against it. And take in account the case when the section intersects
      // page boundaries.
      p.second.firstIndex = index;
      index += p.second.count;
    }
    for (auto &p: got.local16)
      p.second = index++;
    for (auto &p: got.global)
      p.second = index++;
    for (auto &p: got.relocs)
      p.second = index++;
    for (auto &p: got.tls)
      p.second = index++;
    for (auto &p: got.dynTlsSymbols) {
      p.second = index;
      index += 2;
    }
  }

  // Update SymbolAux::gotIdx field to use this
  // value later in the `sortMipsSymbols` function.
  for (auto &p : primGot->global) {
    if (p.first->auxIdx == 0)
      p.first->allocateAux(ctx);
    ctx.symAux.back().gotIdx = p.second;
  }
  for (auto &p : primGot->relocs) {
    if (p.first->auxIdx == 0)
      p.first->allocateAux(ctx);
    ctx.symAux.back().gotIdx = p.second;
  }

  // Create relocations.
  //
  // Note the primary GOT's local and global relocations are implicit, and the
  // MIPS ABI requires the VA be written even for the global entries, so we
  // treat both as constants here.
  for (FileGot &got : gots) {
    // Create relocations for TLS entries.
    for (std::pair<Symbol *, size_t> &p : got.tls) {
      Symbol *s = p.first;
      uint64_t offset = p.second * ctx.arg.wordsize;
      // When building a shared library we still need a dynamic relocation
      // for the TP-relative offset as we don't know how much other data will
      // be allocated before us in the static TLS block.
      if (!s->isPreemptible && !ctx.arg.shared)
        addConstant({R_TPREL, ctx.target->symbolicRel, offset, 0, s});
      else
        ctx.mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible(
            ctx.target->tlsGotRel, *this, offset, *s, ctx.target->symbolicRel);
    }
    for (std::pair<Symbol *, size_t> &p : got.dynTlsSymbols) {
      Symbol *s = p.first;
      uint64_t offset = p.second * ctx.arg.wordsize;
      if (s == nullptr) {
        if (ctx.arg.shared)
          ctx.mainPart->relaDyn->addReloc(
              {ctx.target->tlsModuleIndexRel, this, offset});
        else
          addConstant(
              {R_ADDEND, ctx.target->symbolicRel, offset, 1, ctx.dummySym});
      } else {
        // When building a shared library we still need a dynamic relocation
        // for the module index. Therefore only checking for
        // S->isPreemptible is not sufficient (this happens e.g. for
        // thread-locals that have been marked as local through a linker script)
        if (!s->isPreemptible && !ctx.arg.shared)
          // Write one to the GOT slot.
          addConstant({R_ADDEND, ctx.target->symbolicRel, offset, 1, s});
        else
          ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->tlsModuleIndexRel,
                                                *this, offset, *s);
        offset += ctx.arg.wordsize;
        // However, we can skip writing the TLS offset reloc for non-preemptible
        // symbols since it is known even in shared libraries
        if (s->isPreemptible)
          ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->tlsOffsetRel, *this,
                                                offset, *s);
        else
          addConstant({R_ABS, ctx.target->tlsOffsetRel, offset, 0, s});
      }
    }

    // Relocations for "global" entries.
    for (const std::pair<Symbol *, size_t> &p : got.global) {
      uint64_t offset = p.second * ctx.arg.wordsize;
      if (&got == primGot)
        addConstant({R_ABS, ctx.target->relativeRel, offset, 0, p.first});
      else
        ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->relativeRel, *this,
                                              offset, *p.first);
    }
    // Relocation-only entries exist as dummy entries for dynamic symbols that
    // aren't otherwise in the primary GOT, as the ABI requires an entry for
    // each dynamic symbol. Secondary GOTs have no need for them.
    assert((got.relocs.empty() || &got == primGot) &&
           "Relocation-only entries should only be in the primary GOT");
    for (const std::pair<Symbol *, size_t> &p : got.relocs) {
      uint64_t offset = p.second * ctx.arg.wordsize;
      addConstant({R_ABS, ctx.target->relativeRel, offset, 0, p.first});
    }

    // Relocations for "local" entries
    for (const std::pair<const OutputSection *, FileGot::PageBlock> &l :
         got.pagesMap) {
      size_t pageCount = l.second.count;
      for (size_t pi = 0; pi < pageCount; ++pi) {
        uint64_t offset = (l.second.firstIndex + pi) * ctx.arg.wordsize;
        int64_t addend = int64_t(pi * 0x10000);
        if (!ctx.arg.isPic || &got == primGot)
          addConstant({RE_MIPS_OSEC_LOCAL_PAGE, ctx.target->relativeRel, offset,
                       addend, l.second.repSym});
        else
          ctx.mainPart->relaDyn->addRelativeReloc(
              ctx.target->relativeRel, *this, offset, *l.second.repSym, addend,
              ctx.target->relativeRel, RE_MIPS_OSEC_LOCAL_PAGE);
      }
    }
    for (const std::pair<GotEntry, size_t> &p : got.local16) {
      uint64_t offset = p.second * ctx.arg.wordsize;
      if (p.first.first == nullptr)
        addConstant({R_ADDEND, ctx.target->relativeRel, offset, p.first.second,
                     ctx.dummySym});
      else if (!ctx.arg.isPic || &got == primGot)
        addConstant({R_ABS, ctx.target->relativeRel, offset, p.first.second,
                     p.first.first});
      else
        ctx.mainPart->relaDyn->addRelativeReloc(
            ctx.target->relativeRel, *this, offset, *p.first.first,
            p.first.second, ctx.target->relativeRel, R_ABS);
    }
  }
}

bool MipsGotSection::isNeeded() const {
  // We add the .got section to the result for dynamic MIPS target because
  // its address and properties are mentioned in the .dynamic section.
  return !ctx.arg.relocatable;
}

uint64_t MipsGotSection::getGp(const InputFile *f) const {
  // For files without related GOT or files refer a primary GOT
  // returns "common" _gp value. For secondary GOTs calculate
  // individual _gp values.
  if (!f || f->mipsGotIndex == uint32_t(-1) || f->mipsGotIndex == 0)
    return ctx.sym.mipsGp->getVA(ctx, 0);
  return getVA() + gots[f->mipsGotIndex].startIndex * ctx.arg.wordsize + 0x7ff0;
}

void MipsGotSection::writeTo(uint8_t *buf) {
  // Set the MSB of the second GOT slot. This is not required by any
  // MIPS ABI documentation, though.
  //
  // There is a comment in glibc saying that "The MSB of got[1] of a
  // gnu object is set to identify gnu objects," and in GNU gold it
  // says "the second entry will be used by some runtime loaders".
  // But how this field is being used is unclear.
  //
  // We are not really willing to mimic other linkers behaviors
  // without understanding why they do that, but because all files
  // generated by GNU tools have this special GOT value, and because
  // we've been doing this for years, it is probably a safe bet to
  // keep doing this for now. We really need to revisit this to see
  // if we had to do this.
  writeUint(ctx, buf + ctx.arg.wordsize,
            (uint64_t)1 << (ctx.arg.wordsize * 8 - 1));
  ctx.target->relocateAlloc(*this, buf);
}

// On PowerPC the .plt section is used to hold the table of function addresses
// instead of the .got.plt, and the type is SHT_NOBITS similar to a .bss
// section. I don't know why we have a BSS style type for the section but it is
// consistent across both 64-bit PowerPC ABIs as well as the 32-bit PowerPC ABI.
GotPltSection::GotPltSection(Ctx &ctx)
    : SyntheticSection(ctx, ".got.plt", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE,
                       ctx.target->gotEntrySize) {
  if (ctx.arg.emachine == EM_PPC) {
    name = ".plt";
  } else if (ctx.arg.emachine == EM_PPC64) {
    type = SHT_NOBITS;
    name = ".plt";
  }
}

void GotPltSection::addEntry(Symbol &sym) {
  assert(sym.auxIdx == ctx.symAux.size() - 1 &&
         ctx.symAux.back().pltIdx == entries.size());
  entries.push_back(&sym);
}

size_t GotPltSection::getSize() const {
  return (ctx.target->gotPltHeaderEntriesNum + entries.size()) *
         ctx.target->gotEntrySize;
}

void GotPltSection::writeTo(uint8_t *buf) {
  ctx.target->writeGotPltHeader(buf);
  buf += ctx.target->gotPltHeaderEntriesNum * ctx.target->gotEntrySize;
  for (const Symbol *b : entries) {
    ctx.target->writeGotPlt(buf, *b);
    buf += ctx.target->gotEntrySize;
  }
}

bool GotPltSection::isNeeded() const {
  // We need to emit GOTPLT even if it's empty if there's a relocation relative
  // to it.
  return !entries.empty() || hasGotPltOffRel;
}

static StringRef getIgotPltName(Ctx &ctx) {
  // On ARM the IgotPltSection is part of the GotSection.
  if (ctx.arg.emachine == EM_ARM)
    return ".got";

  // On PowerPC64 the GotPltSection is renamed to '.plt' so the IgotPltSection
  // needs to be named the same.
  if (ctx.arg.emachine == EM_PPC64)
    return ".plt";

  return ".got.plt";
}

// On PowerPC64 the GotPltSection type is SHT_NOBITS so we have to follow suit
// with the IgotPltSection.
IgotPltSection::IgotPltSection(Ctx &ctx)
    : SyntheticSection(ctx, getIgotPltName(ctx),
                       ctx.arg.emachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS,
                       SHF_ALLOC | SHF_WRITE, ctx.target->gotEntrySize) {}

void IgotPltSection::addEntry(Symbol &sym) {
  assert(ctx.symAux.back().pltIdx == entries.size());
  entries.push_back(&sym);
}

size_t IgotPltSection::getSize() const {
  return entries.size() * ctx.target->gotEntrySize;
}

void IgotPltSection::writeTo(uint8_t *buf) {
  for (const Symbol *b : entries) {
    ctx.target->writeIgotPlt(buf, *b);
    buf += ctx.target->gotEntrySize;
  }
}

StringTableSection::StringTableSection(Ctx &ctx, StringRef name, bool dynamic)
    : SyntheticSection(ctx, name, SHT_STRTAB, dynamic ? (uint64_t)SHF_ALLOC : 0,
                       1),
      dynamic(dynamic) {
  // ELF string tables start with a NUL byte.
  strings.push_back("");
  stringMap.try_emplace(CachedHashStringRef(""), 0);
  size = 1;
}

// Adds a string to the string table. If `hashIt` is true we hash and check for
// duplicates. It is optional because the name of global symbols are already
// uniqued and hashing them again has a big cost for a small value: uniquing
// them with some other string that happens to be the same.
unsigned StringTableSection::addString(StringRef s, bool hashIt) {
  if (hashIt) {
    auto r = stringMap.try_emplace(CachedHashStringRef(s), size);
    if (!r.second)
      return r.first->second;
  }
  if (s.empty())
    return 0;
  unsigned ret = this->size;
  this->size = this->size + s.size() + 1;
  strings.push_back(s);
  return ret;
}

void StringTableSection::writeTo(uint8_t *buf) {
  for (StringRef s : strings) {
    memcpy(buf, s.data(), s.size());
    buf[s.size()] = '\0';
    buf += s.size() + 1;
  }
}

// Returns the number of entries in .gnu.version_d: the number of
// non-VER_NDX_LOCAL-non-VER_NDX_GLOBAL definitions, plus 1.
// Note that we don't support vd_cnt > 1 yet.
static unsigned getVerDefNum(Ctx &ctx) {
  return namedVersionDefs(ctx).size() + 1;
}

template <class ELFT>
DynamicSection<ELFT>::DynamicSection(Ctx &ctx)
    : SyntheticSection(ctx, ".dynamic", SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE,
                       ctx.arg.wordsize) {
  this->entsize = ELFT::Is64Bits ? 16 : 8;

  // .dynamic section is not writable on MIPS and on Fuchsia OS
  // which passes -z rodynamic.
  // See "Special Section" in Chapter 4 in the following document:
  // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
  if (ctx.arg.emachine == EM_MIPS || ctx.arg.zRodynamic)
    this->flags = SHF_ALLOC;
}

// The output section .rela.dyn may include these synthetic sections:
//
// - part.relaDyn
// - ctx.in.relaPlt: this is included if a linker script places .rela.plt inside
//   .rela.dyn
//
// DT_RELASZ is the total size of the included sections.
static uint64_t addRelaSz(Ctx &ctx, const RelocationBaseSection &relaDyn) {
  size_t size = relaDyn.getSize();
  if (ctx.in.relaPlt->getParent() == relaDyn.getParent())
    size += ctx.in.relaPlt->getSize();
  return size;
}

// A Linker script may assign the RELA relocation sections to the same
// output section. When this occurs we cannot just use the OutputSection
// Size. Moreover the [DT_JMPREL, DT_JMPREL + DT_PLTRELSZ) is permitted to
// overlap with the [DT_RELA, DT_RELA + DT_RELASZ).
static uint64_t addPltRelSz(Ctx &ctx) { return ctx.in.relaPlt->getSize(); }

// Add remaining entries to complete .dynamic contents.
template <class ELFT>
std::vector<std::pair<int32_t, uint64_t>>
DynamicSection<ELFT>::computeContents() {
  elf::Partition &part = getPartition(ctx);
  bool isMain = part.name.empty();
  std::vector<std::pair<int32_t, uint64_t>> entries;

  auto addInt = [&](int32_t tag, uint64_t val) {
    entries.emplace_back(tag, val);
  };
  auto addInSec = [&](int32_t tag, const InputSection &sec) {
    entries.emplace_back(tag, sec.getVA());
  };

  for (StringRef s : ctx.arg.filterList)
    addInt(DT_FILTER, part.dynStrTab->addString(s));
  for (StringRef s : ctx.arg.auxiliaryList)
    addInt(DT_AUXILIARY, part.dynStrTab->addString(s));

  if (!ctx.arg.rpath.empty())
    addInt(ctx.arg.enableNewDtags ? DT_RUNPATH : DT_RPATH,
           part.dynStrTab->addString(ctx.arg.rpath));

  for (SharedFile *file : ctx.sharedFiles)
    if (file->isNeeded)
      addInt(DT_NEEDED, part.dynStrTab->addString(file->soName));

  if (isMain) {
    if (!ctx.arg.soName.empty())
      addInt(DT_SONAME, part.dynStrTab->addString(ctx.arg.soName));
  } else {
    if (!ctx.arg.soName.empty())
      addInt(DT_NEEDED, part.dynStrTab->addString(ctx.arg.soName));
    addInt(DT_SONAME, part.dynStrTab->addString(part.name));
  }

  // Set DT_FLAGS and DT_FLAGS_1.
  uint32_t dtFlags = 0;
  uint32_t dtFlags1 = 0;
  if (ctx.arg.bsymbolic == BsymbolicKind::All)
    dtFlags |= DF_SYMBOLIC;
  if (ctx.arg.zGlobal)
    dtFlags1 |= DF_1_GLOBAL;
  if (ctx.arg.zInitfirst)
    dtFlags1 |= DF_1_INITFIRST;
  if (ctx.arg.zInterpose)
    dtFlags1 |= DF_1_INTERPOSE;
  if (ctx.arg.zNodefaultlib)
    dtFlags1 |= DF_1_NODEFLIB;
  if (ctx.arg.zNodelete)
    dtFlags1 |= DF_1_NODELETE;
  if (ctx.arg.zNodlopen)
    dtFlags1 |= DF_1_NOOPEN;
  if (ctx.arg.pie)
    dtFlags1 |= DF_1_PIE;
  if (ctx.arg.zNow) {
    dtFlags |= DF_BIND_NOW;
    dtFlags1 |= DF_1_NOW;
  }
  if (ctx.arg.zOrigin) {
    dtFlags |= DF_ORIGIN;
    dtFlags1 |= DF_1_ORIGIN;
  }
  if (!ctx.arg.zText)
    dtFlags |= DF_TEXTREL;
  if (ctx.hasTlsIe && ctx.arg.shared)
    dtFlags |= DF_STATIC_TLS;

  if (dtFlags)
    addInt(DT_FLAGS, dtFlags);
  if (dtFlags1)
    addInt(DT_FLAGS_1, dtFlags1);

  // DT_DEBUG is a pointer to debug information used by debuggers at runtime. We
  // need it for each process, so we don't write it for DSOs. The loader writes
  // the pointer into this entry.
  //
  // DT_DEBUG is the only .dynamic entry that needs to be written to. Some
  // systems (currently only Fuchsia OS) provide other means to give the
  // debugger this information. Such systems may choose make .dynamic read-only.
  // If the target is such a system (used -z rodynamic) don't write DT_DEBUG.
  if (!ctx.arg.shared && !ctx.arg.relocatable && !ctx.arg.zRodynamic)
    addInt(DT_DEBUG, 0);

  if (part.relaDyn->isNeeded()) {
    addInSec(part.relaDyn->dynamicTag, *part.relaDyn);
    entries.emplace_back(part.relaDyn->sizeDynamicTag,
                         addRelaSz(ctx, *part.relaDyn));

    bool isRela = ctx.arg.isRela;
    addInt(isRela ? DT_RELAENT : DT_RELENT,
           isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel));

    // MIPS dynamic loader does not support RELCOUNT tag.
    // The problem is in the tight relation between dynamic
    // relocations and GOT. So do not emit this tag on MIPS.
    if (ctx.arg.emachine != EM_MIPS) {
      size_t numRelativeRels = part.relaDyn->getRelativeRelocCount();
      if (ctx.arg.zCombreloc && numRelativeRels)
        addInt(isRela ? DT_RELACOUNT : DT_RELCOUNT, numRelativeRels);
    }
  }
  if (part.relrDyn && part.relrDyn->getParent() &&
      !part.relrDyn->relocs.empty()) {
    addInSec(ctx.arg.useAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR,
             *part.relrDyn);
    addInt(ctx.arg.useAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ,
           part.relrDyn->getParent()->size);
    addInt(ctx.arg.useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT,
           sizeof(Elf_Relr));
  }
  if (part.relrAuthDyn && part.relrAuthDyn->getParent() &&
      !part.relrAuthDyn->relocs.empty()) {
    addInSec(DT_AARCH64_AUTH_RELR, *part.relrAuthDyn);
    addInt(DT_AARCH64_AUTH_RELRSZ, part.relrAuthDyn->getParent()->size);
    addInt(DT_AARCH64_AUTH_RELRENT, sizeof(Elf_Relr));
  }
  if (isMain && ctx.in.relaPlt->isNeeded()) {
    addInSec(DT_JMPREL, *ctx.in.relaPlt);
    entries.emplace_back(DT_PLTRELSZ, addPltRelSz(ctx));
    switch (ctx.arg.emachine) {
    case EM_MIPS:
      addInSec(DT_MIPS_PLTGOT, *ctx.in.gotPlt);
      break;
    case EM_S390:
      addInSec(DT_PLTGOT, *ctx.in.got);
      break;
    case EM_SPARCV9:
      addInSec(DT_PLTGOT, *ctx.in.plt);
      break;
    case EM_AARCH64:
      if (llvm::find_if(ctx.in.relaPlt->relocs, [&ctx = ctx](
                                                    const DynamicReloc &r) {
            return r.type == ctx.target->pltRel &&
                   r.sym->stOther & STO_AARCH64_VARIANT_PCS;
          }) != ctx.in.relaPlt->relocs.end())
        addInt(DT_AARCH64_VARIANT_PCS, 0);
      addInSec(DT_PLTGOT, *ctx.in.gotPlt);
      break;
    case EM_RISCV:
      if (llvm::any_of(ctx.in.relaPlt->relocs, [&ctx = ctx](
                                                   const DynamicReloc &r) {
            return r.type == ctx.target->pltRel &&
                   (r.sym->stOther & STO_RISCV_VARIANT_CC);
          }))
        addInt(DT_RISCV_VARIANT_CC, 0);
      [[fallthrough]];
    default:
      addInSec(DT_PLTGOT, *ctx.in.gotPlt);
      break;
    }
    addInt(DT_PLTREL, ctx.arg.isRela ? DT_RELA : DT_REL);
  }

  if (ctx.arg.emachine == EM_AARCH64) {
    if (ctx.arg.andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
      addInt(DT_AARCH64_BTI_PLT, 0);
    if (ctx.arg.zPacPlt)
      addInt(DT_AARCH64_PAC_PLT, 0);

    if (hasMemtag(ctx)) {
      addInt(DT_AARCH64_MEMTAG_MODE,
             ctx.arg.memtagMode == NT_MEMTAG_LEVEL_ASYNC);
      addInt(DT_AARCH64_MEMTAG_HEAP, ctx.arg.memtagHeap);
      addInt(DT_AARCH64_MEMTAG_STACK, ctx.arg.memtagStack);
      if (ctx.mainPart->memtagGlobalDescriptors->isNeeded()) {
        addInSec(DT_AARCH64_MEMTAG_GLOBALS,
                 *ctx.mainPart->memtagGlobalDescriptors);
        addInt(DT_AARCH64_MEMTAG_GLOBALSSZ,
               ctx.mainPart->memtagGlobalDescriptors->getSize());
      }
    }
  }

  addInSec(DT_SYMTAB, *part.dynSymTab);
  addInt(DT_SYMENT, sizeof(Elf_Sym));
  addInSec(DT_STRTAB, *part.dynStrTab);
  addInt(DT_STRSZ, part.dynStrTab->getSize());
  if (!ctx.arg.zText)
    addInt(DT_TEXTREL, 0);
  if (part.gnuHashTab && part.gnuHashTab->getParent())
    addInSec(DT_GNU_HASH, *part.gnuHashTab);
  if (part.hashTab && part.hashTab->getParent())
    addInSec(DT_HASH, *part.hashTab);

  if (isMain) {
    if (ctx.out.preinitArray) {
      addInt(DT_PREINIT_ARRAY, ctx.out.preinitArray->addr);
      addInt(DT_PREINIT_ARRAYSZ, ctx.out.preinitArray->size);
    }
    if (ctx.out.initArray) {
      addInt(DT_INIT_ARRAY, ctx.out.initArray->addr);
      addInt(DT_INIT_ARRAYSZ, ctx.out.initArray->size);
    }
    if (ctx.out.finiArray) {
      addInt(DT_FINI_ARRAY, ctx.out.finiArray->addr);
      addInt(DT_FINI_ARRAYSZ, ctx.out.finiArray->size);
    }

    if (Symbol *b = ctx.symtab->find(ctx.arg.init))
      if (b->isDefined())
        addInt(DT_INIT, b->getVA(ctx));
    if (Symbol *b = ctx.symtab->find(ctx.arg.fini))
      if (b->isDefined())
        addInt(DT_FINI, b->getVA(ctx));
  }

  if (part.verSym && part.verSym->isNeeded())
    addInSec(DT_VERSYM, *part.verSym);
  if (part.verDef && part.verDef->isLive()) {
    addInSec(DT_VERDEF, *part.verDef);
    addInt(DT_VERDEFNUM, getVerDefNum(ctx));
  }
  if (part.verNeed && part.verNeed->isNeeded()) {
    addInSec(DT_VERNEED, *part.verNeed);
    unsigned needNum = 0;
    for (SharedFile *f : ctx.sharedFiles)
      if (!f->verneedInfo.empty())
        ++needNum;
    addInt(DT_VERNEEDNUM, needNum);
  }

  if (ctx.arg.emachine == EM_MIPS) {
    addInt(DT_MIPS_RLD_VERSION, 1);
    addInt(DT_MIPS_FLAGS, RHF_NOTPOT);
    addInt(DT_MIPS_BASE_ADDRESS, ctx.target->getImageBase());
    addInt(DT_MIPS_SYMTABNO, part.dynSymTab->getNumSymbols());
    addInt(DT_MIPS_LOCAL_GOTNO, ctx.in.mipsGot->getLocalEntriesNum());

    if (const Symbol *b = ctx.in.mipsGot->getFirstGlobalEntry())
      addInt(DT_MIPS_GOTSYM, b->dynsymIndex);
    else
      addInt(DT_MIPS_GOTSYM, part.dynSymTab->getNumSymbols());
    addInSec(DT_PLTGOT, *ctx.in.mipsGot);
    if (ctx.in.mipsRldMap) {
      if (!ctx.arg.pie)
        addInSec(DT_MIPS_RLD_MAP, *ctx.in.mipsRldMap);
      // Store the offset to the .rld_map section
      // relative to the address of the tag.
      addInt(DT_MIPS_RLD_MAP_REL,
             ctx.in.mipsRldMap->getVA() - (getVA() + entries.size() * entsize));
    }
  }

  // DT_PPC_GOT indicates to glibc Secure PLT is used. If DT_PPC_GOT is absent,
  // glibc assumes the old-style BSS PLT layout which we don't support.
  if (ctx.arg.emachine == EM_PPC)
    addInSec(DT_PPC_GOT, *ctx.in.got);

  // Glink dynamic tag is required by the V2 abi if the plt section isn't empty.
  if (ctx.arg.emachine == EM_PPC64 && ctx.in.plt->isNeeded()) {
    // The Glink tag points to 32 bytes before the first lazy symbol resolution
    // stub, which starts directly after the header.
    addInt(DT_PPC64_GLINK,
           ctx.in.plt->getVA() + ctx.target->pltHeaderSize - 32);
  }

  if (ctx.arg.emachine == EM_PPC64)
    addInt(DT_PPC64_OPT, ctx.target->ppc64DynamicSectionOpt);

  addInt(DT_NULL, 0);
  return entries;
}

template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
  if (OutputSection *sec = getPartition(ctx).dynStrTab->getParent())
    getParent()->link = sec->sectionIndex;
  this->size = computeContents().size() * this->entsize;
}

template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *buf) {
  auto *p = reinterpret_cast<Elf_Dyn *>(buf);

  for (std::pair<int32_t, uint64_t> kv : computeContents()) {
    p->d_tag = kv.first;
    p->d_un.d_val = kv.second;
    ++p;
  }
}

uint64_t DynamicReloc::getOffset() const {
  return inputSec->getVA(offsetInSec);
}

int64_t DynamicReloc::computeAddend(Ctx &ctx) const {
  assert(!isFinal && "addend already computed");
  uint64_t ca = inputSec->getRelocTargetVA(
      ctx, Relocation{expr, type, 0, addend, sym}, getOffset());
  return ctx.arg.is64 ? ca : SignExtend64<32>(ca);
}

uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *symTab) const {
  if (!needsDynSymIndex())
    return 0;

  size_t index = symTab->getSymbolIndex(*sym);
  assert((index != 0 ||
          (type != symTab->ctx.target->gotRel &&
           type != symTab->ctx.target->pltRel) ||
          !symTab->ctx.mainPart->dynSymTab->getParent()) &&
         "GOT or PLT relocation must refer to symbol in dynamic symbol table");
  return index;
}

RelocationBaseSection::RelocationBaseSection(Ctx &ctx, StringRef name,
                                             uint32_t type, int32_t dynamicTag,
                                             int32_t sizeDynamicTag,
                                             bool combreloc,
                                             unsigned concurrency)
    : SyntheticSection(ctx, name, type, SHF_ALLOC, ctx.arg.wordsize),
      dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag),
      relocsVec(concurrency), relativeRel(ctx.target->relativeRel),
      combreloc(combreloc) {}

void RelocationBaseSection::addSymbolReloc(
    RelType dynType, InputSectionBase &isec, uint64_t offsetInSec, Symbol &sym,
    int64_t addend, std::optional<RelType> addendRelType) {
  addReloc(true, dynType, isec, offsetInSec, sym, addend, R_ADDEND,
           addendRelType ? *addendRelType : ctx.target->noneRel);
}

void RelocationBaseSection::addAddendOnlyRelocIfNonPreemptible(
    RelType dynType, InputSectionBase &isec, uint64_t offsetInSec, Symbol &sym,
    RelType addendRelType) {
  // No need to write an addend to the section for preemptible symbols.
  if (sym.isPreemptible)
    addReloc({dynType, &isec, offsetInSec, true, sym, 0, R_ADDEND});
  else
    addReloc(false, dynType, isec, offsetInSec, sym, 0, R_ABS, addendRelType);
}

void RelocationBaseSection::mergeRels() {
  size_t newSize = relativeRelocs.size();
  for (const auto &v : relocsVec)
    newSize += v.size();
  relativeRelocs.reserve(newSize);
  // Classify relocsVec entries into relativeRelocs or relocs. Note that
  // relocsVec may contain non-relative entries (e.g. R_AARCH64_AUTH_RELATIVE)
  // so we must check the type.
  for (const auto &v : relocsVec)
    for (const DynamicReloc &r : v)
      addReloc(r);
  relocsVec.clear();
}

void RelocationBaseSection::finalizeContents() {
  mergeRels();
  // Cache the count for DT_RELACOUNT. DynamicSection<ELFT>::computeContents
  // uses ctx.arg.zCombreloc (not the per-section combreloc) to decide whether
  // to emit DT_RELACOUNT, so this must match.
  if (combreloc)
    numRelativeRelocs = relativeRelocs.size();
  SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();

  // When linking glibc statically, .rel{,a}.plt contains R_*_IRELATIVE
  // relocations due to IFUNC (e.g. strcpy). sh_link will be set to 0 in that
  // case.
  if (symTab && symTab->getParent())
    getParent()->link = symTab->getParent()->sectionIndex;
  else
    getParent()->link = 0;

  if (ctx.in.relaPlt.get() == this && ctx.in.gotPlt->getParent()) {
    getParent()->flags |= ELF::SHF_INFO_LINK;
    getParent()->info = ctx.in.gotPlt->getParent()->sectionIndex;
  }
}

void DynamicReloc::finalize(Ctx &ctx, SymbolTableBaseSection *symt) {
  r_offset = getOffset();
  r_sym = getSymIndex(symt);
  addend = computeAddend(ctx);
  isFinal = true; // Catch errors
}

void RelocationBaseSection::computeRels() {
  SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();
  parallelForEach(relativeRelocs, [&ctx = ctx, symTab](DynamicReloc &rel) {
    rel.finalize(ctx, symTab);
  });
  parallelForEach(relocs, [&ctx = ctx, symTab](DynamicReloc &rel) {
    rel.finalize(ctx, symTab);
  });

  // Place IRELATIVE relocations last so that other dynamic relocations are
  // applied before IFUNC resolvers run.
  auto irelative = std::stable_partition(
      relocs.begin(), relocs.end(),
      [t = ctx.target->iRelativeRel](auto &r) { return r.type != t; });

  // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to
  // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset
  // is to make results easier to read.
  parallelSort(relativeRelocs.begin(), relativeRelocs.end(),
               [](auto &a, auto &b) { return a.r_offset < b.r_offset; });
  // Non-relative relocations are few, so don't bother with parallelSort.
  if (combreloc)
    llvm::sort(relocs.begin(), irelative, [](auto &a, auto &b) {
      return std::tie(a.r_sym, a.r_offset) < std::tie(b.r_sym, b.r_offset);
    });
}

template <class ELFT>
RelocationSection<ELFT>::RelocationSection(Ctx &ctx, StringRef name,
                                           bool combreloc, unsigned concurrency)
    : RelocationBaseSection(ctx, name, ctx.arg.isRela ? SHT_RELA : SHT_REL,
                            ctx.arg.isRela ? DT_RELA : DT_REL,
                            ctx.arg.isRela ? DT_RELASZ : DT_RELSZ, combreloc,
                            concurrency) {
  this->entsize = ctx.arg.isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
}

template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) {
  computeRels();
  // Write relative relocations first for DT_REL[A]COUNT.
  for (const DynamicReloc &rel :
       llvm::concat<const DynamicReloc>(relativeRelocs, relocs)) {
    auto *p = reinterpret_cast<Elf_Rela *>(buf);
    p->r_offset = rel.r_offset;
    p->setSymbolAndType(rel.r_sym, rel.type, ctx.arg.isMips64EL);
    if (ctx.arg.isRela)
      p->r_addend = rel.addend;
    buf += ctx.arg.isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
  }
}

RelrBaseSection::RelrBaseSection(Ctx &ctx, unsigned concurrency,
                                 bool isAArch64Auth)
    : SyntheticSection(
          ctx, isAArch64Auth ? ".relr.auth.dyn" : ".relr.dyn",
          isAArch64Auth
              ? SHT_AARCH64_AUTH_RELR
              : (ctx.arg.useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR),
          SHF_ALLOC, ctx.arg.wordsize),
      relocsVec(concurrency) {}

void RelrBaseSection::mergeRels() {
  size_t newSize = relocs.size();
  for (const auto &v : relocsVec)
    newSize += v.size();
  relocs.reserve(newSize);
  for (const auto &v : relocsVec)
    llvm::append_range(relocs, v);
  relocsVec.clear();
}

void RelrBaseSection::finalizeContents() { mergeRels(); }

template <class ELFT>
AndroidPackedRelocationSection<ELFT>::AndroidPackedRelocationSection(
    Ctx &ctx, StringRef name, unsigned concurrency)
    : RelocationBaseSection(
          ctx, name, ctx.arg.isRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL,
          ctx.arg.isRela ? DT_ANDROID_RELA : DT_ANDROID_REL,
          ctx.arg.isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ,
          /*combreloc=*/false, concurrency) {
  this->entsize = 1;
}

template <class ELFT>
bool AndroidPackedRelocationSection<ELFT>::updateAllocSize(Ctx &ctx) {
  // This function computes the contents of an Android-format packed relocation
  // section.
  //
  // This format compresses relocations by using relocation groups to factor out
  // fields that are common between relocations and storing deltas from previous
  // relocations in SLEB128 format (which has a short representation for small
  // numbers). A good example of a relocation type with common fields is
  // R_*_RELATIVE, which is normally used to represent function pointers in
  // vtables. In the REL format, each relative relocation has the same r_info
  // field, and is only different from other relative relocations in terms of
  // the r_offset field. By sorting relocations by offset, grouping them by
  // r_info and representing each relocation with only the delta from the
  // previous offset, each 8-byte relocation can be compressed to as little as 1
  // byte (or less with run-length encoding). This relocation packer was able to
  // reduce the size of the relocation section in an Android Chromium DSO from
  // 2,911,184 bytes to 174,693 bytes, or 6% of the original size.
  //
  // A relocation section consists of a header containing the literal bytes
  // 'APS2' followed by a sequence of SLEB128-encoded integers. The first two
  // elements are the total number of relocations in the section and an initial
  // r_offset value. The remaining elements define a sequence of relocation
  // groups. Each relocation group starts with a header consisting of the
  // following elements:
  //
  // - the number of relocations in the relocation group
  // - flags for the relocation group
  // - (if RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG is set) the r_offset delta
  //   for each relocation in the group.
  // - (if RELOCATION_GROUPED_BY_INFO_FLAG is set) the value of the r_info
  //   field for each relocation in the group.
  // - (if RELOCATION_GROUP_HAS_ADDEND_FLAG and
  //   RELOCATION_GROUPED_BY_ADDEND_FLAG are set) the r_addend delta for
  //   each relocation in the group.
  //
  // Following the relocation group header are descriptions of each of the
  // relocations in the group. They consist of the following elements:
  //
  // - (if RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG is not set) the r_offset
  //   delta for this relocation.
  // - (if RELOCATION_GROUPED_BY_INFO_FLAG is not set) the value of the r_info
  //   field for this relocation.
  // - (if RELOCATION_GROUP_HAS_ADDEND_FLAG is set and
  //   RELOCATION_GROUPED_BY_ADDEND_FLAG is not set) the r_addend delta for
  //   this relocation.

  size_t oldSize = relocData.size();

  relocData = {'A', 'P', 'S', '2'};
  raw_svector_ostream os(relocData);
  auto add = [&](int64_t v) { encodeSLEB128(v, os); };

  // The format header includes the number of relocations and the initial
  // offset (we set this to zero because the first relocation group will
  // perform the initial adjustment).
  add(relativeRelocs.size() + relocs.size());
  add(0);

  SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();
  auto makeRela = [&](const DynamicReloc &rel) {
    Elf_Rela r;
    r.r_offset = rel.getOffset();
    r.setSymbolAndType(rel.getSymIndex(symTab), rel.type, false);
    r.r_addend = ctx.arg.isRela ? rel.computeAddend(ctx) : 0;
    return r;
  };
  std::vector<Elf_Rela> relatives, nonRelatives;
  for (const DynamicReloc &rel : relativeRelocs)
    relatives.push_back(makeRela(rel));
  for (const DynamicReloc &rel : relocs)
    nonRelatives.push_back(makeRela(rel));

  llvm::sort(relatives, [](const Elf_Rel &a, const Elf_Rel &b) {
    return a.r_offset < b.r_offset;
  });

  // Try to find groups of relative relocations which are spaced one word
  // apart from one another. These generally correspond to vtable entries. The
  // format allows these groups to be encoded using a sort of run-length
  // encoding, but each group will cost 7 bytes in addition to the offset from
  // the previous group, so it is only profitable to do this for groups of
  // size 8 or larger.
  std::vector<Elf_Rela> ungroupedRelatives;
  std::vector<std::vector<Elf_Rela>> relativeGroups;
  for (auto i = relatives.begin(), e = relatives.end(); i != e;) {
    std::vector<Elf_Rela> group;
    do {
      group.push_back(*i++);
    } while (i != e && (i - 1)->r_offset + ctx.arg.wordsize == i->r_offset);

    if (group.size() < 8)
      ungroupedRelatives.insert(ungroupedRelatives.end(), group.begin(),
                                group.end());
    else
      relativeGroups.emplace_back(std::move(group));
  }

  // For non-relative relocations, we would like to:
  //   1. Have relocations with the same symbol offset to be consecutive, so
  //      that the runtime linker can speed-up symbol lookup by implementing an
  //      1-entry cache.
  //   2. Group relocations by r_info to reduce the size of the relocation
  //      section.
  // Since the symbol offset is the high bits in r_info, sorting by r_info
  // allows us to do both.
  //
  // For Rela, we also want to sort by r_addend when r_info is the same. This
  // enables us to group by r_addend as well.
  llvm::sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) {
    return std::tie(a.r_info, a.r_addend, a.r_offset) <
           std::tie(b.r_info, b.r_addend, b.r_offset);
  });

  // Group relocations with the same r_info. Note that each group emits a group
  // header and that may make the relocation section larger. It is hard to
  // estimate the size of a group header as the encoded size of that varies
  // based on r_info. However, we can approximate this trade-off by the number
  // of values encoded. Each group header contains 3 values, and each relocation
  // in a group encodes one less value, as compared to when it is not grouped.
  // Therefore, we only group relocations if there are 3 or more of them with
  // the same r_info.
  //
  // For Rela, the addend for most non-relative relocations is zero, and thus we
  // can usually get a smaller relocation section if we group relocations with 0
  // addend as well.
  std::vector<Elf_Rela> ungroupedNonRelatives;
  std::vector<std::vector<Elf_Rela>> nonRelativeGroups;
  for (auto i = nonRelatives.begin(), e = nonRelatives.end(); i != e;) {
    auto j = i + 1;
    while (j != e && i->r_info == j->r_info &&
           (!ctx.arg.isRela || i->r_addend == j->r_addend))
      ++j;
    if (j - i < 3 || (ctx.arg.isRela && i->r_addend != 0))
      ungroupedNonRelatives.insert(ungroupedNonRelatives.end(), i, j);
    else
      nonRelativeGroups.emplace_back(i, j);
    i = j;
  }

  // Sort ungrouped relocations by offset to minimize the encoded length.
  llvm::sort(ungroupedNonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) {
    return a.r_offset < b.r_offset;
  });

  unsigned hasAddendIfRela =
      ctx.arg.isRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0;

  uint64_t offset = 0;
  uint64_t addend = 0;

  // Emit the run-length encoding for the groups of adjacent relative
  // relocations. Each group is represented using two groups in the packed
  // format. The first is used to set the current offset to the start of the
  // group (and also encodes the first relocation), and the second encodes the
  // remaining relocations.
  for (std::vector<Elf_Rela> &g : relativeGroups) {
    // The first relocation in the group.
    add(1);
    add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG |
        RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela);
    add(g[0].r_offset - offset);
    add(ctx.target->relativeRel);
    if (ctx.arg.isRela) {
      add(g[0].r_addend - addend);
      addend = g[0].r_addend;
    }

    // The remaining relocations.
    add(g.size() - 1);
    add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG |
        RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela);
    add(ctx.arg.wordsize);
    add(ctx.target->relativeRel);
    if (ctx.arg.isRela) {
      for (const auto &i : llvm::drop_begin(g)) {
        add(i.r_addend - addend);
        addend = i.r_addend;
      }
    }

    offset = g.back().r_offset;
  }

  // Now the ungrouped relatives.
  if (!ungroupedRelatives.empty()) {
    add(ungroupedRelatives.size());
    add(RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela);
    add(ctx.target->relativeRel);
    for (Elf_Rela &r : ungroupedRelatives) {
      add(r.r_offset - offset);
      offset = r.r_offset;
      if (ctx.arg.isRela) {
        add(r.r_addend - addend);
        addend = r.r_addend;
      }
    }
  }

  // Grouped non-relatives.
  for (ArrayRef<Elf_Rela> g : nonRelativeGroups) {
    add(g.size());
    add(RELOCATION_GROUPED_BY_INFO_FLAG);
    add(g[0].r_info);
    for (const Elf_Rela &r : g) {
      add(r.r_offset - offset);
      offset = r.r_offset;
    }
    addend = 0;
  }

  // Finally the ungrouped non-relative relocations.
  if (!ungroupedNonRelatives.empty()) {
    add(ungroupedNonRelatives.size());
    add(hasAddendIfRela);
    for (Elf_Rela &r : ungroupedNonRelatives) {
      add(r.r_offset - offset);
      offset = r.r_offset;
      add(r.r_info);
      if (ctx.arg.isRela) {
        add(r.r_addend - addend);
        addend = r.r_addend;
      }
    }
  }

  // Don't allow the section to shrink; otherwise the size of the section can
  // oscillate infinitely.
  if (relocData.size() < oldSize)
    relocData.append(oldSize - relocData.size(), 0);

  // Returns whether the section size changed. We need to keep recomputing both
  // section layout and the contents of this section until the size converges
  // because changing this section's size can affect section layout, which in
  // turn can affect the sizes of the LEB-encoded integers stored in this
  // section.
  return relocData.size() != oldSize;
}

template <class ELFT>
RelrSection<ELFT>::RelrSection(Ctx &ctx, unsigned concurrency,
                               bool isAArch64Auth)
    : RelrBaseSection(ctx, concurrency, isAArch64Auth) {
  this->entsize = ctx.arg.wordsize;
}

template <class ELFT> bool RelrSection<ELFT>::updateAllocSize(Ctx &ctx) {
  // This function computes the contents of an SHT_RELR packed relocation
  // section.
  //
  // Proposal for adding SHT_RELR sections to generic-abi is here:
  //   https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
  //
  // The encoded sequence of Elf64_Relr entries in a SHT_RELR section looks
  // like [ AAAAAAAA BBBBBBB1 BBBBBBB1 ... AAAAAAAA BBBBBB1 ... ]
  //
  // i.e. start with an address, followed by any number of bitmaps. The address
  // entry encodes 1 relocation. The subsequent bitmap entries encode up to 63
  // relocations each, at subsequent offsets following the last address entry.
  //
  // The bitmap entries must have 1 in the least significant bit. The assumption
  // here is that an address cannot have 1 in lsb. Odd addresses are not
  // supported.
  //
  // Excluding the least significant bit in the bitmap, each non-zero bit in
  // the bitmap represents a relocation to be applied to a corresponding machine
  // word that follows the base address word. The second least significant bit
  // represents the machine word immediately following the initial address, and
  // each bit that follows represents the next word, in linear order. As such,
  // a single bitmap can encode up to 31 relocations in a 32-bit object, and
  // 63 relocations in a 64-bit object.
  //
  // This encoding has a couple of interesting properties:
  // 1. Looking at any entry, it is clear whether it's an address or a bitmap:
  //    even means address, odd means bitmap.
  // 2. Just a simple list of addresses is a valid encoding.

  size_t oldSize = relrRelocs.size();
  relrRelocs.clear();

  const size_t wordsize = sizeof(typename ELFT::uint);

  // Number of bits to use for the relocation offsets bitmap.
  // Must be either 63 or 31.
  const size_t nBits = wordsize * 8 - 1;

  // Get offsets for all relative relocations and sort them.
  std::unique_ptr<uint64_t[]> offsets(new uint64_t[relocs.size()]);
  for (auto [i, r] : llvm::enumerate(relocs))
    offsets[i] = r.getOffset();
  llvm::sort(offsets.get(), offsets.get() + relocs.size());

  // For each leading relocation, find following ones that can be folded
  // as a bitmap and fold them.
  for (size_t i = 0, e = relocs.size(); i != e;) {
    // Add a leading relocation.
    relrRelocs.push_back(Elf_Relr(offsets[i]));
    uint64_t base = offsets[i] + wordsize;
    ++i;

    // Find foldable relocations to construct bitmaps.
    for (;;) {
      uint64_t bitmap = 0;
      for (; i != e; ++i) {
        uint64_t d = offsets[i] - base;
        if (d >= nBits * wordsize || d % wordsize)
          break;
        bitmap |= uint64_t(1) << (d / wordsize);
      }
      if (!bitmap)
        break;
      relrRelocs.push_back(Elf_Relr((bitmap << 1) | 1));
      base += nBits * wordsize;
    }
  }

  // Don't allow the section to shrink; otherwise the size of the section can
  // oscillate infinitely. Trailing 1s do not decode to more relocations.
  if (relrRelocs.size() < oldSize) {
    Log(ctx) << ".relr.dyn needs " << (oldSize - relrRelocs.size())
             << " padding word(s)";
    relrRelocs.resize(oldSize, Elf_Relr(1));
  }

  return relrRelocs.size() != oldSize;
}

SymbolTableBaseSection::SymbolTableBaseSection(Ctx &ctx,
                                               StringTableSection &strTabSec)
    : SyntheticSection(ctx, strTabSec.isDynamic() ? ".dynsym" : ".symtab",
                       strTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
                       strTabSec.isDynamic() ? (uint64_t)SHF_ALLOC : 0,
                       ctx.arg.wordsize),
      strTabSec(strTabSec) {}

// Orders symbols according to their positions in the GOT,
// in compliance with MIPS ABI rules.
// See "Global Offset Table" in Chapter 5 in the following document
// for detailed description:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
static void sortMipsSymbols(Ctx &ctx, SmallVector<SymbolTableEntry, 0> &syms) {
  llvm::stable_sort(syms,
                    [&](const SymbolTableEntry &l, const SymbolTableEntry &r) {
                      // Sort entries related to non-local preemptible symbols
                      // by GOT indexes. All other entries go to the beginning
                      // of a dynsym in arbitrary order.
                      if (l.sym->isInGot(ctx) && r.sym->isInGot(ctx))
                        return l.sym->getGotIdx(ctx) < r.sym->getGotIdx(ctx);
                      if (!l.sym->isInGot(ctx) && !r.sym->isInGot(ctx))
                        return false;
                      return !l.sym->isInGot(ctx);
                    });
}

void SymbolTableBaseSection::finalizeContents() {
  if (OutputSection *sec = strTabSec.getParent())
    getParent()->link = sec->sectionIndex;

  if (this->type != SHT_DYNSYM) {
    sortSymTabSymbols();
    return;
  }

  // If it is a .dynsym, there should be no local symbols, but we need
  // to do a few things for the dynamic linker.

  // Section's Info field has the index of the first non-local symbol.
  // Because the first symbol entry is a null entry, 1 is the first.
  getParent()->info = 1;

  if (getPartition(ctx).gnuHashTab) {
    // NB: It also sorts Symbols to meet the GNU hash table requirements.
    getPartition(ctx).gnuHashTab->addSymbols(symbols);
  } else if (ctx.arg.emachine == EM_MIPS) {
    sortMipsSymbols(ctx, symbols);
  }

  // Only the main partition's dynsym indexes are stored in the symbols
  // themselves. All other partitions use a lookup table.
  if (this == ctx.mainPart->dynSymTab.get()) {
    size_t i = 0;
    for (const SymbolTableEntry &s : symbols)
      s.sym->dynsymIndex = ++i;
  }
}

// The ELF spec requires that all local symbols precede global symbols, so we
// sort symbol entries in this function. (For .dynsym, we don't do that because
// symbols for dynamic linking are inherently all globals.)
//
// Aside from above, we put local symbols in groups starting with the STT_FILE
// symbol. That is convenient for purpose of identifying where are local symbols
// coming from.
void SymbolTableBaseSection::sortSymTabSymbols() {
  // Move all local symbols before global symbols.
  auto e = std::stable_partition(
      symbols.begin(), symbols.end(),
      [](const SymbolTableEntry &s) { return s.sym->isLocal(); });
  size_t numLocals = e - symbols.begin();
  getParent()->info = numLocals + 1;

  // We want to group the local symbols by file. For that we rebuild the local
  // part of the symbols vector. We do not need to care about the STT_FILE
  // symbols, they are already naturally placed first in each group. That
  // happens because STT_FILE is always the first symbol in the object and hence
  // precede all other local symbols we add for a file.
  MapVector<InputFile *, SmallVector<SymbolTableEntry, 0>> arr;
  for (const SymbolTableEntry &s : llvm::make_range(symbols.begin(), e))
    arr[s.sym->file].push_back(s);

  auto i = symbols.begin();
  for (auto &p : arr)
    for (SymbolTableEntry &entry : p.second)
      *i++ = entry;
}

void SymbolTableBaseSection::addSymbol(Symbol *b) {
  // Adding a local symbol to a .dynsym is a bug.
  assert(this->type != SHT_DYNSYM || !b->isLocal());
  symbols.push_back({b, strTabSec.addString(b->getName(), false)});
}

size_t SymbolTableBaseSection::getSymbolIndex(const Symbol &sym) {
  if (this == ctx.mainPart->dynSymTab.get())
    return sym.dynsymIndex;

  // Initializes symbol lookup tables lazily. This is used only for -r,
  // --emit-relocs and dynsyms in partitions other than the main one.
  llvm::call_once(onceFlag, [&] {
    symbolIndexMap.reserve(symbols.size());
    size_t i = 0;
    for (const SymbolTableEntry &e : symbols) {
      if (e.sym->type == STT_SECTION)
        sectionIndexMap[e.sym->getOutputSection()] = ++i;
      else
        symbolIndexMap[e.sym] = ++i;
    }
  });

  // Section symbols are mapped based on their output sections
  // to maintain their semantics.
  if (sym.type == STT_SECTION)
    return sectionIndexMap.lookup(sym.getOutputSection());
  return symbolIndexMap.lookup(&sym);
}

template <class ELFT>
SymbolTableSection<ELFT>::SymbolTableSection(Ctx &ctx,
                                             StringTableSection &strTabSec)
    : SymbolTableBaseSection(ctx, strTabSec) {
  this->entsize = sizeof(Elf_Sym);
}

static BssSection *getCommonSec(bool relocatable, Symbol *sym) {
  if (relocatable)
    if (auto *d = dyn_cast<Defined>(sym))
      return dyn_cast_or_null<BssSection>(d->section);
  return nullptr;
}

static uint32_t getSymSectionIndex(Symbol *sym) {
  assert(!(sym->hasFlag(NEEDS_COPY) && sym->isObject()));
  if (!isa<Defined>(sym) || sym->hasFlag(NEEDS_COPY))
    return SHN_UNDEF;
  if (const OutputSection *os = sym->getOutputSection())
    return os->sectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX
                                             : os->sectionIndex;
  return SHN_ABS;
}

// Write the internal symbol table contents to the output symbol table.
template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
  // The first entry is a null entry as per the ELF spec.
  buf += sizeof(Elf_Sym);

  auto *eSym = reinterpret_cast<Elf_Sym *>(buf);
  bool relocatable = ctx.arg.relocatable;
  for (SymbolTableEntry &ent : symbols) {
    Symbol *sym = ent.sym;
    bool isDefinedHere = type == SHT_SYMTAB || sym->partition == partition;

    // Set st_name, st_info and st_other.
    eSym->st_name = ent.strTabOffset;
    eSym->setBindingAndType(sym->binding, sym->type);
    eSym->st_other = sym->stOther;

    if (BssSection *commonSec = getCommonSec(relocatable, sym)) {
      // When -r is specified, a COMMON symbol is not allocated. Its st_shndx
      // holds SHN_COMMON and st_value holds the alignment.
      eSym->st_shndx = SHN_COMMON;
      eSym->st_value = commonSec->addralign;
      eSym->st_size = cast<Defined>(sym)->size;
    } else {
      const uint32_t shndx = getSymSectionIndex(sym);
      if (isDefinedHere) {
        eSym->st_shndx = shndx;
        eSym->st_value = sym->getVA(ctx);
        // Copy symbol size if it is a defined symbol. st_size is not
        // significant for undefined symbols, so whether copying it or not is up
        // to us if that's the case. We'll leave it as zero because by not
        // setting a value, we can get the exact same outputs for two sets of
        // input files that differ only in undefined symbol size in DSOs.
        eSym->st_size = shndx != SHN_UNDEF ? cast<Defined>(sym)->size : 0;
      } else {
        eSym->st_shndx = 0;
        eSym->st_value = 0;
        eSym->st_size = 0;
      }
    }

    ++eSym;
  }

  // On MIPS we need to mark symbol which has a PLT entry and requires
  // pointer equality by STO_MIPS_PLT flag. That is necessary to help
  // dynamic linker distinguish such symbols and MIPS lazy-binding stubs.
  // https://sourceware.org/ml/binutils/2008-07/txt00000.txt
  if (ctx.arg.emachine == EM_MIPS) {
    auto *eSym = reinterpret_cast<Elf_Sym *>(buf);

    for (SymbolTableEntry &ent : symbols) {
      Symbol *sym = ent.sym;
      if (sym->isInPlt(ctx) && sym->hasFlag(NEEDS_COPY))
        eSym->st_other |= STO_MIPS_PLT;
      if (isMicroMips(ctx)) {
        // We already set the less-significant bit for symbols
        // marked by the `STO_MIPS_MICROMIPS` flag and for microMIPS PLT
        // records. That allows us to distinguish such symbols in
        // the `MIPS<ELFT>::relocate()` routine. Now we should
        // clear that bit for non-dynamic symbol table, so tools
        // like `objdump` will be able to deal with a correct
        // symbol position.
        if (sym->isDefined() &&
            ((sym->stOther & STO_MIPS_MICROMIPS) || sym->hasFlag(NEEDS_COPY))) {
          if (!strTabSec.isDynamic())
            eSym->st_value &= ~1;
          eSym->st_other |= STO_MIPS_MICROMIPS;
        }
      }
      if (ctx.arg.relocatable)
        if (auto *d = dyn_cast<Defined>(sym))
          if (isMipsPIC<ELFT>(d))
            eSym->st_other |= STO_MIPS_PIC;
      ++eSym;
    }
  }
}

SymtabShndxSection::SymtabShndxSection(Ctx &ctx)
    : SyntheticSection(ctx, ".symtab_shndx", SHT_SYMTAB_SHNDX, 0, 4) {
  this->entsize = 4;
}

void SymtabShndxSection::writeTo(uint8_t *buf) {
  // We write an array of 32 bit values, where each value has 1:1 association
  // with an entry in ctx.in.symTab if the corresponding entry contains
  // SHN_XINDEX, we need to write actual index, otherwise, we must write
  // SHN_UNDEF(0).
  buf += 4; // Ignore .symtab[0] entry.
  bool relocatable = ctx.arg.relocatable;
  for (const SymbolTableEntry &entry : ctx.in.symTab->getSymbols()) {
    if (!getCommonSec(relocatable, entry.sym) &&
        getSymSectionIndex(entry.sym) == SHN_XINDEX)
      write32(ctx, buf, entry.sym->getOutputSection()->sectionIndex);
    buf += 4;
  }
}

bool SymtabShndxSection::isNeeded() const {
  // SHT_SYMTAB can hold symbols with section indices values up to
  // SHN_LORESERVE. If we need more, we want to use extension SHT_SYMTAB_SHNDX
  // section. Problem is that we reveal the final section indices a bit too
  // late, and we do not know them here. For simplicity, we just always create
  // a .symtab_shndx section when the amount of output sections is huge.
  size_t size = 0;
  for (SectionCommand *cmd : ctx.script->sectionCommands)
    if (isa<OutputDesc>(cmd))
      ++size;
  return size >= SHN_LORESERVE;
}

void SymtabShndxSection::finalizeContents() {
  getParent()->link = ctx.in.symTab->getParent()->sectionIndex;
}

size_t SymtabShndxSection::getSize() const {
  return ctx.in.symTab->getNumSymbols() * 4;
}

// .hash and .gnu.hash sections contain on-disk hash tables that map
// symbol names to their dynamic symbol table indices. Their purpose
// is to help the dynamic linker resolve symbols quickly. If ELF files
// don't have them, the dynamic linker has to do linear search on all
// dynamic symbols, which makes programs slower. Therefore, a .hash
// section is added to a DSO by default.
//
// The Unix semantics of resolving dynamic symbols is somewhat expensive.
// Each ELF file has a list of DSOs that the ELF file depends on and a
// list of dynamic symbols that need to be resolved from any of the
// DSOs. That means resolving all dynamic symbols takes O(m)*O(n)
// where m is the number of DSOs and n is the number of dynamic
// symbols. For modern large programs, both m and n are large.  So
// making each step faster by using hash tables substantially
// improves time to load programs.
//
// (Note that this is not the only way to design the shared library.
// For instance, the Windows DLL takes a different approach. On
// Windows, each dynamic symbol has a name of DLL from which the symbol
// has to be resolved. That makes the cost of symbol resolution O(n).
// This disables some hacky techniques you can use on Unix such as
// LD_PRELOAD, but this is arguably better semantics than the Unix ones.)
//
// Due to historical reasons, we have two different hash tables, .hash
// and .gnu.hash. They are for the same purpose, and .gnu.hash is a new
// and better version of .hash. .hash is just an on-disk hash table, but
// .gnu.hash has a bloom filter in addition to a hash table to skip
// DSOs very quickly. If you are sure that your dynamic linker knows
// about .gnu.hash, you want to specify --hash-style=gnu. Otherwise, a
// safe bet is to specify --hash-style=both for backward compatibility.
GnuHashTableSection::GnuHashTableSection(Ctx &ctx)
    : SyntheticSection(ctx, ".gnu.hash", SHT_GNU_HASH, SHF_ALLOC,
                       ctx.arg.wordsize) {}

void GnuHashTableSection::finalizeContents() {
  if (OutputSection *sec = getPartition(ctx).dynSymTab->getParent())
    getParent()->link = sec->sectionIndex;

  // Computes bloom filter size in word size. We want to allocate 12
  // bits for each symbol. It must be a power of two.
  if (symbols.empty()) {
    maskWords = 1;
  } else {
    uint64_t numBits = symbols.size() * 12;
    maskWords = NextPowerOf2(numBits / (ctx.arg.wordsize * 8));
  }

  size = 16;                            // Header
  size += ctx.arg.wordsize * maskWords; // Bloom filter
  size += nBuckets * 4;                 // Hash buckets
  size += symbols.size() * 4;           // Hash values
}

void GnuHashTableSection::writeTo(uint8_t *buf) {
  // Write a header.
  write32(ctx, buf, nBuckets);
  write32(ctx, buf + 4,
          getPartition(ctx).dynSymTab->getNumSymbols() - symbols.size());
  write32(ctx, buf + 8, maskWords);
  write32(ctx, buf + 12, Shift2);
  buf += 16;

  // Write the 2-bit bloom filter.
  const unsigned c = ctx.arg.is64 ? 64 : 32;
  for (const Entry &sym : symbols) {
    // When C = 64, we choose a word with bits [6:...] and set 1 to two bits in
    // the word using bits [0:5] and [26:31].
    size_t i = (sym.hash / c) & (maskWords - 1);
    uint64_t val = readUint(ctx, buf + i * ctx.arg.wordsize);
    val |= uint64_t(1) << (sym.hash % c);
    val |= uint64_t(1) << ((sym.hash >> Shift2) % c);
    writeUint(ctx, buf + i * ctx.arg.wordsize, val);
  }
  buf += ctx.arg.wordsize * maskWords;

  // Write the hash table.
  uint32_t *buckets = reinterpret_cast<uint32_t *>(buf);
  uint32_t oldBucket = -1;
  uint32_t *values = buckets + nBuckets;
  for (auto i = symbols.begin(), e = symbols.end(); i != e; ++i) {
    // Write a hash value. It represents a sequence of chains that share the
    // same hash modulo value. The last element of each chain is terminated by
    // LSB 1.
    uint32_t hash = i->hash;
    bool isLastInChain = (i + 1) == e || i->bucketIdx != (i + 1)->bucketIdx;
    hash = isLastInChain ? hash | 1 : hash & ~1;
    write32(ctx, values++, hash);

    if (i->bucketIdx == oldBucket)
      continue;
    // Write a hash bucket. Hash buckets contain indices in the following hash
    // value table.
    write32(ctx, buckets + i->bucketIdx,
            getPartition(ctx).dynSymTab->getSymbolIndex(*i->sym));
    oldBucket = i->bucketIdx;
  }
}

// Add symbols to this symbol hash table. Note that this function
// destructively sort a given vector -- which is needed because
// GNU-style hash table places some sorting requirements.
void GnuHashTableSection::addSymbols(SmallVectorImpl<SymbolTableEntry> &v) {
  // We cannot use 'auto' for Mid because GCC 6.1 cannot deduce
  // its type correctly.
  auto mid =
      std::stable_partition(v.begin(), v.end(), [&](const SymbolTableEntry &s) {
        return !s.sym->isDefined() || s.sym->partition != partition;
      });

  // We chose load factor 4 for the on-disk hash table. For each hash
  // collision, the dynamic linker will compare a uint32_t hash value.
  // Since the integer comparison is quite fast, we believe we can
  // make the load factor even larger. 4 is just a conservative choice.
  //
  // Note that we don't want to create a zero-sized hash table because
  // Android loader as of 2018 doesn't like a .gnu.hash containing such
  // table. If that's the case, we create a hash table with one unused
  // dummy slot.
  nBuckets = std::max<size_t>((v.end() - mid) / 4, 1);

  if (mid == v.end())
    return;

  for (SymbolTableEntry &ent : llvm::make_range(mid, v.end())) {
    Symbol *b = ent.sym;
    uint32_t hash = hashGnu(b->getName());
    uint32_t bucketIdx = hash % nBuckets;
    symbols.push_back({b, ent.strTabOffset, hash, bucketIdx});
  }

  llvm::sort(symbols, [](const Entry &l, const Entry &r) {
    return std::tie(l.bucketIdx, l.strTabOffset) <
           std::tie(r.bucketIdx, r.strTabOffset);
  });

  v.erase(mid, v.end());
  for (const Entry &ent : symbols)
    v.push_back({ent.sym, ent.strTabOffset});
}

HashTableSection::HashTableSection(Ctx &ctx)
    : SyntheticSection(ctx, ".hash", SHT_HASH, SHF_ALLOC, 4) {
  this->entsize = 4;
}

void HashTableSection::finalizeContents() {
  SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();

  if (OutputSection *sec = symTab->getParent())
    getParent()->link = sec->sectionIndex;

  unsigned numEntries = 2;               // nbucket and nchain.
  numEntries += symTab->getNumSymbols(); // The chain entries.

  // Create as many buckets as there are symbols.
  numEntries += symTab->getNumSymbols();
  this->size = numEntries * 4;
}

void HashTableSection::writeTo(uint8_t *buf) {
  SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();
  unsigned numSymbols = symTab->getNumSymbols();

  uint32_t *p = reinterpret_cast<uint32_t *>(buf);
  write32(ctx, p++, numSymbols); // nbucket
  write32(ctx, p++, numSymbols); // nchain

  uint32_t *buckets = p;
  uint32_t *chains = p + numSymbols;

  for (const SymbolTableEntry &s : symTab->getSymbols()) {
    Symbol *sym = s.sym;
    StringRef name = sym->getName();
    unsigned i = sym->dynsymIndex;
    uint32_t hash = hashSysV(name) % numSymbols;
    chains[i] = buckets[hash];
    write32(ctx, buckets + hash, i);
  }
}

PltSection::PltSection(Ctx &ctx)
    : SyntheticSection(ctx, ".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR,
                       16),
      headerSize(ctx.target->pltHeaderSize) {
  // On AArch64, PLT entries only do loads from the .got.plt section, so the
  // .plt section can be marked with the SHF_AARCH64_PURECODE section flag.
  if (ctx.arg.emachine == EM_AARCH64)
    this->flags |= SHF_AARCH64_PURECODE;

  // On PowerPC, this section contains lazy symbol resolvers.
  if (ctx.arg.emachine == EM_PPC64) {
    name = ".glink";
    addralign = 4;
  }

  // On x86 when IBT is enabled, this section contains the second PLT (lazy
  // symbol resolvers).
  if ((ctx.arg.emachine == EM_386 || ctx.arg.emachine == EM_X86_64) &&
      (ctx.arg.andFeatures & GNU_PROPERTY_X86_FEATURE_1_IBT))
    name = ".plt.sec";

  // The PLT needs to be writable on SPARC as the dynamic linker will
  // modify the instructions in the PLT entries.
  if (ctx.arg.emachine == EM_SPARCV9)
    this->flags |= SHF_WRITE;
}

void PltSection::writeTo(uint8_t *buf) {
  // At beginning of PLT, we have code to call the dynamic
  // linker to resolve dynsyms at runtime. Write such code.
  ctx.target->writePltHeader(buf);
  size_t off = headerSize;

  for (const Symbol *sym : entries) {
    ctx.target->writePlt(buf + off, *sym, getVA() + off);
    off += ctx.target->pltEntrySize;
  }
}

void PltSection::addEntry(Symbol &sym) {
  assert(sym.auxIdx == ctx.symAux.size() - 1);
  ctx.symAux.back().pltIdx = entries.size();
  entries.push_back(&sym);
}

size_t PltSection::getSize() const {
  return headerSize + entries.size() * ctx.target->pltEntrySize;
}

bool PltSection::isNeeded() const {
  // For -z retpolineplt, .iplt needs the .plt header.
  return !entries.empty() || (ctx.arg.zRetpolineplt && ctx.in.iplt->isNeeded());
}

// Used by ARM to add mapping symbols in the PLT section, which aid
// disassembly.
void PltSection::addSymbols() {
  ctx.target->addPltHeaderSymbols(*this);

  size_t off = headerSize;
  for (size_t i = 0; i < entries.size(); ++i) {
    ctx.target->addPltSymbols(*this, off);
    off += ctx.target->pltEntrySize;
  }
}

IpltSection::IpltSection(Ctx &ctx)
    : SyntheticSection(ctx, ".iplt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR,
                       16) {
  // On AArch64, PLT entries only do loads from the .got.plt section, so the
  // .iplt section can be marked with the SHF_AARCH64_PURECODE section flag.
  if (ctx.arg.emachine == EM_AARCH64)
    this->flags |= SHF_AARCH64_PURECODE;

  if (ctx.arg.emachine == EM_PPC || ctx.arg.emachine == EM_PPC64) {
    name = ".glink";
    addralign = 4;
  }
}

void IpltSection::writeTo(uint8_t *buf) {
  uint32_t off = 0;
  for (const Symbol *sym : entries) {
    ctx.target->writeIplt(buf + off, *sym, getVA() + off);
    off += ctx.target->ipltEntrySize;
  }
}

size_t IpltSection::getSize() const {
  return entries.size() * ctx.target->ipltEntrySize;
}

void IpltSection::addEntry(Symbol &sym) {
  assert(sym.auxIdx == ctx.symAux.size() - 1);
  ctx.symAux.back().pltIdx = entries.size();
  entries.push_back(&sym);
}

// ARM uses mapping symbols to aid disassembly.
void IpltSection::addSymbols() {
  size_t off = 0;
  for (size_t i = 0, e = entries.size(); i != e; ++i) {
    ctx.target->addPltSymbols(*this, off);
    off += ctx.target->pltEntrySize;
  }
}

PPC32GlinkSection::PPC32GlinkSection(Ctx &ctx) : PltSection(ctx) {
  name = ".glink";
  addralign = 4;
}

void PPC32GlinkSection::writeTo(uint8_t *buf) {
  writePPC32GlinkSection(ctx, buf, entries.size());
}

size_t PPC32GlinkSection::getSize() const {
  return headerSize + entries.size() * ctx.target->pltEntrySize + footerSize;
}

// This is an x86-only extra PLT section and used only when a security
// enhancement feature called CET is enabled. In this comment, I'll explain what
// the feature is and why we have two PLT sections if CET is enabled.
//
// So, what does CET do? CET introduces a new restriction to indirect jump
// instructions. CET works this way. Assume that CET is enabled. Then, if you
// execute an indirect jump instruction, the processor verifies that a special
// "landing pad" instruction (which is actually a repurposed NOP instruction and
// now called "endbr32" or "endbr64") is at the jump target. If the jump target
// does not start with that instruction, the processor raises an exception
// instead of continuing executing code.
//
// If CET is enabled, the compiler emits endbr to all locations where indirect
// jumps may jump to.
//
// This mechanism makes it extremely hard to transfer the control to a middle of
// a function that is not supporsed to be a indirect jump target, preventing
// certain types of attacks such as ROP or JOP.
//
// Note that the processors in the market as of 2019 don't actually support the
// feature. Only the spec is available at the moment.
//
// Now, I'll explain why we have this extra PLT section for CET.
//
// Since you can indirectly jump to a PLT entry, we have to make PLT entries
// start with endbr. The problem is there's no extra space for endbr (which is 4
// bytes long), as the PLT entry is only 16 bytes long and all bytes are already
// used.
//
// In order to deal with the issue, we split a PLT entry into two PLT entries.
// Remember that each PLT entry contains code to jump to an address read from
// .got.plt AND code to resolve a dynamic symbol lazily. With the 2-PLT scheme,
// the former code is written to .plt.sec, and the latter code is written to
// .plt.
//
// Lazy symbol resolution in the 2-PLT scheme works in the usual way, except
// that the regular .plt is now called .plt.sec and .plt is repurposed to
// contain only code for lazy symbol resolution.
//
// In other words, this is how the 2-PLT scheme works. Application code is
// supposed to jump to .plt.sec to call an external function. Each .plt.sec
// entry contains code to read an address from a corresponding .got.plt entry
// and jump to that address. Addresses in .got.plt initially point to .plt, so
// when an application calls an external function for the first time, the
// control is transferred to a function that resolves a symbol name from
// external shared object files. That function then rewrites a .got.plt entry
// with a resolved address, so that the subsequent function calls directly jump
// to a desired location from .plt.sec.
//
// There is an open question as to whether the 2-PLT scheme was desirable or
// not. We could have simply extended the PLT entry size to 32-bytes to
// accommodate endbr, and that scheme would have been much simpler than the
// 2-PLT scheme. One reason to split PLT was, by doing that, we could keep hot
// code (.plt.sec) from cold code (.plt). But as far as I know no one proved
// that the optimization actually makes a difference.
//
// That said, the 2-PLT scheme is a part of the ABI, debuggers and other tools
// depend on it, so we implement the ABI.
IBTPltSection::IBTPltSection(Ctx &ctx)
    : SyntheticSection(ctx, ".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR,
                       16) {}

void IBTPltSection::writeTo(uint8_t *buf) {
  ctx.target->writeIBTPlt(buf, ctx.in.plt->getNumEntries());
}

size_t IBTPltSection::getSize() const {
  // 16 is the header size of .plt.
  return 16 + ctx.in.plt->getNumEntries() * ctx.target->pltEntrySize;
}

bool IBTPltSection::isNeeded() const { return ctx.in.plt->getNumEntries() > 0; }

RelroPaddingSection::RelroPaddingSection(Ctx &ctx)
    : SyntheticSection(ctx, ".relro_padding", SHT_NOBITS, SHF_ALLOC | SHF_WRITE,
                       1) {}

PaddingSection::PaddingSection(Ctx &ctx, uint64_t amount, OutputSection *parent)
    : SyntheticSection(ctx, ".padding", SHT_PROGBITS, SHF_ALLOC, 1) {
  size = amount;
  this->parent = parent;
}

void PaddingSection::writeTo(uint8_t *buf) {
  std::array<uint8_t, 4> filler = getParent()->getFiller(ctx);
  uint8_t *end = buf + size;
  for (; buf + 4 <= end; buf += 4)
    memcpy(buf, &filler[0], 4);
  memcpy(buf, &filler[0], end - buf);
}

// The string hash function for .gdb_index.
static uint32_t computeGdbHash(StringRef s) {
  uint32_t h = 0;
  for (uint8_t c : s)
    h = h * 67 + toLower(c) - 113;
  return h;
}

// 4-byte alignment ensures that values in the hash lookup table and the name
// table are aligned.
DebugNamesBaseSection::DebugNamesBaseSection(Ctx &ctx)
    : SyntheticSection(ctx, ".debug_names", SHT_PROGBITS, 0, 4) {}

// Get the size of the .debug_names section header in bytes for DWARF32:
static uint32_t getDebugNamesHeaderSize(uint32_t augmentationStringSize) {
  return /* unit length */ 4 +
         /* version */ 2 +
         /* padding */ 2 +
         /* CU count */ 4 +
         /* TU count */ 4 +
         /* Foreign TU count */ 4 +
         /* Bucket Count */ 4 +
         /* Name Count */ 4 +
         /* Abbrev table size */ 4 +
         /* Augmentation string size */ 4 +
         /* Augmentation string */ augmentationStringSize;
}

static Expected<DebugNamesBaseSection::IndexEntry *>
readEntry(uint64_t &offset, const DWARFDebugNames::NameIndex &ni,
          uint64_t entriesBase, DWARFDataExtractor &namesExtractor,
          const LLDDWARFSection &namesSec) {
  auto ie = makeThreadLocal<DebugNamesBaseSection::IndexEntry>();
  ie->poolOffset = offset;
  Error err = Error::success();
  uint64_t ulebVal = namesExtractor.getULEB128(&offset, &err);
  if (err)
    return createStringError(inconvertibleErrorCode(),
                             "invalid abbrev code: %s",
                             llvm::toString(std::move(err)).c_str());
  if (!isUInt<32>(ulebVal))
    return createStringError(inconvertibleErrorCode(),
                             "abbrev code too large for DWARF32: %" PRIu64,
                             ulebVal);
  ie->abbrevCode = static_cast<uint32_t>(ulebVal);
  auto it = ni.getAbbrevs().find_as(ie->abbrevCode);
  if (it == ni.getAbbrevs().end())
    return createStringError(inconvertibleErrorCode(),
                             "abbrev code not found in abbrev table: %" PRIu32,
                             ie->abbrevCode);

  DebugNamesBaseSection::AttrValue attr, cuAttr = {0, 0};
  for (DWARFDebugNames::AttributeEncoding a : it->Attributes) {
    if (a.Index == dwarf::DW_IDX_parent) {
      if (a.Form == dwarf::DW_FORM_ref4) {
        attr.attrValue = namesExtractor.getU32(&offset, &err);
        attr.attrSize = 4;
        ie->parentOffset = entriesBase + attr.attrValue;
      } else if (a.Form != DW_FORM_flag_present)
        return createStringError(inconvertibleErrorCode(),
                                 "invalid form for DW_IDX_parent");
    } else {
      switch (a.Form) {
      case DW_FORM_data1:
      case DW_FORM_ref1: {
        attr.attrValue = namesExtractor.getU8(&offset, &err);
        attr.attrSize = 1;
        break;
      }
      case DW_FORM_data2:
      case DW_FORM_ref2: {
        attr.attrValue = namesExtractor.getU16(&offset, &err);
        attr.attrSize = 2;
        break;
      }
      case DW_FORM_data4:
      case DW_FORM_ref4: {
        attr.attrValue = namesExtractor.getU32(&offset, &err);
        attr.attrSize = 4;
        break;
      }
      default:
        return createStringError(
            inconvertibleErrorCode(),
            "unrecognized form encoding %d in abbrev table", a.Form);
      }
    }
    if (err)
      return createStringError(inconvertibleErrorCode(),
                               "error while reading attributes: %s",
                               llvm::toString(std::move(err)).c_str());
    if (a.Index == DW_IDX_compile_unit)
      cuAttr = attr;
    else if (a.Form != DW_FORM_flag_present)
      ie->attrValues.push_back(attr);
  }
  // Canonicalize abbrev by placing the CU/TU index at the end.
  ie->attrValues.push_back(cuAttr);
  return ie;
}

void DebugNamesBaseSection::parseDebugNames(
    Ctx &ctx, InputChunk &inputChunk, OutputChunk &chunk,
    DWARFDataExtractor &namesExtractor, DataExtractor &strExtractor,
    function_ref<SmallVector<uint32_t, 0>(
        uint32_t numCus, const DWARFDebugNames::Header &,
        const DWARFDebugNames::DWARFDebugNamesOffsets &)>
        readOffsets) {
  const LLDDWARFSection &namesSec = inputChunk.section;
  DenseMap<uint32_t, IndexEntry *> offsetMap;
  // Number of CUs seen in previous NameIndex sections within current chunk.
  uint32_t numCus = 0;
  for (const DWARFDebugNames::NameIndex &ni : *inputChunk.llvmDebugNames) {
    NameData &nd = inputChunk.nameData.emplace_back();
    nd.hdr = ni.getHeader();
    if (nd.hdr.Format != DwarfFormat::DWARF32) {
      Err(ctx) << namesSec.sec
               << ": found DWARF64, which is currently unsupported";
      return;
    }
    if (nd.hdr.Version != 5) {
      Err(ctx) << namesSec.sec << ": unsupported version: " << nd.hdr.Version;
      return;
    }
    uint32_t dwarfSize = dwarf::getDwarfOffsetByteSize(DwarfFormat::DWARF32);
    DWARFDebugNames::DWARFDebugNamesOffsets locs = ni.getOffsets();
    if (locs.EntriesBase > namesExtractor.getData().size()) {
      Err(ctx) << namesSec.sec << ": entry pool start is beyond end of section";
      return;
    }

    SmallVector<uint32_t, 0> entryOffsets = readOffsets(numCus, nd.hdr, locs);

    // Read the entry pool.
    offsetMap.clear();
    nd.nameEntries.resize(nd.hdr.NameCount);
    for (auto i : seq(nd.hdr.NameCount)) {
      NameEntry &ne = nd.nameEntries[i];
      uint64_t strOffset = locs.StringOffsetsBase + i * dwarfSize;
      ne.stringOffset = strOffset;
      uint64_t strp = namesExtractor.getRelocatedValue(dwarfSize, &strOffset);
      StringRef name = strExtractor.getCStrRef(&strp);
      ne.name = name.data();
      ne.hashValue = caseFoldingDjbHash(name);

      // Read a series of index entries that end with abbreviation code 0.
      uint64_t offset = locs.EntriesBase + entryOffsets[i];
      while (offset < namesSec.Data.size() && namesSec.Data[offset] != 0) {
        // Read & store all entries (for the same string).
        Expected<IndexEntry *> ieOrErr =
            readEntry(offset, ni, locs.EntriesBase, namesExtractor, namesSec);
        if (!ieOrErr) {
          Err(ctx) << namesSec.sec << ": " << ieOrErr.takeError();
          return;
        }
        ne.indexEntries.push_back(std::move(*ieOrErr));
      }
      if (offset >= namesSec.Data.size())
        Err(ctx) << namesSec.sec << ": index entry is out of bounds";

      for (IndexEntry &ie : ne.entries())
        offsetMap[ie.poolOffset] = &ie;
    }

    // Assign parent pointers, which will be used to update DW_IDX_parent index
    // attributes. Note: offsetMap[0] does not exist, so parentOffset == 0 will
    // get parentEntry == null as well.
    for (NameEntry &ne : nd.nameEntries)
      for (IndexEntry &ie : ne.entries())
        ie.parentEntry = offsetMap.lookup(ie.parentOffset);
    numCus += nd.hdr.CompUnitCount;
  }
}

// Compute the form for output DW_IDX_compile_unit attributes, similar to
// DIEInteger::BestForm. The input form (often DW_FORM_data1) may not hold all
// the merged CU indices.
std::pair<uint8_t, dwarf::Form> static getMergedCuCountForm(
    uint32_t compUnitCount) {
  if (compUnitCount > UINT16_MAX)
    return {4, DW_FORM_data4};
  if (compUnitCount > UINT8_MAX)
    return {2, DW_FORM_data2};
  return {1, DW_FORM_data1};
}

void DebugNamesBaseSection::computeHdrAndAbbrevTable(
    MutableArrayRef<InputChunk> inputChunks) {
  TimeTraceScope timeScope("Merge .debug_names", "hdr and abbrev table");
  size_t numCu = 0;
  hdr.Format = DwarfFormat::DWARF32;
  hdr.Version = 5;
  hdr.CompUnitCount = 0;
  hdr.LocalTypeUnitCount = 0;
  hdr.ForeignTypeUnitCount = 0;
  hdr.AugmentationStringSize = 0;

  // Compute CU and TU counts.
  for (auto i : seq(numChunks)) {
    InputChunk &inputChunk = inputChunks[i];
    inputChunk.baseCuIdx = numCu;
    numCu += chunks[i].compUnits.size();
    for (const NameData &nd : inputChunk.nameData) {
      hdr.CompUnitCount += nd.hdr.CompUnitCount;
      // TODO: We don't handle type units yet, so LocalTypeUnitCount &
      // ForeignTypeUnitCount are left as 0.
      if (nd.hdr.LocalTypeUnitCount || nd.hdr.ForeignTypeUnitCount)
        Warn(ctx) << inputChunk.section.sec
                  << ": type units are not implemented";
      // If augmentation strings are not identical, use an empty string.
      if (i == 0) {
        hdr.AugmentationStringSize = nd.hdr.AugmentationStringSize;
        hdr.AugmentationString = nd.hdr.AugmentationString;
      } else if (hdr.AugmentationString != nd.hdr.AugmentationString) {
        // There are conflicting augmentation strings, so it's best for the
        // merged index to not use an augmentation string.
        hdr.AugmentationStringSize = 0;
        hdr.AugmentationString.clear();
      }
    }
  }

  // Create the merged abbrev table, uniquifyinng the input abbrev tables and
  // computing mapping from old (per-cu) abbrev codes to new (merged) abbrev
  // codes.
  FoldingSet<Abbrev> abbrevSet;
  // Determine the form for the DW_IDX_compile_unit attributes in the merged
  // index. The input form may not be big enough for all CU indices.
  dwarf::Form cuAttrForm = getMergedCuCountForm(hdr.CompUnitCount).second;
  for (InputChunk &inputChunk : inputChunks) {
    for (auto [i, ni] : enumerate(*inputChunk.llvmDebugNames)) {
      for (const DWARFDebugNames::Abbrev &oldAbbrev : ni.getAbbrevs()) {
        // Canonicalize abbrev by placing the CU/TU index at the end,
        // similar to 'parseDebugNames'.
        Abbrev abbrev;
        DWARFDebugNames::AttributeEncoding cuAttr(DW_IDX_compile_unit,
                                                  cuAttrForm);
        abbrev.code = oldAbbrev.Code;
        abbrev.tag = oldAbbrev.Tag;
        for (DWARFDebugNames::AttributeEncoding a : oldAbbrev.Attributes) {
          if (a.Index == DW_IDX_compile_unit)
            cuAttr.Index = a.Index;
          else
            abbrev.attributes.push_back({a.Index, a.Form});
        }
        // Put the CU/TU index at the end of the attributes list.
        abbrev.attributes.push_back(cuAttr);

        // Profile the abbrev, get or assign a new code, then record the abbrev
        // code mapping.
        FoldingSetNodeID id;
        abbrev.Profile(id);
        uint32_t newCode;
        void *insertPos;
        if (Abbrev *existing = abbrevSet.FindNodeOrInsertPos(id, insertPos)) {
          // Found it; we've already seen an identical abbreviation.
          newCode = existing->code;
        } else {
          Abbrev *abbrev2 =
              new (abbrevAlloc.Allocate()) Abbrev(std::move(abbrev));
          abbrevSet.InsertNode(abbrev2, insertPos);
          abbrevTable.push_back(abbrev2);
          newCode = abbrevTable.size();
          abbrev2->code = newCode;
        }
        inputChunk.nameData[i].abbrevCodeMap[oldAbbrev.Code] = newCode;
      }
    }
  }

  // Compute the merged abbrev table.
  raw_svector_ostream os(abbrevTableBuf);
  for (Abbrev *abbrev : abbrevTable) {
    encodeULEB128(abbrev->code, os);
    encodeULEB128(abbrev->tag, os);
    for (DWARFDebugNames::AttributeEncoding a : abbrev->attributes) {
      encodeULEB128(a.Index, os);
      encodeULEB128(a.Form, os);
    }
    os.write("\0", 2); // attribute specification end
  }
  os.write(0); // abbrev table end
  hdr.AbbrevTableSize = abbrevTableBuf.size();
}

void DebugNamesBaseSection::Abbrev::Profile(FoldingSetNodeID &id) const {
  id.AddInteger(tag);
  for (const DWARFDebugNames::AttributeEncoding &attr : attributes) {
    id.AddInteger(attr.Index);
    id.AddInteger(attr.Form);
  }
}

std::pair<uint32_t, uint32_t> DebugNamesBaseSection::computeEntryPool(
    MutableArrayRef<InputChunk> inputChunks) {
  TimeTraceScope timeScope("Merge .debug_names", "entry pool");
  // Collect and de-duplicate all the names (preserving all the entries).
  // Speed it up using multithreading, as the number of symbols can be in the
  // order of millions.
  const size_t concurrency =
      bit_floor(std::min<size_t>(ctx.arg.threadCount, numShards));
  const size_t shift = 32 - countr_zero(numShards);
  const uint8_t cuAttrSize = getMergedCuCountForm(hdr.CompUnitCount).first;
  DenseMap<CachedHashStringRef, size_t> maps[numShards];

  parallelFor(0, concurrency, [&](size_t threadId) {
    for (auto i : seq(numChunks)) {
      InputChunk &inputChunk = inputChunks[i];
      for (auto j : seq(inputChunk.nameData.size())) {
        NameData &nd = inputChunk.nameData[j];
        // Deduplicate the NameEntry records (based on the string/name),
        // appending all IndexEntries from duplicate NameEntry records to
        // the single preserved copy.
        for (NameEntry &ne : nd.nameEntries) {
          auto shardId = ne.hashValue >> shift;
          if ((shardId & (concurrency - 1)) != threadId)
            continue;

          ne.chunkIdx = i;
          for (IndexEntry &ie : ne.entries()) {
            // Update the IndexEntry's abbrev code to match the merged
            // abbreviations.
            ie.abbrevCode = nd.abbrevCodeMap[ie.abbrevCode];
            // Update the DW_IDX_compile_unit attribute (the last one after
            // canonicalization) to have correct merged offset value and size.
            auto &back = ie.attrValues.back();
            back.attrValue += inputChunk.baseCuIdx + j;
            back.attrSize = cuAttrSize;
          }

          auto &nameVec = nameVecs[shardId];
          auto [it, inserted] = maps[shardId].try_emplace(
              CachedHashStringRef(ne.name, ne.hashValue), nameVec.size());
          if (inserted)
            nameVec.push_back(std::move(ne));
          else
            nameVec[it->second].indexEntries.append(std::move(ne.indexEntries));
        }
      }
    }
  });

  // Compute entry offsets in parallel. First, compute offsets relative to the
  // current shard.
  uint32_t offsets[numShards];
  parallelFor(0, numShards, [&](size_t shard) {
    uint32_t offset = 0;
    for (NameEntry &ne : nameVecs[shard]) {
      ne.entryOffset = offset;
      for (IndexEntry &ie : ne.entries()) {
        ie.poolOffset = offset;
        offset += getULEB128Size(ie.abbrevCode);
        for (AttrValue value : ie.attrValues)
          offset += value.attrSize;
      }
      ++offset; // index entry sentinel
    }
    offsets[shard] = offset;
  });
  // Then add shard offsets.
  std::partial_sum(offsets, std::end(offsets), offsets);
  parallelFor(1, numShards, [&](size_t shard) {
    uint32_t offset = offsets[shard - 1];
    for (NameEntry &ne : nameVecs[shard]) {
      ne.entryOffset += offset;
      for (IndexEntry &ie : ne.entries())
        ie.poolOffset += offset;
    }
  });

  // Update the DW_IDX_parent entries that refer to real parents (have
  // DW_FORM_ref4).
  parallelFor(0, numShards, [&](size_t shard) {
    for (NameEntry &ne : nameVecs[shard]) {
      for (IndexEntry &ie : ne.entries()) {
        if (!ie.parentEntry)
          continue;
        // Abbrevs are indexed starting at 1; vector starts at 0. (abbrevCode
        // corresponds to position in the merged table vector).
        const Abbrev *abbrev = abbrevTable[ie.abbrevCode - 1];
        for (const auto &[a, v] : zip_equal(abbrev->attributes, ie.attrValues))
          if (a.Index == DW_IDX_parent && a.Form == DW_FORM_ref4)
            v.attrValue = ie.parentEntry->poolOffset;
      }
    }
  });

  // Return (entry pool size, number of entries).
  uint32_t num = 0;
  for (auto &map : maps)
    num += map.size();
  return {offsets[numShards - 1], num};
}

void DebugNamesBaseSection::init(
    function_ref<void(InputFile *, InputChunk &, OutputChunk &)> parseFile) {
  TimeTraceScope timeScope("Merge .debug_names");
  // Collect and remove input .debug_names sections. Save InputSection pointers
  // to relocate string offsets in `writeTo`.
  SetVector<InputFile *> files;
  for (InputSectionBase *s : ctx.inputSections) {
    InputSection *isec = dyn_cast<InputSection>(s);
    if (!isec)
      continue;
    if (!(s->flags & SHF_ALLOC) && s->name == ".debug_names") {
      s->markDead();
      inputSections.push_back(isec);
      files.insert(isec->file);
    }
  }

  // Parse input .debug_names sections and extract InputChunk and OutputChunk
  // data. OutputChunk contains CU information, which will be needed by
  // `writeTo`.
  auto inputChunksPtr = std::make_unique<InputChunk[]>(files.size());
  MutableArrayRef<InputChunk> inputChunks(inputChunksPtr.get(), files.size());
  numChunks = files.size();
  chunks = std::make_unique<OutputChunk[]>(files.size());
  {
    TimeTraceScope timeScope("Merge .debug_names", "parse");
    parallelFor(0, files.size(), [&](size_t i) {
      parseFile(files[i], inputChunks[i], chunks[i]);
    });
  }

  // Compute section header (except unit_length), abbrev table, and entry pool.
  computeHdrAndAbbrevTable(inputChunks);
  uint32_t entryPoolSize;
  std::tie(entryPoolSize, hdr.NameCount) = computeEntryPool(inputChunks);
  hdr.BucketCount = dwarf::getDebugNamesBucketCount(hdr.NameCount);

  // Compute the section size. Subtract 4 to get the unit_length for DWARF32.
  uint32_t hdrSize = getDebugNamesHeaderSize(hdr.AugmentationStringSize);
  size = findDebugNamesOffsets(hdrSize, hdr).EntriesBase + entryPoolSize;
  hdr.UnitLength = size - 4;
}

template <class ELFT>
DebugNamesSection<ELFT>::DebugNamesSection(Ctx &ctx)
    : DebugNamesBaseSection(ctx) {
  init([&](InputFile *f, InputChunk &inputChunk, OutputChunk &chunk) {
    auto *file = cast<ObjFile<ELFT>>(f);
    DWARFContext dwarf(std::make_unique<LLDDwarfObj<ELFT>>(file));
    auto &dobj = static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj());
    chunk.infoSec = dobj.getInfoSection();
    DWARFDataExtractor namesExtractor(dobj, dobj.getNamesSection(),
                                      ELFT::Endianness == endianness::little,
                                      ELFT::Is64Bits ? 8 : 4);
    // .debug_str is needed to get symbol names from string offsets.
    DataExtractor strExtractor(dobj.getStrSection(),
                               ELFT::Endianness == endianness::little,
                               ELFT::Is64Bits ? 8 : 4);
    inputChunk.section = dobj.getNamesSection();

    inputChunk.llvmDebugNames.emplace(namesExtractor, strExtractor);
    if (Error e = inputChunk.llvmDebugNames->extract()) {
      Err(ctx) << dobj.getNamesSection().sec << ": " << std::move(e);
    }
    parseDebugNames(
        ctx, inputChunk, chunk, namesExtractor, strExtractor,
        [&chunk, namesData = dobj.getNamesSection().Data.data()](
            uint32_t numCus, const DWARFDebugNames::Header &hdr,
            const DWARFDebugNames::DWARFDebugNamesOffsets &locs) {
          // Read CU offsets, which are relocated by .debug_info + X
          // relocations. Record the section offset to be relocated by
          // `finalizeContents`.
          chunk.compUnits.resize_for_overwrite(numCus + hdr.CompUnitCount);
          for (auto i : seq(hdr.CompUnitCount))
            chunk.compUnits[numCus + i] = locs.CUsBase + i * 4;

          // Read entry offsets.
          const char *p = namesData + locs.EntryOffsetsBase;
          SmallVector<uint32_t, 0> entryOffsets;
          entryOffsets.resize_for_overwrite(hdr.NameCount);
          for (uint32_t &offset : entryOffsets)
            offset = endian::readNext<uint32_t, ELFT::Endianness, unaligned>(p);
          return entryOffsets;
        });
  });
}

template <class ELFT>
template <class RelTy>
void DebugNamesSection<ELFT>::getNameRelocs(
    const InputFile &file, DenseMap<uint32_t, uint32_t> &relocs,
    Relocs<RelTy> rels) {
  for (const RelTy &rel : rels) {
    Symbol &sym = file.getRelocTargetSym(rel);
    relocs[rel.r_offset] = sym.getVA(ctx, getAddend<ELFT>(rel));
  }
}

template <class ELFT> void DebugNamesSection<ELFT>::finalizeContents() {
  // Get relocations of .debug_names sections.
  auto relocs = std::make_unique<DenseMap<uint32_t, uint32_t>[]>(numChunks);
  parallelFor(0, numChunks, [&](size_t i) {
    InputSection *sec = inputSections[i];
    invokeOnRelocs(*sec, getNameRelocs, *sec->file, relocs.get()[i]);

    // Relocate CU offsets with .debug_info + X relocations.
    OutputChunk &chunk = chunks.get()[i];
    for (auto [j, cuOffset] : enumerate(chunk.compUnits))
      cuOffset = relocs.get()[i].lookup(cuOffset);
  });

  // Relocate string offsets in the name table with .debug_str + X relocations.
  parallelForEach(nameVecs, [&](auto &nameVec) {
    for (NameEntry &ne : nameVec)
      ne.stringOffset = relocs.get()[ne.chunkIdx].lookup(ne.stringOffset);
  });
}

template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
  [[maybe_unused]] const uint8_t *const beginBuf = buf;
  // Write the header.
  endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.UnitLength);
  endian::writeNext<uint16_t, ELFT::Endianness>(buf, hdr.Version);
  buf += 2; // padding
  endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.CompUnitCount);
  endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.LocalTypeUnitCount);
  endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.ForeignTypeUnitCount);
  endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.BucketCount);
  endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.NameCount);
  endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.AbbrevTableSize);
  endian::writeNext<uint32_t, ELFT::Endianness>(buf,
                                                hdr.AugmentationStringSize);
  memcpy(buf, hdr.AugmentationString.c_str(), hdr.AugmentationString.size());
  buf += hdr.AugmentationStringSize;

  // Write the CU list.
  for (auto &chunk : getChunks())
    for (uint32_t cuOffset : chunk.compUnits)
      endian::writeNext<uint32_t, ELFT::Endianness>(buf, cuOffset);

  // TODO: Write the local TU list, then the foreign TU list..

  // Write the hash lookup table.
  SmallVector<SmallVector<NameEntry *, 0>, 0> buckets(hdr.BucketCount);
  // Symbols enter into a bucket whose index is the hash modulo bucket_count.
  for (auto &nameVec : nameVecs)
    for (NameEntry &ne : nameVec)
      buckets[ne.hashValue % hdr.BucketCount].push_back(&ne);

  // Write buckets (accumulated bucket counts).
  uint32_t bucketIdx = 1;
  for (const SmallVector<NameEntry *, 0> &bucket : buckets) {
    if (!bucket.empty())
      endian::write32<ELFT::Endianness>(buf, bucketIdx);
    buf += 4;
    bucketIdx += bucket.size();
  }
  // Write the hashes.
  for (const SmallVector<NameEntry *, 0> &bucket : buckets)
    for (const NameEntry *e : bucket)
      endian::writeNext<uint32_t, ELFT::Endianness>(buf, e->hashValue);

  // Write the name table. The name entries are ordered by bucket_idx and
  // correspond one-to-one with the hash lookup table.
  //
  // First, write the relocated string offsets.
  for (const SmallVector<NameEntry *, 0> &bucket : buckets)
    for (const NameEntry *ne : bucket)
      endian::writeNext<uint32_t, ELFT::Endianness>(buf, ne->stringOffset);

  // Then write the entry offsets.
  for (const SmallVector<NameEntry *, 0> &bucket : buckets)
    for (const NameEntry *ne : bucket)
      endian::writeNext<uint32_t, ELFT::Endianness>(buf, ne->entryOffset);

  // Write the abbrev table.
  buf = llvm::copy(abbrevTableBuf, buf);

  // Write the entry pool. Unlike the name table, the name entries follow the
  // nameVecs order computed by `computeEntryPool`.
  for (auto &nameVec : nameVecs) {
    for (NameEntry &ne : nameVec) {
      // Write all the entries for the string.
      for (const IndexEntry &ie : ne.entries()) {
        buf += encodeULEB128(ie.abbrevCode, buf);
        for (AttrValue value : ie.attrValues) {
          switch (value.attrSize) {
          case 1:
            *buf++ = value.attrValue;
            break;
          case 2:
            endian::writeNext<uint16_t, ELFT::Endianness>(buf, value.attrValue);
            break;
          case 4:
            endian::writeNext<uint32_t, ELFT::Endianness>(buf, value.attrValue);
            break;
          default:
            llvm_unreachable("invalid attrSize");
          }
        }
      }
      ++buf; // index entry sentinel
    }
  }
  assert(uint64_t(buf - beginBuf) == size);
}

GdbIndexSection::GdbIndexSection(Ctx &ctx)
    : SyntheticSection(ctx, ".gdb_index", SHT_PROGBITS, 0, 1) {}

// Returns the desired size of an on-disk hash table for a .gdb_index section.
// There's a tradeoff between size and collision rate. We aim 75% utilization.
size_t GdbIndexSection::computeSymtabSize() const {
  return std::max<size_t>(NextPowerOf2(symbols.size() * 4 / 3), 1024);
}

static SmallVector<GdbIndexSection::CuEntry, 0>
readCuList(DWARFContext &dwarf) {
  SmallVector<GdbIndexSection::CuEntry, 0> ret;
  for (std::unique_ptr<DWARFUnit> &cu : dwarf.compile_units())
    ret.push_back({cu->getOffset(), cu->getLength() + 4});
  return ret;
}

static SmallVector<GdbIndexSection::AddressEntry, 0>
readAddressAreas(Ctx &ctx, DWARFContext &dwarf, InputSection *sec) {
  SmallVector<GdbIndexSection::AddressEntry, 0> ret;

  uint32_t cuIdx = 0;
  for (std::unique_ptr<DWARFUnit> &cu : dwarf.compile_units()) {
    if (Error e = cu->tryExtractDIEsIfNeeded(false)) {
      Warn(ctx) << sec << ": " << std::move(e);
      return {};
    }
    Expected<DWARFAddressRangesVector> ranges = cu->collectAddressRanges();
    if (!ranges) {
      Warn(ctx) << sec << ": " << ranges.takeError();
      return {};
    }

    ArrayRef<InputSectionBase *> sections = sec->file->getSections();
    for (DWARFAddressRange &r : *ranges) {
      if (r.SectionIndex == -1ULL)
        continue;
      // Range list with zero size has no effect.
      InputSectionBase *s = sections[r.SectionIndex];
      if (s && s != &InputSection::discarded && s->isLive())
        if (r.LowPC != r.HighPC)
          ret.push_back({cast<InputSection>(s), r.LowPC, r.HighPC, cuIdx});
    }
    ++cuIdx;
  }

  return ret;
}

template <class ELFT>
static SmallVector<GdbIndexSection::NameAttrEntry, 0>
readPubNamesAndTypes(Ctx &ctx, const LLDDwarfObj<ELFT> &obj,
                     const SmallVectorImpl<GdbIndexSection::CuEntry> &cus) {
  const LLDDWARFSection &pubNames = obj.getGnuPubnamesSection();
  const LLDDWARFSection &pubTypes = obj.getGnuPubtypesSection();

  SmallVector<GdbIndexSection::NameAttrEntry, 0> ret;
  for (const LLDDWARFSection *pub : {&pubNames, &pubTypes}) {
    DWARFDataExtractor data(obj, *pub, ELFT::Endianness == endianness::little,
                            ELFT::Is64Bits ? 8 : 4);
    DWARFDebugPubTable table;
    table.extract(data, /*GnuStyle=*/true, [&](Error e) {
      Warn(ctx) << pub->sec << ": " << std::move(e);
    });
    for (const DWARFDebugPubTable::Set &set : table.getData()) {
      // The value written into the constant pool is kind << 24 | cuIndex. As we
      // don't know how many compilation units precede this object to compute
      // cuIndex, we compute (kind << 24 | cuIndexInThisObject) instead, and add
      // the number of preceding compilation units later.
      uint32_t i = llvm::partition_point(cus,
                                         [&](GdbIndexSection::CuEntry cu) {
                                           return cu.cuOffset < set.Offset;
                                         }) -
                   cus.begin();
      for (const DWARFDebugPubTable::Entry &ent : set.Entries)
        ret.push_back({{ent.Name, computeGdbHash(ent.Name)},
                       (ent.Descriptor.toBits() << 24) | i});
    }
  }
  return ret;
}

// Create a list of symbols from a given list of symbol names and types
// by uniquifying them by name.
static std::pair<SmallVector<GdbIndexSection::GdbSymbol, 0>, size_t>
createSymbols(
    Ctx &ctx,
    ArrayRef<SmallVector<GdbIndexSection::NameAttrEntry, 0>> nameAttrs,
    const SmallVector<GdbIndexSection::GdbChunk, 0> &chunks) {
  using GdbSymbol = GdbIndexSection::GdbSymbol;
  using NameAttrEntry = GdbIndexSection::NameAttrEntry;

  // For each chunk, compute the number of compilation units preceding it.
  uint32_t cuIdx = 0;
  std::unique_ptr<uint32_t[]> cuIdxs(new uint32_t[chunks.size()]);
  for (uint32_t i = 0, e = chunks.size(); i != e; ++i) {
    cuIdxs[i] = cuIdx;
    cuIdx += chunks[i].compilationUnits.size();
  }

  // Collect the compilation unitss for each unique name. Speed it up using
  // multi-threading as the number of symbols can be in the order of millions.
  // Shard GdbSymbols by hash's high bits.
  constexpr size_t numShards = 32;
  const size_t concurrency =
      llvm::bit_floor(std::min<size_t>(ctx.arg.threadCount, numShards));
  const size_t shift = 32 - llvm::countr_zero(numShards);
  auto map =
      std::make_unique<DenseMap<CachedHashStringRef, size_t>[]>(numShards);
  auto symbols = std::make_unique<SmallVector<GdbSymbol, 0>[]>(numShards);
  parallelFor(0, concurrency, [&](size_t threadId) {
    uint32_t i = 0;
    for (ArrayRef<NameAttrEntry> entries : nameAttrs) {
      for (const NameAttrEntry &ent : entries) {
        size_t shardId = ent.name.hash() >> shift;
        if ((shardId & (concurrency - 1)) != threadId)
          continue;

        uint32_t v = ent.cuIndexAndAttrs + cuIdxs[i];
        auto [it, inserted] =
            map[shardId].try_emplace(ent.name, symbols[shardId].size());
        if (inserted)
          symbols[shardId].push_back({ent.name, {v}, 0, 0});
        else
          symbols[shardId][it->second].cuVector.push_back(v);
      }
      ++i;
    }
  });

  size_t numSymbols = 0;
  for (ArrayRef<GdbSymbol> v : ArrayRef(symbols.get(), numShards))
    numSymbols += v.size();

  // The return type is a flattened vector, so we'll copy each vector
  // contents to Ret.
  SmallVector<GdbSymbol, 0> ret;
  ret.reserve(numSymbols);
  for (SmallVector<GdbSymbol, 0> &vec :
       MutableArrayRef(symbols.get(), numShards))
    for (GdbSymbol &sym : vec)
      ret.push_back(std::move(sym));

  // CU vectors and symbol names are adjacent in the output file.
  // We can compute their offsets in the output file now.
  size_t off = 0;
  for (GdbSymbol &sym : ret) {
    sym.cuVectorOff = off;
    off += (sym.cuVector.size() + 1) * 4;
  }
  for (GdbSymbol &sym : ret) {
    sym.nameOff = off;
    off += sym.name.size() + 1;
  }
  // If off overflows, the last symbol's nameOff likely overflows.
  if (!isUInt<32>(off))
    Err(ctx) << "--gdb-index: constant pool size (" << off
             << ") exceeds UINT32_MAX";

  return {ret, off};
}

// Returns a newly-created .gdb_index section.
template <class ELFT>
std::unique_ptr<GdbIndexSection> GdbIndexSection::create(Ctx &ctx) {
  llvm::TimeTraceScope timeScope("Create gdb index");

  // Collect InputFiles with .debug_info. See the comment in
  // LLDDwarfObj<ELFT>::LLDDwarfObj. If we do lightweight parsing in the future,
  // note that isec->data() may uncompress the full content, which should be
  // parallelized.
  SetVector<InputFile *> files;
  for (InputSectionBase *s : ctx.inputSections) {
    InputSection *isec = dyn_cast<InputSection>(s);
    if (!isec)
      continue;
    // .debug_gnu_pub{names,types} are useless in executables.
    // They are present in input object files solely for creating
    // a .gdb_index. So we can remove them from the output.
    if (s->name == ".debug_gnu_pubnames" || s->name == ".debug_gnu_pubtypes")
      s->markDead();
    else if (isec->name == ".debug_info")
      files.insert(isec->file);
  }
  // Drop .rel[a].debug_gnu_pub{names,types} for --emit-relocs.
  llvm::erase_if(ctx.inputSections, [](InputSectionBase *s) {
    if (auto *isec = dyn_cast<InputSection>(s))
      if (InputSectionBase *rel = isec->getRelocatedSection())
        return !rel->isLive();
    return !s->isLive();
  });

  SmallVector<GdbChunk, 0> chunks(files.size());
  SmallVector<SmallVector<NameAttrEntry, 0>, 0> nameAttrs(files.size());

  parallelFor(0, files.size(), [&](size_t i) {
    // To keep memory usage low, we don't want to keep cached DWARFContext, so
    // avoid getDwarf() here.
    ObjFile<ELFT> *file = cast<ObjFile<ELFT>>(files[i]);
    DWARFContext dwarf(std::make_unique<LLDDwarfObj<ELFT>>(file));
    auto &dobj = static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj());

    // If the are multiple compile units .debug_info (very rare ld -r --unique),
    // this only picks the last one. Other address ranges are lost.
    chunks[i].sec = dobj.getInfoSection();
    chunks[i].compilationUnits = readCuList(dwarf);
    chunks[i].addressAreas = readAddressAreas(ctx, dwarf, chunks[i].sec);
    nameAttrs[i] =
        readPubNamesAndTypes<ELFT>(ctx, dobj, chunks[i].compilationUnits);
  });

  auto ret = std::make_unique<GdbIndexSection>(ctx);
  ret->chunks = std::move(chunks);
  std::tie(ret->symbols, ret->size) =
      createSymbols(ctx, nameAttrs, ret->chunks);

  // Count the areas other than the constant pool.
  ret->size += sizeof(GdbIndexHeader) + ret->computeSymtabSize() * 8;
  for (GdbChunk &chunk : ret->chunks)
    ret->size +=
        chunk.compilationUnits.size() * 16 + chunk.addressAreas.size() * 20;

  return ret;
}

void GdbIndexSection::writeTo(uint8_t *buf) {
  // Write the header.
  auto *hdr = reinterpret_cast<GdbIndexHeader *>(buf);
  uint8_t *start = buf;
  hdr->version = 7;
  buf += sizeof(*hdr);

  // Write the CU list.
  hdr->cuListOff = buf - start;
  for (GdbChunk &chunk : chunks) {
    for (CuEntry &cu : chunk.compilationUnits) {
      write64le(buf, chunk.sec->outSecOff + cu.cuOffset);
      write64le(buf + 8, cu.cuLength);
      buf += 16;
    }
  }

  // Write the address area.
  hdr->cuTypesOff = buf - start;
  hdr->addressAreaOff = buf - start;
  uint32_t cuOff = 0;
  for (GdbChunk &chunk : chunks) {
    for (AddressEntry &e : chunk.addressAreas) {
      // In the case of ICF there may be duplicate address range entries.
      const uint64_t baseAddr = e.section->repl->getVA(0);
      write64le(buf, baseAddr + e.lowAddress);
      write64le(buf + 8, baseAddr + e.highAddress);
      write32le(buf + 16, e.cuIndex + cuOff);
      buf += 20;
    }
    cuOff += chunk.compilationUnits.size();
  }

  // Write the on-disk open-addressing hash table containing symbols.
  hdr->symtabOff = buf - start;
  size_t symtabSize = computeSymtabSize();
  uint32_t mask = symtabSize - 1;

  for (GdbSymbol &sym : symbols) {
    uint32_t h = sym.name.hash();
    uint32_t i = h & mask;
    uint32_t step = ((h * 17) & mask) | 1;

    while (read32le(buf + i * 8))
      i = (i + step) & mask;

    write32le(buf + i * 8, sym.nameOff);
    write32le(buf + i * 8 + 4, sym.cuVectorOff);
  }

  buf += symtabSize * 8;

  // Write the string pool.
  hdr->constantPoolOff = buf - start;
  parallelForEach(symbols, [&](GdbSymbol &sym) {
    memcpy(buf + sym.nameOff, sym.name.data(), sym.name.size());
  });

  // Write the CU vectors.
  for (GdbSymbol &sym : symbols) {
    write32le(buf, sym.cuVector.size());
    buf += 4;
    for (uint32_t val : sym.cuVector) {
      write32le(buf, val);
      buf += 4;
    }
  }
}

bool GdbIndexSection::isNeeded() const { return !chunks.empty(); }

VersionDefinitionSection::VersionDefinitionSection(Ctx &ctx)
    : SyntheticSection(ctx, ".gnu.version_d", SHT_GNU_verdef, SHF_ALLOC,
                       sizeof(uint32_t)) {}

StringRef VersionDefinitionSection::getFileDefName() {
  if (!getPartition(ctx).name.empty())
    return getPartition(ctx).name;
  if (!ctx.arg.soName.empty())
    return ctx.arg.soName;
  return ctx.arg.outputFile;
}

void VersionDefinitionSection::finalizeContents() {
  fileDefNameOff = getPartition(ctx).dynStrTab->addString(getFileDefName());
  for (const VersionDefinition &v : namedVersionDefs(ctx))
    verDefNameOffs.push_back(getPartition(ctx).dynStrTab->addString(v.name));

  if (OutputSection *sec = getPartition(ctx).dynStrTab->getParent())
    getParent()->link = sec->sectionIndex;

  // sh_info should be set to the number of definitions. This fact is missed in
  // documentation, but confirmed by binutils community:
  // https://sourceware.org/ml/binutils/2014-11/msg00355.html
  getParent()->info = getVerDefNum(ctx);
}

void VersionDefinitionSection::writeOne(uint8_t *buf, uint32_t index,
                                        StringRef name, size_t nameOff) {
  uint16_t flags = index == 1 ? VER_FLG_BASE : 0;

  // Write a verdef.
  write16(ctx, buf, 1);                  // vd_version
  write16(ctx, buf + 2, flags);          // vd_flags
  write16(ctx, buf + 4, index);          // vd_ndx
  write16(ctx, buf + 6, 1);              // vd_cnt
  write32(ctx, buf + 8, hashSysV(name)); // vd_hash
  write32(ctx, buf + 12, 20);            // vd_aux
  write32(ctx, buf + 16, 28);            // vd_next

  // Write a veraux.
  write32(ctx, buf + 20, nameOff); // vda_name
  write32(ctx, buf + 24, 0);       // vda_next
}

void VersionDefinitionSection::writeTo(uint8_t *buf) {
  writeOne(buf, 1, getFileDefName(), fileDefNameOff);

  auto nameOffIt = verDefNameOffs.begin();
  for (const VersionDefinition &v : namedVersionDefs(ctx)) {
    buf += EntrySize;
    writeOne(buf, v.id, v.name, *nameOffIt++);
  }

  // Need to terminate the last version definition.
  write32(ctx, buf + 16, 0); // vd_next
}

size_t VersionDefinitionSection::getSize() const {
  return EntrySize * getVerDefNum(ctx);
}

// .gnu.version is a table where each entry is 2 byte long.
VersionTableSection::VersionTableSection(Ctx &ctx)
    : SyntheticSection(ctx, ".gnu.version", SHT_GNU_versym, SHF_ALLOC,
                       sizeof(uint16_t)) {
  this->entsize = 2;
}

void VersionTableSection::finalizeContents() {
  if (OutputSection *osec = getPartition(ctx).dynSymTab->getParent())
    getParent()->link = osec->sectionIndex;
}

size_t VersionTableSection::getSize() const {
  return (getPartition(ctx).dynSymTab->getSymbols().size() + 1) * 2;
}

void VersionTableSection::writeTo(uint8_t *buf) {
  buf += 2;
  for (const SymbolTableEntry &s : getPartition(ctx).dynSymTab->getSymbols()) {
    // For an unextracted lazy symbol (undefined weak), it must have been
    // converted to Undefined.
    assert(!s.sym->isLazy());
    // Undefined symbols should use index 0 when unversioned.
    write16(ctx, buf, s.sym->isUndefined() ? 0 : s.sym->versionId);
    buf += 2;
  }
}

bool VersionTableSection::isNeeded() const {
  return isLive() &&
         (getPartition(ctx).verDef || getPartition(ctx).verNeed->isNeeded());
}

void elf::addVerneed(Ctx &ctx, Symbol &ss) {
  auto &file = cast<SharedFile>(*ss.file);
  if (ss.versionId == VER_NDX_GLOBAL)
    return;

  if (file.verneedInfo.empty())
    file.verneedInfo.resize(file.verdefs.size());

  // Select a version identifier for the vernaux data structure, if we haven't
  // already allocated one. The verdef identifiers cover the range
  // [1..getVerDefNum(ctx)]; this causes the vernaux identifiers to start from
  // getVerDefNum(ctx)+1.
  if (file.verneedInfo[ss.versionId].id == 0)
    file.verneedInfo[ss.versionId].id = ++ctx.vernauxNum + getVerDefNum(ctx);
  file.verneedInfo[ss.versionId].weak &= ss.isWeak();

  ss.versionId = file.verneedInfo[ss.versionId].id;
}

template <class ELFT>
VersionNeedSection<ELFT>::VersionNeedSection(Ctx &ctx)
    : SyntheticSection(ctx, ".gnu.version_r", SHT_GNU_verneed, SHF_ALLOC,
                       sizeof(uint32_t)) {}

template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() {
  for (SharedFile *f : ctx.sharedFiles) {
    if (f->verneedInfo.empty())
      continue;
    verneeds.emplace_back();
    Verneed &vn = verneeds.back();
    vn.nameStrTab = getPartition(ctx).dynStrTab->addString(f->soName);
    bool isLibc = ctx.arg.relrGlibc && f->soName.starts_with("libc.so.");
    bool isGlibc2 = false;
    for (unsigned i = 0; i != f->verneedInfo.size(); ++i) {
      if (f->verneedInfo[i].id == 0)
        continue;
      // Each Verdef has one or more Verdaux entries. The first Verdaux gives
      // the version name; subsequent entries (if any) are parent versions
      // (e.g., v2 {} v1;). We only use the first one, as parent versions have
      // no rtld behavior difference in practice.
      auto *verdef =
          reinterpret_cast<const typename ELFT::Verdef *>(f->verdefs[i]);
      StringRef ver(f->getStringTable().data() + verdef->getAux()->vda_name);
      if (isLibc && ver.starts_with("GLIBC_2."))
        isGlibc2 = true;
      vn.vernauxs.push_back({verdef->vd_hash, f->verneedInfo[i],
                             getPartition(ctx).dynStrTab->addString(ver)});
    }
    if (isGlibc2) {
      const char *ver = "GLIBC_ABI_DT_RELR";
      vn.vernauxs.push_back(
          {hashSysV(ver),
           {uint16_t(++ctx.vernauxNum + getVerDefNum(ctx)), false},
           getPartition(ctx).dynStrTab->addString(ver)});
    }
  }

  if (OutputSection *sec = getPartition(ctx).dynStrTab->getParent())
    getParent()->link = sec->sectionIndex;
  getParent()->info = verneeds.size();
}

template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *buf) {
  // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs.
  auto *verneed = reinterpret_cast<Elf_Verneed *>(buf);
  auto *vernaux = reinterpret_cast<Elf_Vernaux *>(verneed + verneeds.size());

  for (auto &vn : verneeds) {
    // Create an Elf_Verneed for this DSO.
    verneed->vn_version = 1;
    verneed->vn_cnt = vn.vernauxs.size();
    verneed->vn_file = vn.nameStrTab;
    verneed->vn_aux =
        reinterpret_cast<char *>(vernaux) - reinterpret_cast<char *>(verneed);
    verneed->vn_next = sizeof(Elf_Verneed);
    ++verneed;

    // Create the Elf_Vernauxs for this Elf_Verneed.
    for (auto &vna : vn.vernauxs) {
      vernaux->vna_hash = vna.hash;
      vernaux->vna_flags = vna.verneedInfo.weak ? VER_FLG_WEAK : 0;
      vernaux->vna_other = vna.verneedInfo.id;
      vernaux->vna_name = vna.nameStrTab;
      vernaux->vna_next = sizeof(Elf_Vernaux);
      ++vernaux;
    }

    vernaux[-1].vna_next = 0;
  }
  verneed[-1].vn_next = 0;
}

template <class ELFT> size_t VersionNeedSection<ELFT>::getSize() const {
  return verneeds.size() * sizeof(Elf_Verneed) +
         ctx.vernauxNum * sizeof(Elf_Vernaux);
}

template <class ELFT> bool VersionNeedSection<ELFT>::isNeeded() const {
  return isLive() && ctx.vernauxNum != 0;
}

void MergeSyntheticSection::addSection(MergeInputSection *ms) {
  ms->parent = this;
  sections.push_back(ms);
  assert(addralign == ms->addralign || !(ms->flags & SHF_STRINGS));
  addralign = std::max(addralign, ms->addralign);
}

MergeTailSection::MergeTailSection(Ctx &ctx, StringRef name, uint32_t type,
                                   uint64_t flags, uint32_t alignment)
    : MergeSyntheticSection(ctx, name, type, flags, alignment),
      builder(StringTableBuilder::RAW, llvm::Align(alignment)) {}

size_t MergeTailSection::getSize() const { return builder.getSize(); }

void MergeTailSection::writeTo(uint8_t *buf) { builder.write(buf); }

void MergeTailSection::finalizeContents() {
  // Add all string pieces to the string table builder to create section
  // contents.
  for (MergeInputSection *sec : sections)
    for (size_t i = 0, e = sec->pieces.size(); i != e; ++i)
      if (sec->pieces[i].live)
        builder.add(sec->getData(i));

  // Fix the string table content. After this, the contents will never change.
  builder.finalize();

  // finalize() fixed tail-optimized strings, so we can now get
  // offsets of strings. Get an offset for each string and save it
  // to a corresponding SectionPiece for easy access.
  for (MergeInputSection *sec : sections)
    for (size_t i = 0, e = sec->pieces.size(); i != e; ++i)
      if (sec->pieces[i].live)
        sec->pieces[i].outputOff = builder.getOffset(sec->getData(i));
}

void MergeNoTailSection::writeTo(uint8_t *buf) {
  parallelFor(0, numShards,
              [&](size_t i) { shards[i].write(buf + shardOffsets[i]); });
}

// This function is very hot (i.e. it can take several seconds to finish)
// because sometimes the number of inputs is in an order of magnitude of
// millions. So, we use multi-threading.
//
// For any strings S and T, we know S is not mergeable with T if S's hash
// value is different from T's. If that's the case, we can safely put S and
// T into different string builders without worrying about merge misses.
// We do it in parallel.
void MergeNoTailSection::finalizeContents() {
  // Initializes string table builders.
  for (size_t i = 0; i < numShards; ++i)
    shards.emplace_back(StringTableBuilder::RAW, llvm::Align(addralign));

  // Concurrency level. Must be a power of 2 to avoid expensive modulo
  // operations in the following tight loop.
  const size_t concurrency =
      llvm::bit_floor(std::min<size_t>(ctx.arg.threadCount, numShards));

  // Add section pieces to the builders.
  parallelFor(0, concurrency, [&](size_t threadId) {
    for (MergeInputSection *sec : sections) {
      for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) {
        if (!sec->pieces[i].live)
          continue;
        size_t shardId = getShardId(sec->pieces[i].hash);
        if ((shardId & (concurrency - 1)) == threadId)
          sec->pieces[i].outputOff = shards[shardId].add(sec->getData(i));
      }
    }
  });

  // Compute an in-section offset for each shard.
  size_t off = 0;
  for (size_t i = 0; i < numShards; ++i) {
    shards[i].finalizeInOrder();
    if (shards[i].getSize() > 0)
      off = alignToPowerOf2(off, addralign);
    shardOffsets[i] = off;
    off += shards[i].getSize();
  }
  size = off;

  // So far, section pieces have offsets from beginning of shards, but
  // we want offsets from beginning of the whole section. Fix them.
  parallelForEach(sections, [&](MergeInputSection *sec) {
    for (SectionPiece &piece : sec->pieces)
      if (piece.live)
        piece.outputOff += shardOffsets[getShardId(piece.hash)];
  });
}

template <class ELFT> void elf::splitSections(Ctx &ctx) {
  llvm::TimeTraceScope timeScope("Split sections");
  // splitIntoPieces needs to be called on each MergeInputSection
  // before calling finalizeContents().
  parallelForEach(ctx.objectFiles, [](ELFFileBase *file) {
    for (InputSectionBase *sec : file->getSections()) {
      if (!sec)
        continue;
      if (auto *s = dyn_cast<MergeInputSection>(sec))
        s->splitIntoPieces();
      else if (auto *eh = dyn_cast<EhInputSection>(sec))
        eh->split<ELFT>();
    }

    // For non-section Defined symbols in merge sections, pre-resolve the piece
    // index to avoid potentially repeated binary search (MarkLive, RelocScan,
    // includeInSymtab). Encode each non-section Defined symbol's value as
    // ((pieceIdx + 1) << mergeValueShift) | intraPieceOffset.
    auto resolve = [](Defined *d) {
      auto *ms = dyn_cast_or_null<MergeInputSection>(d->section);
      if (!ms || d->isSection())
        return;
      SectionPiece &piece = ms->getSectionPiece(d->value);
      uint32_t idx = &piece - ms->pieces.data();
      uint64_t off = d->value - piece.inputOff;
      d->value = ((uint64_t)(idx + 1) << mergeValueShift) | off;
    };
    for (Symbol *sym : file->getLocalSymbols())
      if (auto *d = dyn_cast<Defined>(sym))
        resolve(d);
    for (Symbol *sym : file->getGlobalSymbols())
      if (auto *d = dyn_cast<Defined>(sym); d && d->file == file)
        resolve(d);
  });
}

void elf::combineEhSections(Ctx &ctx) {
  llvm::TimeTraceScope timeScope("Combine EH sections");
  for (EhInputSection *sec : ctx.ehInputSections) {
    EhFrameSection &eh = *sec->getPartition(ctx).ehFrame;
    sec->parent = &eh;
    eh.addralign = std::max(eh.addralign, sec->addralign);
    eh.sections.push_back(sec);
    llvm::append_range(eh.dependentSections, sec->dependentSections);
  }

  if (!ctx.mainPart->armExidx)
    return;
  llvm::erase_if(ctx.inputSections, [&](InputSectionBase *s) {
    // Ignore dead sections and the partition end marker (.part.end),
    // whose partition number is out of bounds.
    if (!s->isLive() || s->partition == 255)
      return false;
    Partition &part = s->getPartition(ctx);
    return s->kind() == SectionBase::Regular && part.armExidx &&
           part.armExidx->addSection(cast<InputSection>(s));
  });
}

ARMExidxSyntheticSection::ARMExidxSyntheticSection(Ctx &ctx)
    : SyntheticSection(ctx, ".ARM.exidx", SHT_ARM_EXIDX,
                       SHF_ALLOC | SHF_LINK_ORDER, ctx.arg.wordsize) {}

static InputSection *findExidxSection(InputSection *isec) {
  for (InputSection *d : isec->dependentSections)
    if (d->type == SHT_ARM_EXIDX && d->isLive())
      return d;
  return nullptr;
}

static bool isValidExidxSectionDep(InputSection *isec) {
  return (isec->flags & SHF_ALLOC) && (isec->flags & SHF_EXECINSTR) &&
         isec->getSize() > 0;
}

bool ARMExidxSyntheticSection::addSection(InputSection *isec) {
  if (isec->type == SHT_ARM_EXIDX) {
    if (InputSection *dep = isec->getLinkOrderDep())
      if (isValidExidxSectionDep(dep)) {
        exidxSections.push_back(isec);
        // Every exidxSection is 8 bytes, we need an estimate of
        // size before assignAddresses can be called. Final size
        // will only be known after finalize is called.
        size += 8;
      }
    return true;
  }

  if (isValidExidxSectionDep(isec)) {
    executableSections.push_back(isec);
    return false;
  }

  // FIXME: we do not output a relocation section when --emit-relocs is used
  // as we do not have relocation sections for linker generated table entries
  // and we would have to erase at a late stage relocations from merged entries.
  // Given that exception tables are already position independent and a binary
  // analyzer could derive the relocations we choose to erase the relocations.
  if (ctx.arg.emitRelocs && isec->type == SHT_REL)
    if (InputSectionBase *ex = isec->getRelocatedSection())
      if (isa<InputSection>(ex) && ex->type == SHT_ARM_EXIDX)
        return true;

  return false;
}

// References to .ARM.Extab Sections have bit 31 clear and are not the
// special EXIDX_CANTUNWIND bit-pattern.
static bool isExtabRef(uint32_t unwind) {
  return (unwind & 0x80000000) == 0 && unwind != 0x1;
}

// Return true if the .ARM.exidx section Cur can be merged into the .ARM.exidx
// section Prev, where Cur follows Prev in the table. This can be done if the
// unwinding instructions in Cur are identical to Prev. Linker generated
// EXIDX_CANTUNWIND entries are represented by nullptr as they do not have an
// InputSection.
static bool isDuplicateArmExidxSec(Ctx &ctx, InputSection *prev,
                                   InputSection *cur) {
  // Get the last table Entry from the previous .ARM.exidx section. If Prev is
  // nullptr then it will be a synthesized EXIDX_CANTUNWIND entry.
  uint32_t prevUnwind = 1;
  if (prev)
    prevUnwind =
        read32(ctx, prev->content().data() + prev->content().size() - 4);
  if (isExtabRef(prevUnwind))
    return false;

  // We consider the unwind instructions of an .ARM.exidx table entry
  // a duplicate if the previous unwind instructions if:
  // - Both are the special EXIDX_CANTUNWIND.
  // - Both are the same inline unwind instructions.
  // We do not attempt to follow and check links into .ARM.extab tables as
  // consecutive identical entries are rare and the effort to check that they
  // are identical is high.

  // If Cur is nullptr then this is synthesized EXIDX_CANTUNWIND entry.
  if (cur == nullptr)
    return prevUnwind == 1;

  for (uint32_t offset = 4; offset < (uint32_t)cur->content().size(); offset +=8) {
    uint32_t curUnwind = read32(ctx, cur->content().data() + offset);
    if (isExtabRef(curUnwind) || curUnwind != prevUnwind)
      return false;
  }
  // All table entries in this .ARM.exidx Section can be merged into the
  // previous Section.
  return true;
}

// The .ARM.exidx table must be sorted in ascending order of the address of the
// functions the table describes. std::optionally duplicate adjacent table
// entries can be removed. At the end of the function the executableSections
// must be sorted in ascending order of address, Sentinel is set to the
// InputSection with the highest address and any InputSections that have
// mergeable .ARM.exidx table entries are removed from it.
void ARMExidxSyntheticSection::finalizeContents() {
  // Ensure that any fixed-point iterations after the first see the original set
  // of sections.
  if (!originalExecutableSections.empty())
    executableSections = originalExecutableSections;
  else if (ctx.arg.enableNonContiguousRegions)
    originalExecutableSections = executableSections;

  // The executableSections and exidxSections that we use to derive the final
  // contents of this SyntheticSection are populated before
  // processSectionCommands() and ICF. A /DISCARD/ entry in SECTIONS command or
  // ICF may remove executable InputSections and their dependent .ARM.exidx
  // section that we recorded earlier.
  auto isDiscarded = [](const InputSection *isec) { return !isec->isLive(); };
  llvm::erase_if(exidxSections, isDiscarded);
  // We need to remove discarded InputSections and InputSections without
  // .ARM.exidx sections that if we generated the .ARM.exidx it would be out
  // of range.
  auto isDiscardedOrOutOfRange = [this](InputSection *isec) {
    if (!isec->isLive())
      return true;
    if (findExidxSection(isec))
      return false;
    int64_t off = static_cast<int64_t>(isec->getVA() - getVA());
    return off != llvm::SignExtend64(off, 31);
  };
  llvm::erase_if(executableSections, isDiscardedOrOutOfRange);

  // Sort the executable sections that may or may not have associated
  // .ARM.exidx sections by order of ascending address. This requires the
  // relative positions of InputSections and OutputSections to be known.
  auto compareByFilePosition = [](const InputSection *a,
                                  const InputSection *b) {
    OutputSection *aOut = a->getParent();
    OutputSection *bOut = b->getParent();

    if (aOut != bOut)
      return aOut->addr < bOut->addr;
    return a->outSecOff < b->outSecOff;
  };
  llvm::stable_sort(executableSections, compareByFilePosition);
  sentinel = executableSections.back();
  // std::optionally merge adjacent duplicate entries.
  if (ctx.arg.mergeArmExidx) {
    SmallVector<InputSection *, 0> selectedSections;
    selectedSections.reserve(executableSections.size());
    selectedSections.push_back(executableSections[0]);
    size_t prev = 0;
    for (size_t i = 1; i < executableSections.size(); ++i) {
      InputSection *ex1 = findExidxSection(executableSections[prev]);
      InputSection *ex2 = findExidxSection(executableSections[i]);
      if (!isDuplicateArmExidxSec(ctx, ex1, ex2)) {
        selectedSections.push_back(executableSections[i]);
        prev = i;
      }
    }
    executableSections = std::move(selectedSections);
  }
  // offset is within the SyntheticSection.
  size_t offset = 0;
  size = 0;
  for (InputSection *isec : executableSections) {
    if (InputSection *d = findExidxSection(isec)) {
      d->outSecOff = offset;
      d->parent = getParent();
      offset += d->getSize();
    } else {
      offset += 8;
    }
  }
  // Size includes Sentinel.
  size = offset + 8;
}

InputSection *ARMExidxSyntheticSection::getLinkOrderDep() const {
  return executableSections.front();
}

// To write the .ARM.exidx table from the ExecutableSections we have three cases
// 1.) The InputSection has a .ARM.exidx InputSection in its dependent sections.
//     We write the .ARM.exidx section contents and apply its relocations.
// 2.) The InputSection does not have a dependent .ARM.exidx InputSection. We
//     must write the contents of an EXIDX_CANTUNWIND directly. We use the
//     start of the InputSection as the purpose of the linker generated
//     section is to terminate the address range of the previous entry.
// 3.) A trailing EXIDX_CANTUNWIND sentinel section is required at the end of
//     the table to terminate the address range of the final entry.
void ARMExidxSyntheticSection::writeTo(uint8_t *buf) {

  // A linker generated CANTUNWIND entry is made up of two words:
  // 0x0 with R_ARM_PREL31 relocation to target.
  // 0x1 with EXIDX_CANTUNWIND.
  uint64_t offset = 0;
  for (InputSection *isec : executableSections) {
    assert(isec->getParent() != nullptr);
    if (InputSection *d = findExidxSection(isec)) {
      for (int dataOffset = 0; dataOffset != (int)d->content().size();
           dataOffset += 4)
        write32(ctx, buf + offset + dataOffset,
                read32(ctx, d->content().data() + dataOffset));
      // Recalculate outSecOff as finalizeAddressDependentContent()
      // may have altered syntheticSection outSecOff.
      d->outSecOff = offset + outSecOff;
      ctx.target->relocateAlloc(*d, buf + offset);
      offset += d->getSize();
    } else {
      // A Linker generated CANTUNWIND section.
      write32(ctx, buf + offset + 0, 0x0);
      write32(ctx, buf + offset + 4, 0x1);
      uint64_t s = isec->getVA();
      uint64_t p = getVA() + offset;
      ctx.target->relocateNoSym(buf + offset, R_ARM_PREL31, s - p);
      offset += 8;
    }
  }
  // Write Sentinel CANTUNWIND entry.
  write32(ctx, buf + offset + 0, 0x0);
  write32(ctx, buf + offset + 4, 0x1);
  uint64_t s = sentinel->getVA(sentinel->getSize());
  uint64_t p = getVA() + offset;
  ctx.target->relocateNoSym(buf + offset, R_ARM_PREL31, s - p);
  assert(size == offset + 8);
}

bool ARMExidxSyntheticSection::isNeeded() const {
  return llvm::any_of(exidxSections,
                      [](InputSection *isec) { return isec->isLive(); });
}

ThunkSection::ThunkSection(Ctx &ctx, OutputSection *os, uint64_t off)
    : SyntheticSection(ctx, ".text.thunk", SHT_PROGBITS,
                       SHF_ALLOC | SHF_EXECINSTR,
                       ctx.arg.emachine == EM_PPC64 ? 16 : 4) {
  this->parent = os;
  this->outSecOff = off;
}

size_t ThunkSection::getSize() const {
  if (roundUpSizeForErrata)
    return alignTo(size, 4096);
  return size;
}

void ThunkSection::addThunk(Thunk *t) {
  thunks.push_back(t);
  t->addSymbols(*this);
}

void ThunkSection::writeTo(uint8_t *buf) {
  for (Thunk *t : thunks)
    t->writeTo(buf + t->offset);
}

InputSection *ThunkSection::getTargetInputSection() const {
  if (thunks.empty())
    return nullptr;
  const Thunk *t = thunks.front();
  return t->getTargetInputSection();
}

bool ThunkSection::assignOffsets() {
  uint64_t off = 0;
  bool changed = false;
  for (Thunk *t : thunks) {
    if (t->alignment > addralign) {
      addralign = t->alignment;
      changed = true;
    }
    off = alignToPowerOf2(off, t->alignment);
    t->setOffset(off);
    uint32_t size = t->size();
    t->getThunkTargetSym()->size = size;
    off += size;
  }
  if (off != size)
    changed = true;
  size = off;
  return changed;
}

// If linking position-dependent code then the table will store the addresses
// directly in the binary so the section has type SHT_PROGBITS. If linking
// position-independent code the section has type SHT_NOBITS since it will be
// allocated and filled in by the dynamic linker.
PPC64LongBranchTargetSection::PPC64LongBranchTargetSection(Ctx &ctx)
    : SyntheticSection(ctx, ".branch_lt",
                       ctx.arg.isPic ? SHT_NOBITS : SHT_PROGBITS,
                       SHF_ALLOC | SHF_WRITE, 8) {}

uint64_t PPC64LongBranchTargetSection::getEntryVA(const Symbol *sym,
                                                  int64_t addend) {
  return getVA() + entry_index.find({sym, addend})->second * 8;
}

std::optional<uint32_t>
PPC64LongBranchTargetSection::addEntry(const Symbol *sym, int64_t addend) {
  auto res =
      entry_index.try_emplace(std::make_pair(sym, addend), entries.size());
  if (!res.second)
    return std::nullopt;
  entries.emplace_back(sym, addend);
  return res.first->second;
}

size_t PPC64LongBranchTargetSection::getSize() const {
  return entries.size() * 8;
}

void PPC64LongBranchTargetSection::writeTo(uint8_t *buf) {
  // If linking non-pic we have the final addresses of the targets and they get
  // written to the table directly. For pic the dynamic linker will allocate
  // the section and fill it.
  if (ctx.arg.isPic)
    return;

  for (auto entry : entries) {
    const Symbol *sym = entry.first;
    int64_t addend = entry.second;
    assert(sym->getVA(ctx));
    // Need calls to branch to the local entry-point since a long-branch
    // must be a local-call.
    write64(ctx, buf,
            sym->getVA(ctx, addend) +
                getPPC64GlobalEntryToLocalEntryOffset(ctx, sym->stOther));
    buf += 8;
  }
}

bool PPC64LongBranchTargetSection::isNeeded() const {
  // `removeUnusedSyntheticSections()` is called before thunk allocation which
  // is too early to determine if this section will be empty or not. We need
  // Finalized to keep the section alive until after thunk creation. Finalized
  // only gets set to true once `finalizeSections()` is called after thunk
  // creation. Because of this, if we don't create any long-branch thunks we end
  // up with an empty .branch_lt section in the binary.
  return !finalized || !entries.empty();
}

static uint8_t getAbiVersion(Ctx &ctx) {
  // MIPS non-PIC executable gets ABI version 1.
  if (ctx.arg.emachine == EM_MIPS) {
    if (!ctx.arg.isPic && !ctx.arg.relocatable &&
        (ctx.arg.eflags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
      return 1;
    return 0;
  }

  if (ctx.arg.emachine == EM_AMDGPU && !ctx.objectFiles.empty()) {
    uint8_t ver = ctx.objectFiles[0]->abiVersion;
    for (InputFile *file : ArrayRef(ctx.objectFiles).slice(1))
      if (file->abiVersion != ver)
        Err(ctx) << "incompatible ABI version: " << file;
    return ver;
  }

  return 0;
}

template <typename ELFT>
void elf::writeEhdr(Ctx &ctx, uint8_t *buf, Partition &part) {
  memcpy(buf, "\177ELF", 4);

  auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf);
  eHdr->e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
  eHdr->e_ident[EI_DATA] =
      ELFT::Endianness == endianness::little ? ELFDATA2LSB : ELFDATA2MSB;
  eHdr->e_ident[EI_VERSION] = EV_CURRENT;
  eHdr->e_ident[EI_OSABI] = ctx.arg.osabi;
  eHdr->e_ident[EI_ABIVERSION] = getAbiVersion(ctx);
  eHdr->e_machine = ctx.arg.emachine;
  eHdr->e_version = EV_CURRENT;
  eHdr->e_flags = ctx.arg.eflags;
  eHdr->e_ehsize = sizeof(typename ELFT::Ehdr);
  eHdr->e_phnum = part.phdrs.size();
  eHdr->e_shentsize = sizeof(typename ELFT::Shdr);

  if (!ctx.arg.relocatable) {
    eHdr->e_phoff = sizeof(typename ELFT::Ehdr);
    eHdr->e_phentsize = sizeof(typename ELFT::Phdr);
  }
}

template <typename ELFT> void elf::writePhdrs(uint8_t *buf, Partition &part) {
  // Write the program header table.
  auto *hBuf = reinterpret_cast<typename ELFT::Phdr *>(buf);
  for (std::unique_ptr<PhdrEntry> &p : part.phdrs) {
    hBuf->p_type = p->p_type;
    hBuf->p_flags = p->p_flags;
    hBuf->p_offset = p->p_offset;
    hBuf->p_vaddr = p->p_vaddr;
    hBuf->p_paddr = p->p_paddr;
    hBuf->p_filesz = p->p_filesz;
    hBuf->p_memsz = p->p_memsz;
    hBuf->p_align = p->p_align;
    ++hBuf;
  }
}

template <typename ELFT>
PartitionElfHeaderSection<ELFT>::PartitionElfHeaderSection(Ctx &ctx)
    : SyntheticSection(ctx, "", SHT_LLVM_PART_EHDR, SHF_ALLOC, 1) {}

template <typename ELFT>
size_t PartitionElfHeaderSection<ELFT>::getSize() const {
  return sizeof(typename ELFT::Ehdr);
}

template <typename ELFT>
void PartitionElfHeaderSection<ELFT>::writeTo(uint8_t *buf) {
  writeEhdr<ELFT>(ctx, buf, getPartition(ctx));

  // Loadable partitions are always ET_DYN.
  auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf);
  eHdr->e_type = ET_DYN;
}

template <typename ELFT>
PartitionProgramHeadersSection<ELFT>::PartitionProgramHeadersSection(Ctx &ctx)
    : SyntheticSection(ctx, ".phdrs", SHT_LLVM_PART_PHDR, SHF_ALLOC, 1) {}

template <typename ELFT>
size_t PartitionProgramHeadersSection<ELFT>::getSize() const {
  return sizeof(typename ELFT::Phdr) * getPartition(ctx).phdrs.size();
}

template <typename ELFT>
void PartitionProgramHeadersSection<ELFT>::writeTo(uint8_t *buf) {
  writePhdrs<ELFT>(buf, getPartition(ctx));
}

PartitionIndexSection::PartitionIndexSection(Ctx &ctx)
    : SyntheticSection(ctx, ".rodata", SHT_PROGBITS, SHF_ALLOC, 4) {}

size_t PartitionIndexSection::getSize() const {
  return 12 * (ctx.partitions.size() - 1);
}

void PartitionIndexSection::finalizeContents() {
  for (size_t i = 1; i != ctx.partitions.size(); ++i)
    ctx.partitions[i].nameStrTab =
        ctx.mainPart->dynStrTab->addString(ctx.partitions[i].name);
}

void PartitionIndexSection::writeTo(uint8_t *buf) {
  uint64_t va = getVA();
  for (size_t i = 1; i != ctx.partitions.size(); ++i) {
    write32(ctx, buf,
            ctx.mainPart->dynStrTab->getVA() + ctx.partitions[i].nameStrTab -
                va);
    write32(ctx, buf + 4, ctx.partitions[i].elfHeader->getVA() - (va + 4));

    SyntheticSection *next = i == ctx.partitions.size() - 1
                                 ? ctx.in.partEnd.get()
                                 : ctx.partitions[i + 1].elfHeader.get();
    write32(ctx, buf + 8, next->getVA() - ctx.partitions[i].elfHeader->getVA());

    va += 12;
    buf += 12;
  }
}

static bool needsInterpSection(Ctx &ctx) {
  return !ctx.arg.relocatable && !ctx.arg.shared &&
         !ctx.arg.dynamicLinker.empty() && ctx.script->needsInterpSection();
}

bool elf::hasMemtag(Ctx &ctx) {
  return ctx.arg.emachine == EM_AARCH64 &&
         ctx.arg.memtagMode != ELF::NT_MEMTAG_LEVEL_NONE;
}

// Fully static executables don't support MTE globals at this point in time, as
// we currently rely on:
//   - A dynamic loader to process relocations, and
//   - Dynamic entries.
// This restriction could be removed in future by re-using some of the ideas
// that ifuncs use in fully static executables.
bool elf::canHaveMemtagGlobals(Ctx &ctx) {
  return hasMemtag(ctx) &&
         (ctx.arg.relocatable || ctx.arg.shared || needsInterpSection(ctx));
}

constexpr char kMemtagAndroidNoteName[] = "Android";
void MemtagAndroidNote::writeTo(uint8_t *buf) {
  static_assert(
      sizeof(kMemtagAndroidNoteName) == 8,
      "Android 11 & 12 have an ABI that the note name is 8 bytes long. Keep it "
      "that way for backwards compatibility.");

  write32(ctx, buf, sizeof(kMemtagAndroidNoteName));
  write32(ctx, buf + 4, sizeof(uint32_t));
  write32(ctx, buf + 8, ELF::NT_ANDROID_TYPE_MEMTAG);
  memcpy(buf + 12, kMemtagAndroidNoteName, sizeof(kMemtagAndroidNoteName));
  buf += 12 + alignTo(sizeof(kMemtagAndroidNoteName), 4);

  uint32_t value = 0;
  value |= ctx.arg.memtagMode;
  if (ctx.arg.memtagHeap)
    value |= ELF::NT_MEMTAG_HEAP;
  // Note, MTE stack is an ABI break. Attempting to run an MTE stack-enabled
  // binary on Android 11 or 12 will result in a checkfail in the loader.
  if (ctx.arg.memtagStack)
    value |= ELF::NT_MEMTAG_STACK;
  write32(ctx, buf, value); // note value
}

size_t MemtagAndroidNote::getSize() const {
  return sizeof(llvm::ELF::Elf64_Nhdr) +
         /*namesz=*/alignTo(sizeof(kMemtagAndroidNoteName), 4) +
         /*descsz=*/sizeof(uint32_t);
}

void PackageMetadataNote::writeTo(uint8_t *buf) {
  write32(ctx, buf, 4);
  write32(ctx, buf + 4, ctx.arg.packageMetadata.size() + 1);
  write32(ctx, buf + 8, FDO_PACKAGING_METADATA);
  memcpy(buf + 12, "FDO", 4);
  memcpy(buf + 16, ctx.arg.packageMetadata.data(),
         ctx.arg.packageMetadata.size());
}

size_t PackageMetadataNote::getSize() const {
  return sizeof(llvm::ELF::Elf64_Nhdr) + 4 +
         alignTo(ctx.arg.packageMetadata.size() + 1, 4);
}

// Helper function, return the size of the ULEB128 for 'v', optionally writing
// it to `*(buf + offset)` if `buf` is non-null.
static size_t computeOrWriteULEB128(uint64_t v, uint8_t *buf, size_t offset) {
  if (buf)
    return encodeULEB128(v, buf + offset);
  return getULEB128Size(v);
}

// https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#83encoding-of-sht_aarch64_memtag_globals_dynamic
constexpr uint64_t kMemtagStepSizeBits = 3;
constexpr uint64_t kMemtagGranuleSize = 16;
static size_t
createMemtagGlobalDescriptors(Ctx &ctx,
                              const SmallVector<const Symbol *, 0> &symbols,
                              uint8_t *buf = nullptr) {
  size_t sectionSize = 0;
  uint64_t lastGlobalEnd = 0;

  for (const Symbol *sym : symbols) {
    if (!includeInSymtab(ctx, *sym))
      continue;
    const uint64_t addr = sym->getVA(ctx);
    const uint64_t size = sym->getSize();

    if (addr <= kMemtagGranuleSize && buf != nullptr)
      Err(ctx) << "address of the tagged symbol \"" << sym->getName()
               << "\" falls in the ELF header. This is indicative of a "
                  "compiler/linker bug";
    if (addr % kMemtagGranuleSize != 0)
      Err(ctx) << "address of the tagged symbol \"" << sym->getName()
               << "\" at 0x" << Twine::utohexstr(addr)
               << "\" is not granule (16-byte) aligned";
    if (size == 0)
      Err(ctx) << "size of the tagged symbol \"" << sym->getName()
               << "\" is not allowed to be zero";
    if (size % kMemtagGranuleSize != 0)
      Err(ctx) << "size of the tagged symbol \"" << sym->getName()
               << "\" (size 0x" << Twine::utohexstr(size)
               << ") is not granule (16-byte) aligned";

    const uint64_t sizeToEncode = size / kMemtagGranuleSize;
    const uint64_t stepToEncode = ((addr - lastGlobalEnd) / kMemtagGranuleSize)
                                  << kMemtagStepSizeBits;
    if (sizeToEncode < (1 << kMemtagStepSizeBits)) {
      sectionSize += computeOrWriteULEB128(stepToEncode | sizeToEncode, buf, sectionSize);
    } else {
      sectionSize += computeOrWriteULEB128(stepToEncode, buf, sectionSize);
      sectionSize += computeOrWriteULEB128(sizeToEncode - 1, buf, sectionSize);
    }
    lastGlobalEnd = addr + size;
  }

  return sectionSize;
}

bool MemtagGlobalDescriptors::updateAllocSize(Ctx &ctx) {
  size_t oldSize = getSize();
  llvm::stable_sort(symbols, [&ctx = ctx](const Symbol *s1, const Symbol *s2) {
    return s1->getVA(ctx) < s2->getVA(ctx);
  });
  return oldSize != getSize();
}

void MemtagGlobalDescriptors::writeTo(uint8_t *buf) {
  createMemtagGlobalDescriptors(ctx, symbols, buf);
}

size_t MemtagGlobalDescriptors::getSize() const {
  return createMemtagGlobalDescriptors(ctx, symbols);
}

static OutputSection *findSection(Ctx &ctx, StringRef name) {
  for (SectionCommand *cmd : ctx.script->sectionCommands)
    if (auto *osd = dyn_cast<OutputDesc>(cmd))
      if (osd->osec.name == name)
        return &osd->osec;
  return nullptr;
}

static Defined *addOptionalRegular(Ctx &ctx, StringRef name, SectionBase *sec,
                                   uint64_t val, uint8_t stOther = STV_HIDDEN) {
  Symbol *s = ctx.symtab->find(name);
  if (!s || s->isDefined() || s->isCommon())
    return nullptr;

  s->resolve(ctx, Defined{ctx, ctx.internalFile, StringRef(), STB_GLOBAL,
                          stOther, STT_NOTYPE, val,
                          /*size=*/0, sec});
  s->isUsedInRegularObj = true;
  return cast<Defined>(s);
}

template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
  // Add the .interp section first because it is not a SyntheticSection.
  // The removeUnusedSyntheticSections() function relies on the
  // SyntheticSections coming last.
  if (needsInterpSection(ctx)) {
    for (size_t i = 1; i <= ctx.partitions.size(); ++i) {
      InputSection *sec = createInterpSection(ctx);
      sec->partition = i;
      ctx.inputSections.push_back(sec);
    }
  }

  auto add = [&](SyntheticSection &sec) { ctx.inputSections.push_back(&sec); };

  if (ctx.arg.zSectionHeader)
    ctx.in.shStrTab =
        std::make_unique<StringTableSection>(ctx, ".shstrtab", false);

  ctx.out.programHeaders =
      std::make_unique<OutputSection>(ctx, "", 0, SHF_ALLOC);
  ctx.out.programHeaders->addralign = ctx.arg.wordsize;

  if (ctx.arg.strip != StripPolicy::All) {
    ctx.in.strTab = std::make_unique<StringTableSection>(ctx, ".strtab", false);
    ctx.in.symTab =
        std::make_unique<SymbolTableSection<ELFT>>(ctx, *ctx.in.strTab);
    ctx.in.symTabShndx = std::make_unique<SymtabShndxSection>(ctx);
  }

  ctx.in.bss = std::make_unique<BssSection>(ctx, ".bss", 0, 1);
  add(*ctx.in.bss);

  // If there is a SECTIONS command and a .data.rel.ro section name use name
  // .data.rel.ro.bss so that we match in the .data.rel.ro output section.
  // This makes sure our relro is contiguous.
  bool hasDataRelRo =
      ctx.script->hasSectionsCommand && findSection(ctx, ".data.rel.ro");
  ctx.in.bssRelRo = std::make_unique<BssSection>(
      ctx, hasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1);
  add(*ctx.in.bssRelRo);

  ctx.target->initTargetSpecificSections();

  StringRef relaDynName = ctx.arg.isRela ? ".rela.dyn" : ".rel.dyn";

  const unsigned threadCount = ctx.arg.threadCount;
  for (Partition &part : ctx.partitions) {
    auto add = [&](SyntheticSection &sec) {
      sec.partition = part.getNumber(ctx);
      ctx.inputSections.push_back(&sec);
    };

    if (!part.name.empty()) {
      part.elfHeader = std::make_unique<PartitionElfHeaderSection<ELFT>>(ctx);
      part.elfHeader->name = part.name;
      add(*part.elfHeader);

      part.programHeaders =
          std::make_unique<PartitionProgramHeadersSection<ELFT>>(ctx);
      add(*part.programHeaders);
    }

    if (ctx.arg.buildId != BuildIdKind::None) {
      part.buildId = std::make_unique<BuildIdSection>(ctx);
      add(*part.buildId);
    }

    // dynSymTab is always present to simplify several finalizeSections
    // functions.
    part.dynStrTab = std::make_unique<StringTableSection>(ctx, ".dynstr", true);
    part.dynSymTab =
        std::make_unique<SymbolTableSection<ELFT>>(ctx, *part.dynStrTab);

    if (ctx.arg.relocatable)
      continue;
    part.dynamic = std::make_unique<DynamicSection<ELFT>>(ctx);

    if (hasMemtag(ctx)) {
      if (ctx.arg.memtagAndroidNote) {
        part.memtagAndroidNote = std::make_unique<MemtagAndroidNote>(ctx);
        add(*part.memtagAndroidNote);
      }
      if (canHaveMemtagGlobals(ctx)) {
        part.memtagGlobalDescriptors =
            std::make_unique<MemtagGlobalDescriptors>(ctx);
        add(*part.memtagGlobalDescriptors);
      }
    }

    if (ctx.arg.androidPackDynRelocs)
      part.relaDyn = std::make_unique<AndroidPackedRelocationSection<ELFT>>(
          ctx, relaDynName, threadCount);
    else
      part.relaDyn = std::make_unique<RelocationSection<ELFT>>(
          ctx, relaDynName, /*combreloc=*/true, threadCount);

    if (ctx.hasDynsym) {
      add(*part.dynSymTab);

      part.verSym = std::make_unique<VersionTableSection>(ctx);
      add(*part.verSym);

      if (!namedVersionDefs(ctx).empty()) {
        part.verDef = std::make_unique<VersionDefinitionSection>(ctx);
        add(*part.verDef);
      }

      part.verNeed = std::make_unique<VersionNeedSection<ELFT>>(ctx);
      add(*part.verNeed);

      if (ctx.arg.gnuHash) {
        part.gnuHashTab = std::make_unique<GnuHashTableSection>(ctx);
        add(*part.gnuHashTab);
      }

      if (ctx.arg.sysvHash) {
        part.hashTab = std::make_unique<HashTableSection>(ctx);
        add(*part.hashTab);
      }

      add(*part.dynamic);
      add(*part.dynStrTab);
    }
    add(*part.relaDyn);

    if (ctx.arg.relrPackDynRelocs) {
      part.relrDyn = std::make_unique<RelrSection<ELFT>>(ctx, threadCount);
      add(*part.relrDyn);
      part.relrAuthDyn = std::make_unique<RelrSection<ELFT>>(
          ctx, threadCount, /*isAArch64Auth=*/true);
      add(*part.relrAuthDyn);
    }

    if (ctx.arg.ehFrameHdr) {
      part.ehFrameHdr = std::make_unique<EhFrameHeader>(ctx);
      add(*part.ehFrameHdr);
    }
    part.ehFrame = std::make_unique<EhFrameSection>(ctx);
    add(*part.ehFrame);

    if (ctx.arg.emachine == EM_ARM) {
      // This section replaces all the individual .ARM.exidx InputSections.
      part.armExidx = std::make_unique<ARMExidxSyntheticSection>(ctx);
      add(*part.armExidx);
    }

    if (!ctx.arg.packageMetadata.empty()) {
      part.packageMetadataNote = std::make_unique<PackageMetadataNote>(ctx);
      add(*part.packageMetadataNote);
    }
  }

  if (ctx.partitions.size() != 1) {
    // Create the partition end marker. This needs to be in partition number 255
    // so that it is sorted after all other partitions. It also has other
    // special handling (see createPhdrs() and combineEhSections()).
    ctx.in.partEnd =
        std::make_unique<BssSection>(ctx, ".part.end", ctx.arg.maxPageSize, 1);
    ctx.in.partEnd->partition = 255;
    add(*ctx.in.partEnd);

    ctx.in.partIndex = std::make_unique<PartitionIndexSection>(ctx);
    addOptionalRegular(ctx, "__part_index_begin", ctx.in.partIndex.get(), 0);
    addOptionalRegular(ctx, "__part_index_end", ctx.in.partIndex.get(),
                       ctx.in.partIndex->getSize());
    add(*ctx.in.partIndex);
  }

  // Add .got. MIPS' .got is so different from the other archs,
  // it has its own class.
  if (ctx.arg.emachine == EM_MIPS) {
    ctx.in.mipsGot = std::make_unique<MipsGotSection>(ctx);
    add(*ctx.in.mipsGot);
  } else {
    ctx.in.got = std::make_unique<GotSection>(ctx);
    add(*ctx.in.got);
  }

  ctx.in.gotPlt = std::make_unique<GotPltSection>(ctx);
  add(*ctx.in.gotPlt);
  ctx.in.igotPlt = std::make_unique<IgotPltSection>(ctx);
  add(*ctx.in.igotPlt);
  // Add .relro_padding if DATA_SEGMENT_RELRO_END is used; otherwise, add the
  // section in the absence of PHDRS/SECTIONS commands.
  if (ctx.arg.zRelro &&
      ((ctx.script->phdrsCommands.empty() && !ctx.script->hasSectionsCommand) ||
       ctx.script->seenRelroEnd)) {
    ctx.in.relroPadding = std::make_unique<RelroPaddingSection>(ctx);
    add(*ctx.in.relroPadding);
  }

  // _GLOBAL_OFFSET_TABLE_ is defined relative to either .got.plt or .got. Treat
  // it as a relocation and ensure the referenced section is created.
  if (ctx.sym.globalOffsetTable && ctx.arg.emachine != EM_MIPS) {
    if (ctx.target->gotBaseSymInGotPlt)
      ctx.in.gotPlt->hasGotPltOffRel = true;
    else
      ctx.in.got->hasGotOffRel = true;
  }

  // We always need to add rel[a].plt to output if it has entries.
  // Even for static linking it can contain R_[*]_IRELATIVE relocations.
  ctx.in.relaPlt = std::make_unique<RelocationSection<ELFT>>(
      ctx, ctx.arg.isRela ? ".rela.plt" : ".rel.plt", /*sort=*/false,
      /*threadCount=*/1);
  add(*ctx.in.relaPlt);

  if (ctx.arg.emachine == EM_PPC)
    ctx.in.plt = std::make_unique<PPC32GlinkSection>(ctx);
  else
    ctx.in.plt = std::make_unique<PltSection>(ctx);
  add(*ctx.in.plt);
  ctx.in.iplt = std::make_unique<IpltSection>(ctx);
  add(*ctx.in.iplt);

  if (ctx.arg.andFeatures || ctx.aarch64PauthAbiCoreInfo) {
    ctx.in.gnuProperty = std::make_unique<GnuPropertySection>(ctx);
    add(*ctx.in.gnuProperty);
  }

  if (ctx.arg.debugNames) {
    ctx.in.debugNames = std::make_unique<DebugNamesSection<ELFT>>(ctx);
    add(*ctx.in.debugNames);
  }

  if (ctx.arg.gdbIndex) {
    ctx.in.gdbIndex = GdbIndexSection::create<ELFT>(ctx);
    add(*ctx.in.gdbIndex);
  }

  // .note.GNU-stack is always added when we are creating a re-linkable
  // object file. Other linkers are using the presence of this marker
  // section to control the executable-ness of the stack area, but that
  // is irrelevant these days. Stack area should always be non-executable
  // by default. So we emit this section unconditionally.
  if (ctx.arg.relocatable) {
    ctx.in.gnuStack = std::make_unique<GnuStackSection>(ctx);
    add(*ctx.in.gnuStack);
  }

  if (ctx.in.symTab)
    add(*ctx.in.symTab);
  if (ctx.in.symTabShndx)
    add(*ctx.in.symTabShndx);
  if (ctx.in.shStrTab)
    add(*ctx.in.shStrTab);
  if (ctx.in.strTab)
    add(*ctx.in.strTab);
}

template void elf::splitSections<ELF32LE>(Ctx &);
template void elf::splitSections<ELF32BE>(Ctx &);
template void elf::splitSections<ELF64LE>(Ctx &);
template void elf::splitSections<ELF64BE>(Ctx &);

template void EhFrameSection::iterateFDEWithLSDA<ELF32LE>(
    function_ref<void(InputSection &)>);
template void EhFrameSection::iterateFDEWithLSDA<ELF32BE>(
    function_ref<void(InputSection &)>);
template void EhFrameSection::iterateFDEWithLSDA<ELF64LE>(
    function_ref<void(InputSection &)>);
template void EhFrameSection::iterateFDEWithLSDA<ELF64BE>(
    function_ref<void(InputSection &)>);

template class elf::SymbolTableSection<ELF32LE>;
template class elf::SymbolTableSection<ELF32BE>;
template class elf::SymbolTableSection<ELF64LE>;
template class elf::SymbolTableSection<ELF64BE>;

template void elf::writeEhdr<ELF32LE>(Ctx &, uint8_t *Buf, Partition &Part);
template void elf::writeEhdr<ELF32BE>(Ctx &, uint8_t *Buf, Partition &Part);
template void elf::writeEhdr<ELF64LE>(Ctx &, uint8_t *Buf, Partition &Part);
template void elf::writeEhdr<ELF64BE>(Ctx &, uint8_t *Buf, Partition &Part);

template void elf::writePhdrs<ELF32LE>(uint8_t *Buf, Partition &Part);
template void elf::writePhdrs<ELF32BE>(uint8_t *Buf, Partition &Part);
template void elf::writePhdrs<ELF64LE>(uint8_t *Buf, Partition &Part);
template void elf::writePhdrs<ELF64BE>(uint8_t *Buf, Partition &Part);

template void elf::createSyntheticSections<ELF32LE>(Ctx &);
template void elf::createSyntheticSections<ELF32BE>(Ctx &);
template void elf::createSyntheticSections<ELF64LE>(Ctx &);
template void elf::createSyntheticSections<ELF64BE>(Ctx &);
