[patch] Merge identical strings

Rafael EspĂ­ndola via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 27 20:07:10 PST 2016


The main reason for coding this right now is that as a side effect we
compute the string table earlier which gives me some flexibility to
experiment with when we output each section.

The other reason is that it avoids the need to have reserve and
addString in sync.

Every string should be hashed once. The addString method returns the
offset and we remember that.

The patch right now always merges strings, but that should be easy to
change. The method addString could just push them to a std::vector if
not optimizing. Do you want me to implement that?

When linking clang on a Opteron this goes from 1.090608063 to
1.135082244 seconds (1.04X slower)

and strtab goes from 5426172 to 5319595 bytes (1.02X smaller).

Linking scylladb goes from 8.104377098 to 8.116767958 (1.0015X slower)
and the strtab goes from 14824893 to 14443221 (1.026X smaller).

Cheers,
Rafael
-------------- next part --------------
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
index fd08dfb..a2bb7b8 100644
--- a/ELF/OutputSections.cpp
+++ b/ELF/OutputSections.cpp
@@ -1,1805 +1,1751 @@
 //===- OutputSections.cpp -------------------------------------------------===//
 //
 //                             The LLVM Linker
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
 #include "OutputSections.h"
 #include "Config.h"
 #include "SymbolTable.h"
 #include "Target.h"
 #include "llvm/Support/Dwarf.h"
 #include "llvm/Support/MathExtras.h"
 #include <map>
 
 using namespace llvm;
 using namespace llvm::object;
 using namespace llvm::support::endian;
 using namespace llvm::ELF;
 
 using namespace lld;
 using namespace lld::elf2;
 
 template <class ELFT>
 OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t Type,
                                            uintX_t Flags)
     : Name(Name) {
   memset(&Header, 0, sizeof(Elf_Shdr));
   Header.sh_type = Type;
   Header.sh_flags = Flags;
 }
 
 template <class ELFT>
 GotPltSection<ELFT>::GotPltSection()
     : OutputSectionBase<ELFT>(".got.plt", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
   this->Header.sh_addralign = sizeof(uintX_t);
 }
 
 template <class ELFT> void GotPltSection<ELFT>::addEntry(SymbolBody *Sym) {
   Sym->GotPltIndex = Target->getGotPltHeaderEntriesNum() + Entries.size();
   Entries.push_back(Sym);
 }
 
 template <class ELFT> bool GotPltSection<ELFT>::empty() const {
   return Entries.empty();
 }
 
 template <class ELFT>
 typename GotPltSection<ELFT>::uintX_t
 GotPltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
   return this->getVA() + B.GotPltIndex * sizeof(uintX_t);
 }
 
 template <class ELFT> void GotPltSection<ELFT>::finalize() {
   this->Header.sh_size =
       (Target->getGotPltHeaderEntriesNum() + Entries.size()) * sizeof(uintX_t);
 }
 
 template <class ELFT> void GotPltSection<ELFT>::writeTo(uint8_t *Buf) {
   Target->writeGotPltHeaderEntries(Buf);
   Buf += Target->getGotPltHeaderEntriesNum() * sizeof(uintX_t);
   for (const SymbolBody *B : Entries) {
     Target->writeGotPltEntry(Buf, Out<ELFT>::Plt->getEntryAddr(*B));
     Buf += sizeof(uintX_t);
   }
 }
 
 template <class ELFT>
 GotSection<ELFT>::GotSection()
     : OutputSectionBase<ELFT>(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
   if (Config->EMachine == EM_MIPS)
     this->Header.sh_flags |= SHF_MIPS_GPREL;
   this->Header.sh_addralign = sizeof(uintX_t);
 }
 
 template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody *Sym) {
   Sym->GotIndex = Entries.size();
   Entries.push_back(Sym);
 }
 
 template <class ELFT> void GotSection<ELFT>::addMipsLocalEntry() {
   ++MipsLocalEntries;
 }
 
 template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody *Sym) {
   if (Sym->hasGlobalDynIndex())
     return false;
   Sym->GlobalDynIndex = Target->getGotHeaderEntriesNum() + Entries.size();
   // Global Dynamic TLS entries take two GOT slots.
   Entries.push_back(Sym);
   Entries.push_back(nullptr);
   return true;
 }
 
 template <class ELFT> bool GotSection<ELFT>::addCurrentModuleTlsIndex() {
   if (LocalTlsIndexOff != uint32_t(-1))
     return false;
   Entries.push_back(nullptr);
   Entries.push_back(nullptr);
   LocalTlsIndexOff = (Entries.size() - 2) * sizeof(uintX_t);
   return true;
 }
 
 template <class ELFT>
 typename GotSection<ELFT>::uintX_t
 GotSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
   return this->getVA() +
          (Target->getGotHeaderEntriesNum() + MipsLocalEntries + B.GotIndex) *
              sizeof(uintX_t);
 }
 
 template <class ELFT>
 typename GotSection<ELFT>::uintX_t
 GotSection<ELFT>::getMipsLocalFullAddr(const SymbolBody &B) {
   return getMipsLocalEntryAddr(getSymVA<ELFT>(B));
 }
 
 template <class ELFT>
 typename GotSection<ELFT>::uintX_t
 GotSection<ELFT>::getMipsLocalPageAddr(uintX_t EntryValue) {
   // Initialize the entry by the %hi(EntryValue) expression
   // but without right-shifting.
   return getMipsLocalEntryAddr((EntryValue + 0x8000) & ~0xffff);
 }
 
 template <class ELFT>
 typename GotSection<ELFT>::uintX_t
 GotSection<ELFT>::getMipsLocalEntryAddr(uintX_t EntryValue) {
   size_t NewIndex = Target->getGotHeaderEntriesNum() + MipsLocalGotPos.size();
   auto P = MipsLocalGotPos.insert(std::make_pair(EntryValue, NewIndex));
   assert(!P.second || MipsLocalGotPos.size() <= MipsLocalEntries);
   return this->getVA() + P.first->second * sizeof(uintX_t);
 }
 
 template <class ELFT>
 typename GotSection<ELFT>::uintX_t
 GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const {
   return this->getVA() + B.GlobalDynIndex * sizeof(uintX_t);
 }
 
 template <class ELFT>
 const SymbolBody *GotSection<ELFT>::getMipsFirstGlobalEntry() const {
   return Entries.empty() ? nullptr : Entries.front();
 }
 
 template <class ELFT>
 unsigned GotSection<ELFT>::getMipsLocalEntriesNum() const {
   return Target->getGotHeaderEntriesNum() + MipsLocalEntries;
 }
 
 template <class ELFT> void GotSection<ELFT>::finalize() {
   this->Header.sh_size =
       (Target->getGotHeaderEntriesNum() + MipsLocalEntries + Entries.size()) *
       sizeof(uintX_t);
 }
 
 template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
   Target->writeGotHeaderEntries(Buf);
   for (const auto &L : MipsLocalGotPos) {
     uint8_t *Entry = Buf + L.second * sizeof(uintX_t);
     write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, L.first);
   }
   Buf += Target->getGotHeaderEntriesNum() * sizeof(uintX_t);
   Buf += MipsLocalEntries * sizeof(uintX_t);
   for (const SymbolBody *B : Entries) {
     uint8_t *Entry = Buf;
     Buf += sizeof(uintX_t);
     if (!B)
       continue;
     // MIPS has special rules to fill up GOT entries.
     // 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
     // As the first approach, we can just store addresses for all symbols.
     if (Config->EMachine != EM_MIPS && canBePreempted(B, false))
       continue; // The dynamic linker will take care of it.
     uintX_t VA = getSymVA<ELFT>(*B);
     write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA);
   }
 }
 
 template <class ELFT>
 PltSection<ELFT>::PltSection()
     : OutputSectionBase<ELFT>(".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR) {
   this->Header.sh_addralign = 16;
 }
 
 template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) {
   size_t Off = 0;
   bool LazyReloc = Target->supportsLazyRelocations();
   if (LazyReloc) {
     // First write PLT[0] entry which is special.
     Target->writePltZeroEntry(Buf, Out<ELFT>::GotPlt->getVA(), this->getVA());
     Off += Target->getPltZeroEntrySize();
   }
   for (auto &I : Entries) {
     const SymbolBody *E = I.first;
     unsigned RelOff = I.second;
     uint64_t GotVA =
         LazyReloc ? Out<ELFT>::GotPlt->getVA() : Out<ELFT>::Got->getVA();
     uint64_t GotE = LazyReloc ? Out<ELFT>::GotPlt->getEntryAddr(*E)
                               : Out<ELFT>::Got->getEntryAddr(*E);
     uint64_t Plt = this->getVA() + Off;
     Target->writePltEntry(Buf + Off, GotVA, GotE, Plt, E->PltIndex, RelOff);
     Off += Target->getPltEntrySize();
   }
 }
 
 template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody *Sym) {
   Sym->PltIndex = Entries.size();
   unsigned RelOff = Target->supportsLazyRelocations()
                         ? Out<ELFT>::RelaPlt->getRelocOffset()
                         : Out<ELFT>::RelaDyn->getRelocOffset();
   Entries.push_back(std::make_pair(Sym, RelOff));
 }
 
 template <class ELFT>
 typename PltSection<ELFT>::uintX_t
 PltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
   return this->getVA() + Target->getPltZeroEntrySize() +
          B.PltIndex * Target->getPltEntrySize();
 }
 
 template <class ELFT> void PltSection<ELFT>::finalize() {
   this->Header.sh_size = Target->getPltZeroEntrySize() +
                          Entries.size() * Target->getPltEntrySize();
 }
 
 template <class ELFT>
 RelocationSection<ELFT>::RelocationSection(StringRef Name, bool IsRela)
     : OutputSectionBase<ELFT>(Name, IsRela ? SHT_RELA : SHT_REL, SHF_ALLOC),
       IsRela(IsRela) {
   this->Header.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
   this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
 }
 
 // Applies corresponding symbol and type for dynamic tls relocation.
 // Returns true if relocation was handled.
 template <class ELFT>
 bool RelocationSection<ELFT>::applyTlsDynamicReloc(SymbolBody *Body,
                                                    uint32_t Type, Elf_Rel *P,
                                                    Elf_Rel *N) {
   if (Target->isTlsLocalDynamicReloc(Type)) {
     P->setSymbolAndType(0, Target->getTlsModuleIndexReloc(), Config->Mips64EL);
     P->r_offset = Out<ELFT>::Got->getLocalTlsIndexVA();
     return true;
   }
 
   if (!Body || !Target->isTlsGlobalDynamicReloc(Type))
     return false;
 
   if (Target->isTlsOptimized(Type, Body)) {
     P->setSymbolAndType(Body->DynamicSymbolTableIndex,
                         Target->getTlsGotReloc(), Config->Mips64EL);
     P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
     return true;
   }
 
   P->setSymbolAndType(Body->DynamicSymbolTableIndex,
                       Target->getTlsModuleIndexReloc(), Config->Mips64EL);
   P->r_offset = Out<ELFT>::Got->getGlobalDynAddr(*Body);
   N->setSymbolAndType(Body->DynamicSymbolTableIndex,
                       Target->getTlsOffsetReloc(), Config->Mips64EL);
   N->r_offset = Out<ELFT>::Got->getGlobalDynAddr(*Body) + sizeof(uintX_t);
   return true;
 }
 
 template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
   for (const DynamicReloc<ELFT> &Rel : Relocs) {
     auto *P = reinterpret_cast<Elf_Rel *>(Buf);
     Buf += IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
 
     // Skip placeholder for global dynamic TLS relocation pair. It was already
     // handled by the previous relocation.
     if (!Rel.C)
       continue;
 
     InputSectionBase<ELFT> &C = *Rel.C;
     const Elf_Rel &RI = *Rel.RI;
     uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
     const ObjectFile<ELFT> &File = *C.getFile();
     SymbolBody *Body = File.getSymbolBody(SymIndex);
     if (Body)
       Body = Body->repl();
 
     uint32_t Type = RI.getType(Config->Mips64EL);
     if (applyTlsDynamicReloc(Body, Type, P, reinterpret_cast<Elf_Rel *>(Buf)))
       continue;
 
     // Emit a copy relocation.
     auto *SS = dyn_cast_or_null<SharedSymbol<ELFT>>(Body);
     if (SS && SS->NeedsCopy) {
       P->setSymbolAndType(Body->DynamicSymbolTableIndex, Target->getCopyReloc(),
                           Config->Mips64EL);
       P->r_offset = Out<ELFT>::Bss->getVA() + SS->OffsetInBss;
       continue;
     }
 
     bool NeedsGot = Body && Target->relocNeedsGot(Type, *Body);
     bool CBP = canBePreempted(Body, NeedsGot);
     bool LazyReloc = Body && Target->supportsLazyRelocations() &&
                      Target->relocNeedsPlt(Type, *Body);
     bool IsDynRelative = Type == Target->getRelativeReloc();
 
     unsigned Sym = CBP ? Body->DynamicSymbolTableIndex : 0;
     unsigned Reloc;
     if (!CBP && Body && isGnuIFunc<ELFT>(*Body))
       Reloc = Target->getIRelativeReloc();
     else if (!CBP || IsDynRelative)
       Reloc = Target->getRelativeReloc();
     else if (LazyReloc)
       Reloc = Target->getPltReloc();
     else if (NeedsGot)
       Reloc = Body->isTls() ? Target->getTlsGotReloc() : Target->getGotReloc();
     else
       Reloc = Target->getDynReloc(Type);
     P->setSymbolAndType(Sym, Reloc, Config->Mips64EL);
 
     if (LazyReloc)
       P->r_offset = Out<ELFT>::GotPlt->getEntryAddr(*Body);
     else if (NeedsGot)
       P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
     else
       P->r_offset = C.getOffset(RI.r_offset) + C.OutSec->getVA();
 
     uintX_t OrigAddend = 0;
     if (IsRela && !NeedsGot)
       OrigAddend = static_cast<const Elf_Rela &>(RI).r_addend;
 
     uintX_t Addend;
     if (CBP || IsDynRelative)
       Addend = OrigAddend;
     else if (Body)
       Addend = getSymVA<ELFT>(*Body) + OrigAddend;
     else if (IsRela)
       Addend =
           getLocalRelTarget(File, static_cast<const Elf_Rela &>(RI),
                             getAddend<ELFT>(static_cast<const Elf_Rela &>(RI)));
     else
       Addend = getLocalRelTarget(File, RI, 0);
 
     if (IsRela)
       static_cast<Elf_Rela *>(P)->r_addend = Addend;
   }
 }
 
 template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() {
   const unsigned EntrySize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
   return EntrySize * Relocs.size();
 }
 
 template <class ELFT> void RelocationSection<ELFT>::finalize() {
   this->Header.sh_link = Static ? Out<ELFT>::SymTab->SectionIndex
                                 : Out<ELFT>::DynSymTab->SectionIndex;
   this->Header.sh_size = Relocs.size() * this->Header.sh_entsize;
 }
 
 template <class ELFT>
 InterpSection<ELFT>::InterpSection()
     : OutputSectionBase<ELFT>(".interp", SHT_PROGBITS, SHF_ALLOC) {
   this->Header.sh_size = Config->DynamicLinker.size() + 1;
   this->Header.sh_addralign = 1;
 }
 
 template <class ELFT>
 void OutputSectionBase<ELFT>::writeHeaderTo(Elf_Shdr *SHdr) {
   Header.sh_name = Out<ELFT>::ShStrTab->addString(Name);
   *SHdr = Header;
 }
 
 template <class ELFT> void InterpSection<ELFT>::writeTo(uint8_t *Buf) {
   memcpy(Buf, Config->DynamicLinker.data(), Config->DynamicLinker.size());
 }
 
 template <class ELFT>
 HashTableSection<ELFT>::HashTableSection()
     : OutputSectionBase<ELFT>(".hash", SHT_HASH, SHF_ALLOC) {
   this->Header.sh_entsize = sizeof(Elf_Word);
   this->Header.sh_addralign = sizeof(Elf_Word);
 }
 
 static uint32_t hashSysv(StringRef Name) {
   uint32_t H = 0;
   for (char C : Name) {
     H = (H << 4) + C;
     uint32_t G = H & 0xf0000000;
     if (G)
       H ^= G >> 24;
     H &= ~G;
   }
   return H;
 }
 
 template <class ELFT> void HashTableSection<ELFT>::finalize() {
   this->Header.sh_link = Out<ELFT>::DynSymTab->SectionIndex;
 
   unsigned NumEntries = 2;                 // nbucket and nchain.
   NumEntries += Out<ELFT>::DynSymTab->getNumSymbols(); // The chain entries.
 
   // Create as many buckets as there are symbols.
   // FIXME: This is simplistic. We can try to optimize it, but implementing
   // support for SHT_GNU_HASH is probably even more profitable.
   NumEntries += Out<ELFT>::DynSymTab->getNumSymbols();
   this->Header.sh_size = NumEntries * sizeof(Elf_Word);
 }
 
 template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) {
   unsigned NumSymbols = Out<ELFT>::DynSymTab->getNumSymbols();
   auto *P = reinterpret_cast<Elf_Word *>(Buf);
   *P++ = NumSymbols; // nbucket
   *P++ = NumSymbols; // nchain
 
   Elf_Word *Buckets = P;
   Elf_Word *Chains = P + NumSymbols;
 
   for (SymbolBody *Body : Out<ELFT>::DynSymTab->getSymbols()) {
     StringRef Name = Body->getName();
     unsigned I = Body->DynamicSymbolTableIndex;
     uint32_t Hash = hashSysv(Name) % NumSymbols;
     Chains[I] = Buckets[Hash];
     Buckets[Hash] = I;
   }
 }
 
 static uint32_t hashGnu(StringRef Name) {
   uint32_t H = 5381;
   for (uint8_t C : Name)
     H = (H << 5) + H + C;
   return H;
 }
 
 template <class ELFT>
 GnuHashTableSection<ELFT>::GnuHashTableSection()
     : OutputSectionBase<ELFT>(".gnu.hash", SHT_GNU_HASH, SHF_ALLOC) {
   this->Header.sh_entsize = ELFT::Is64Bits ? 0 : 4;
   this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
 }
 
 template <class ELFT>
 unsigned GnuHashTableSection<ELFT>::calcNBuckets(unsigned NumHashed) {
   if (!NumHashed)
     return 0;
 
   // These values are prime numbers which are not greater than 2^(N-1) + 1.
   // In result, for any particular NumHashed we return a prime number
   // which is not greater than NumHashed.
   static const unsigned Primes[] = {
       1,   1,    3,    3,    7,    13,    31,    61,    127,   251,
       509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071};
 
   return Primes[std::min<unsigned>(Log2_32_Ceil(NumHashed),
                                    array_lengthof(Primes) - 1)];
 }
 
 // Bloom filter estimation: at least 8 bits for each hashed symbol.
 // GNU Hash table requirement: it should be a power of 2,
 //   the minimum value is 1, even for an empty table.
 // Expected results for a 32-bit target:
 //   calcMaskWords(0..4)   = 1
 //   calcMaskWords(5..8)   = 2
 //   calcMaskWords(9..16)  = 4
 // For a 64-bit target:
 //   calcMaskWords(0..8)   = 1
 //   calcMaskWords(9..16)  = 2
 //   calcMaskWords(17..32) = 4
 template <class ELFT>
 unsigned GnuHashTableSection<ELFT>::calcMaskWords(unsigned NumHashed) {
   if (!NumHashed)
     return 1;
   return NextPowerOf2((NumHashed - 1) / sizeof(Elf_Off));
 }
 
 template <class ELFT> void GnuHashTableSection<ELFT>::finalize() {
   unsigned NumHashed = HashedSymbols.size();
   NBuckets = calcNBuckets(NumHashed);
   MaskWords = calcMaskWords(NumHashed);
   // Second hash shift estimation: just predefined values.
   Shift2 = ELFT::Is64Bits ? 6 : 5;
 
   this->Header.sh_link = Out<ELFT>::DynSymTab->SectionIndex;
   this->Header.sh_size = sizeof(Elf_Word) * 4            // Header
                          + sizeof(Elf_Off) * MaskWords   // Bloom Filter
                          + sizeof(Elf_Word) * NBuckets   // Hash Buckets
                          + sizeof(Elf_Word) * NumHashed; // Hash Values
 }
 
 template <class ELFT> void GnuHashTableSection<ELFT>::writeTo(uint8_t *Buf) {
   writeHeader(Buf);
   if (HashedSymbols.empty())
     return;
   writeBloomFilter(Buf);
   writeHashTable(Buf);
 }
 
 template <class ELFT>
 void GnuHashTableSection<ELFT>::writeHeader(uint8_t *&Buf) {
   auto *P = reinterpret_cast<Elf_Word *>(Buf);
   *P++ = NBuckets;
   *P++ = Out<ELFT>::DynSymTab->getNumSymbols() - HashedSymbols.size();
   *P++ = MaskWords;
   *P++ = Shift2;
   Buf = reinterpret_cast<uint8_t *>(P);
 }
 
 template <class ELFT>
 void GnuHashTableSection<ELFT>::writeBloomFilter(uint8_t *&Buf) {
   unsigned C = sizeof(Elf_Off) * 8;
 
   auto *Masks = reinterpret_cast<Elf_Off *>(Buf);
   for (const HashedSymbolData &Item : HashedSymbols) {
     size_t Pos = (Item.Hash / C) & (MaskWords - 1);
     uintX_t V = (uintX_t(1) << (Item.Hash % C)) |
                 (uintX_t(1) << ((Item.Hash >> Shift2) % C));
     Masks[Pos] |= V;
   }
   Buf += sizeof(Elf_Off) * MaskWords;
 }
 
 template <class ELFT>
 void GnuHashTableSection<ELFT>::writeHashTable(uint8_t *Buf) {
   Elf_Word *Buckets = reinterpret_cast<Elf_Word *>(Buf);
   Elf_Word *Values = Buckets + NBuckets;
 
   int PrevBucket = -1;
   int I = 0;
   for (const HashedSymbolData &Item : HashedSymbols) {
     int Bucket = Item.Hash % NBuckets;
     assert(PrevBucket <= Bucket);
     if (Bucket != PrevBucket) {
       Buckets[Bucket] = Item.Body->DynamicSymbolTableIndex;
       PrevBucket = Bucket;
       if (I > 0)
         Values[I - 1] |= 1;
     }
     Values[I] = Item.Hash & ~1;
     ++I;
   }
   if (I > 0)
     Values[I - 1] |= 1;
 }
 
 static bool includeInGnuHashTable(SymbolBody *B) {
   // Assume that includeInDynamicSymtab() is already checked.
   return !B->isUndefined();
 }
 
 template <class ELFT>
 void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolBody *> &Symbols) {
   std::vector<SymbolBody *> NotHashed;
   NotHashed.reserve(Symbols.size());
   HashedSymbols.reserve(Symbols.size());
   for (SymbolBody *B : Symbols) {
     if (includeInGnuHashTable(B))
       HashedSymbols.push_back(HashedSymbolData{B, hashGnu(B->getName())});
     else
       NotHashed.push_back(B);
   }
   if (HashedSymbols.empty())
     return;
 
   unsigned NBuckets = calcNBuckets(HashedSymbols.size());
   std::stable_sort(HashedSymbols.begin(), HashedSymbols.end(),
                    [&](const HashedSymbolData &L, const HashedSymbolData &R) {
                      return L.Hash % NBuckets < R.Hash % NBuckets;
                    });
 
   Symbols = std::move(NotHashed);
   for (const HashedSymbolData &Item : HashedSymbols)
     Symbols.push_back(Item.Body);
 }
 
 template <class ELFT>
 DynamicSection<ELFT>::DynamicSection(SymbolTable<ELFT> &SymTab)
     : OutputSectionBase<ELFT>(".dynamic", SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE),
       SymTab(SymTab) {
   Elf_Shdr &Header = this->Header;
   Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
   Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
 
   // .dynamic section is not writable on MIPS.
   // See "Special Section" in Chapter 4 in the following document:
   // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
   if (Config->EMachine == EM_MIPS)
     Header.sh_flags = SHF_ALLOC;
 }
 
 template <class ELFT> void DynamicSection<ELFT>::finalize() {
   if (this->Header.sh_size)
     return; // Already finalized.
 
   Elf_Shdr &Header = this->Header;
   Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
 
-  unsigned NumEntries = 0;
+  // Reserve strings
+  if (!Config->RPath.empty())
+    Out<ELFT>::DynStrTab->reserve(Config->RPath);
+  if (!Config->SoName.empty())
+    Out<ELFT>::DynStrTab->reserve(Config->SoName);
+  for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
+    if (F->isNeeded())
+      Out<ELFT>::DynStrTab->reserve(F->getSoName());
+  Out<ELFT>::DynStrTab->finalize();
+
   if (Out<ELFT>::RelaDyn->hasRelocs()) {
-    ++NumEntries; // DT_RELA / DT_REL
-    ++NumEntries; // DT_RELASZ / DT_RELSZ
-    ++NumEntries; // DT_RELAENT / DT_RELENT
+    bool IsRela = Out<ELFT>::RelaDyn->isRela();
+    Entries.push_back({IsRela ? DT_RELA : DT_REL, Out<ELFT>::RelaDyn});
+    Entries.push_back(
+        {IsRela ? DT_RELASZ : DT_RELSZ, Out<ELFT>::RelaDyn->getSize()});
+    Entries.push_back({IsRela ? DT_RELAENT : DT_RELENT,
+                       uintX_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))});
   }
   if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
-    ++NumEntries; // DT_JMPREL
-    ++NumEntries; // DT_PLTRELSZ
-    ++NumEntries; // DT_PLTGOT / DT_MIPS_PLTGOT
-    ++NumEntries; // DT_PLTREL
+    Entries.push_back({DT_JMPREL, Out<ELFT>::RelaPlt});
+    Entries.push_back({DT_PLTRELSZ, Out<ELFT>::RelaPlt->getSize()});
+    Entries.push_back({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT,
+                       Out<ELFT>::GotPlt});
+    Entries.push_back(
+        {DT_PLTREL, Out<ELFT>::RelaPlt->isRela() ? DT_RELA : DT_REL});
   }
 
-  ++NumEntries; // DT_SYMTAB
-  ++NumEntries; // DT_SYMENT
-  ++NumEntries; // DT_STRTAB
-  ++NumEntries; // DT_STRSZ
+  Entries.push_back({DT_SYMTAB, Out<ELFT>::DynSymTab});
+  Entries.push_back({DT_SYMENT, sizeof(Elf_Sym)});
+  Entries.push_back({DT_STRTAB, Out<ELFT>::DynStrTab});
+  Entries.push_back({DT_STRSZ, Out<ELFT>::DynStrTab->getSize()});
   if (Out<ELFT>::GnuHashTab)
-    ++NumEntries; // DT_GNU_HASH
+    Entries.push_back({DT_GNU_HASH, Out<ELFT>::GnuHashTab});
   if (Out<ELFT>::HashTab)
-    ++NumEntries; // DT_HASH
+    Entries.push_back({DT_HASH, Out<ELFT>::HashTab});
 
-  if (!Config->RPath.empty()) {
-    ++NumEntries; // DT_RUNPATH / DT_RPATH
-    Out<ELFT>::DynStrTab->reserve(Config->RPath);
-  }
-
-  if (!Config->SoName.empty()) {
-    ++NumEntries; // DT_SONAME
-    Out<ELFT>::DynStrTab->reserve(Config->SoName);
-  }
+  if (!Config->RPath.empty())
+    Entries.push_back({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
+                       Out<ELFT>::DynStrTab->addString(Config->RPath)});
 
-  if (PreInitArraySec)
-    NumEntries += 2;
-  if (InitArraySec)
-    NumEntries += 2;
-  if (FiniArraySec)
-    NumEntries += 2;
+  if (!Config->SoName.empty())
+    Entries.push_back(
+        {DT_SONAME, Out<ELFT>::DynStrTab->addString(Config->SoName)});
 
-  for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles()) {
-    if (!F->isNeeded())
-      continue;
-    Out<ELFT>::DynStrTab->reserve(F->getSoName());
-    ++NumEntries;
+  if (PreInitArraySec) {
+    Entries.push_back({DT_PREINIT_ARRAY, PreInitArraySec});
+    Entries.push_back({DT_PREINIT_ARRAYSZ, PreInitArraySec->getSize()});
+  }
+  if (InitArraySec) {
+    Entries.push_back({DT_INIT_ARRAY, InitArraySec});
+    Entries.push_back({DT_INIT_ARRAYSZ, (uintX_t)InitArraySec->getSize()});
+  }
+  if (FiniArraySec) {
+    Entries.push_back({DT_FINI_ARRAY, FiniArraySec});
+    Entries.push_back({DT_FINI_ARRAYSZ, (uintX_t)FiniArraySec->getSize()});
   }
 
+  for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
+    if (F->isNeeded())
+      Entries.push_back(
+          {DT_NEEDED, Out<ELFT>::DynStrTab->addString(F->getSoName())});
+
   if (Symbol *S = SymTab.getSymbols().lookup(Config->Init))
     InitSym = S->Body;
   if (Symbol *S = SymTab.getSymbols().lookup(Config->Fini))
     FiniSym = S->Body;
   if (InitSym)
-    ++NumEntries; // DT_INIT
+    Entries.push_back({DT_INIT, InitSym});
   if (FiniSym)
-    ++NumEntries; // DT_FINI
+    Entries.push_back({DT_FINI, FiniSym});
 
   if (Config->Bsymbolic)
     DtFlags |= DF_SYMBOLIC;
   if (Config->ZNodelete)
     DtFlags1 |= DF_1_NODELETE;
   if (Config->ZNow) {
     DtFlags |= DF_BIND_NOW;
     DtFlags1 |= DF_1_NOW;
   }
   if (Config->ZOrigin) {
     DtFlags |= DF_ORIGIN;
     DtFlags1 |= DF_1_ORIGIN;
   }
 
   if (DtFlags)
-    ++NumEntries; // DT_FLAGS
+    Entries.push_back({DT_FLAGS, DtFlags});
   if (DtFlags1)
-    ++NumEntries; // DT_FLAGS_1
+    Entries.push_back({DT_FLAGS_1, DtFlags1});
 
   if (!Config->Entry.empty())
-    ++NumEntries; // DT_DEBUG
+    Entries.push_back({DT_DEBUG, (uintX_t)0});
 
   if (Config->EMachine == EM_MIPS) {
-    ++NumEntries; // DT_MIPS_RLD_VERSION
-    ++NumEntries; // DT_MIPS_FLAGS
-    ++NumEntries; // DT_MIPS_BASE_ADDRESS
-    ++NumEntries; // DT_MIPS_SYMTABNO
-    ++NumEntries; // DT_MIPS_LOCAL_GOTNO
-    ++NumEntries; // DT_MIPS_GOTSYM;
-    ++NumEntries; // DT_PLTGOT
+    Entries.push_back({DT_MIPS_RLD_VERSION, 1});
+    Entries.push_back({DT_MIPS_FLAGS, RHF_NOTPOT});
+    Entries.push_back({DT_MIPS_BASE_ADDRESS, (uintX_t)Target->getVAStart()});
+    Entries.push_back(
+        {DT_MIPS_SYMTABNO, Out<ELFT>::DynSymTab->getNumSymbols()});
+    Entries.push_back(
+        {DT_MIPS_LOCAL_GOTNO, Out<ELFT>::Got->getMipsLocalEntriesNum()});
+    if (const SymbolBody *B = Out<ELFT>::Got->getMipsFirstGlobalEntry())
+      Entries.push_back({DT_MIPS_GOTSYM, B->DynamicSymbolTableIndex});
+    else
+      Entries.push_back(
+          {DT_MIPS_GOTSYM, Out<ELFT>::DynSymTab->getNumSymbols()});
+    Entries.push_back({DT_PLTGOT, Out<ELFT>::Got});
     if (Out<ELFT>::MipsRldMap)
-      ++NumEntries; // DT_MIPS_RLD_MAP
+      Entries.push_back({DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap});
   }
 
-  ++NumEntries; // DT_NULL
-
-  Header.sh_size = NumEntries * Header.sh_entsize;
+  // +1 for DT_NULL
+  Header.sh_size = (Entries.size() + 1) * Header.sh_entsize;
 }
 
 template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
   auto *P = reinterpret_cast<Elf_Dyn *>(Buf);
 
   auto WritePtr = [&](int32_t Tag, uint64_t Val) {
     P->d_tag = Tag;
     P->d_un.d_ptr = Val;
     ++P;
   };
 
   auto WriteVal = [&](int32_t Tag, uint32_t Val) {
     P->d_tag = Tag;
     P->d_un.d_val = Val;
     ++P;
   };
 
-  if (Out<ELFT>::RelaDyn->hasRelocs()) {
-    bool IsRela = Out<ELFT>::RelaDyn->isRela();
-    WritePtr(IsRela ? DT_RELA : DT_REL, Out<ELFT>::RelaDyn->getVA());
-    WriteVal(IsRela ? DT_RELASZ : DT_RELSZ, Out<ELFT>::RelaDyn->getSize());
-    WriteVal(IsRela ? DT_RELAENT : DT_RELENT,
-             IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel));
-  }
-  if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
-    WritePtr(DT_JMPREL, Out<ELFT>::RelaPlt->getVA());
-    WriteVal(DT_PLTRELSZ, Out<ELFT>::RelaPlt->getSize());
-    // On MIPS, the address of the .got.plt section is stored in
-    // the DT_MIPS_PLTGOT entry because the DT_PLTGOT entry points to
-    // the .got section. See "Dynamic Section" in the following document:
-    // https://sourceware.org/ml/binutils/2008-07/txt00000.txt
-    WritePtr((Config->EMachine == EM_MIPS) ? DT_MIPS_PLTGOT : DT_PLTGOT,
-             Out<ELFT>::GotPlt->getVA());
-    WriteVal(DT_PLTREL, Out<ELFT>::RelaPlt->isRela() ? DT_RELA : DT_REL);
-  }
-
-  WritePtr(DT_SYMTAB, Out<ELFT>::DynSymTab->getVA());
-  WritePtr(DT_SYMENT, sizeof(Elf_Sym));
-  WritePtr(DT_STRTAB, Out<ELFT>::DynStrTab->getVA());
-  WriteVal(DT_STRSZ, Out<ELFT>::DynStrTab->getSize());
-  if (Out<ELFT>::GnuHashTab)
-    WritePtr(DT_GNU_HASH, Out<ELFT>::GnuHashTab->getVA());
-  if (Out<ELFT>::HashTab)
-    WritePtr(DT_HASH, Out<ELFT>::HashTab->getVA());
-
-  // If --enable-new-dtags is set, lld emits DT_RUNPATH
-  // instead of DT_RPATH. The two tags are functionally
-  // equivalent except for the following:
-  // - DT_RUNPATH is searched after LD_LIBRARY_PATH, while
-  //   DT_RPATH is searched before.
-  // - DT_RUNPATH is used only to search for direct
-  //   dependencies of the object it's contained in, while
-  //   DT_RPATH is used for indirect dependencies as well.
-  if (!Config->RPath.empty())
-    WriteVal(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
-             Out<ELFT>::DynStrTab->addString(Config->RPath));
-
-  if (!Config->SoName.empty())
-    WriteVal(DT_SONAME, Out<ELFT>::DynStrTab->addString(Config->SoName));
-
-  auto WriteArray = [&](int32_t T1, int32_t T2,
-                        const OutputSectionBase<ELFT> *Sec) {
-    if (!Sec)
-      return;
-    WritePtr(T1, Sec->getVA());
-    WriteVal(T2, Sec->getSize());
-  };
-  WriteArray(DT_PREINIT_ARRAY, DT_PREINIT_ARRAYSZ, PreInitArraySec);
-  WriteArray(DT_INIT_ARRAY, DT_INIT_ARRAYSZ, InitArraySec);
-  WriteArray(DT_FINI_ARRAY, DT_FINI_ARRAYSZ, FiniArraySec);
-
-  for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
-    if (F->isNeeded())
-      WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->addString(F->getSoName()));
-
-  if (InitSym)
-    WritePtr(DT_INIT, getSymVA<ELFT>(*InitSym));
-  if (FiniSym)
-    WritePtr(DT_FINI, getSymVA<ELFT>(*FiniSym));
-  if (DtFlags)
-    WriteVal(DT_FLAGS, DtFlags);
-  if (DtFlags1)
-    WriteVal(DT_FLAGS_1, DtFlags1);
-  if (!Config->Entry.empty())
-    WriteVal(DT_DEBUG, 0);
-
-  // See "Dynamic Section" in Chapter 5 in the following document
-  // for detailed description:
-  // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
-  if (Config->EMachine == EM_MIPS) {
-    WriteVal(DT_MIPS_RLD_VERSION, 1);
-    WriteVal(DT_MIPS_FLAGS, RHF_NOTPOT);
-    WritePtr(DT_MIPS_BASE_ADDRESS, Target->getVAStart());
-    WriteVal(DT_MIPS_SYMTABNO, Out<ELFT>::DynSymTab->getNumSymbols());
-    WriteVal(DT_MIPS_LOCAL_GOTNO, Out<ELFT>::Got->getMipsLocalEntriesNum());
-    if (const SymbolBody *B = Out<ELFT>::Got->getMipsFirstGlobalEntry())
-      WriteVal(DT_MIPS_GOTSYM, B->DynamicSymbolTableIndex);
-    else
-      WriteVal(DT_MIPS_GOTSYM, Out<ELFT>::DynSymTab->getNumSymbols());
-    WritePtr(DT_PLTGOT, Out<ELFT>::Got->getVA());
-    if (Out<ELFT>::MipsRldMap)
-      WritePtr(DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap->getVA());
+  for (const Entry &E : Entries) {
+    switch (E.Kind) {
+    case Entry::SecAddr:
+      WritePtr(E.Tag, E.OutSec->getVA());
+      break;
+    case Entry::SymAddr:
+      WritePtr(E.Tag, getSymVA<ELFT>(*E.Sym));
+      break;
+    case Entry::PlainInt:
+      WriteVal(E.Tag, E.Val);
+      break;
+    }
   }
-
-  WriteVal(DT_NULL, 0);
 }
 
 template <class ELFT>
 EhFrameHeader<ELFT>::EhFrameHeader()
     : OutputSectionBase<ELFT>(".eh_frame_hdr", llvm::ELF::SHT_PROGBITS,
                               SHF_ALLOC) {
   // It's a 4 bytes of header + pointer to the contents of the .eh_frame section
   // + the number of FDE pointers in the table.
   this->Header.sh_size = 12;
 }
 
 // We have to get PC values of FDEs. They depend on relocations
 // which are target specific, so we run this code after performing
 // all relocations. We read the values from ouput buffer according to the
 // encoding given for FDEs. Return value is an offset to the initial PC value
 // for the FDE.
 template <class ELFT>
 typename EhFrameHeader<ELFT>::uintX_t
 EhFrameHeader<ELFT>::getFdePc(uintX_t EhVA, const FdeData &F) {
   const endianness E = ELFT::TargetEndianness;
   assert((F.Enc & 0xF0) != dwarf::DW_EH_PE_datarel);
 
   uintX_t FdeOff = EhVA + F.Off + 8;
   switch (F.Enc & 0xF) {
   case dwarf::DW_EH_PE_udata2:
   case dwarf::DW_EH_PE_sdata2:
     return FdeOff + read16<E>(F.PCRel);
   case dwarf::DW_EH_PE_udata4:
   case dwarf::DW_EH_PE_sdata4:
     return FdeOff + read32<E>(F.PCRel);
   case dwarf::DW_EH_PE_udata8:
   case dwarf::DW_EH_PE_sdata8:
     return FdeOff + read64<E>(F.PCRel);
   case dwarf::DW_EH_PE_absptr:
     if (sizeof(uintX_t) == 8)
       return FdeOff + read64<E>(F.PCRel);
     return FdeOff + read32<E>(F.PCRel);
   }
   error("unknown FDE size encoding");
 }
 
 template <class ELFT> void EhFrameHeader<ELFT>::writeTo(uint8_t *Buf) {
   const endianness E = ELFT::TargetEndianness;
 
   const uint8_t Header[] = {1, dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4,
                             dwarf::DW_EH_PE_udata4,
                             dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4};
   memcpy(Buf, Header, sizeof(Header));
 
   uintX_t EhVA = Sec->getVA();
   uintX_t VA = this->getVA();
   uintX_t EhOff = EhVA - VA - 4;
   write32<E>(Buf + 4, EhOff);
   write32<E>(Buf + 8, this->FdeList.size());
   Buf += 12;
 
   // InitialPC -> Offset in .eh_frame, sorted by InitialPC.
   std::map<uintX_t, size_t> PcToOffset;
   for (const FdeData &F : FdeList)
     PcToOffset[getFdePc(EhVA, F)] = F.Off;
 
   for (auto &I : PcToOffset) {
     // The first four bytes are an offset to the initial PC value for the FDE.
     write32<E>(Buf, I.first - VA);
     // The last four bytes are an offset to the FDE data itself.
     write32<E>(Buf + 4, EhVA + I.second - VA);
     Buf += 8;
   }
 }
 
 template <class ELFT>
 void EhFrameHeader<ELFT>::assignEhFrame(EHOutputSection<ELFT> *Sec) {
   if (this->Sec && this->Sec != Sec)
     assert("multiple .eh_frame sections not supported for .eh_frame_hdr");
   Live = Config->EhFrameHdr;
   this->Sec = Sec;
 }
 
 template <class ELFT>
 void EhFrameHeader<ELFT>::addFde(uint8_t Enc, size_t Off, uint8_t *PCRel) {
   if (Live && (Enc & 0xF0) == dwarf::DW_EH_PE_datarel)
     error("DW_EH_PE_datarel encoding unsupported for FDEs by .eh_frame_hdr");
   FdeList.push_back(FdeData{Enc, Off, PCRel});
 }
 
 template <class ELFT> void EhFrameHeader<ELFT>::reserveFde() {
   // Each FDE entry is 8 bytes long:
   // The first four bytes are an offset to the initial PC value for the FDE. The
   // last four byte are an offset to the FDE data itself.
   this->Header.sh_size += 8;
 }
 
 template <class ELFT>
 OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type,
                                    uintX_t Flags)
     : OutputSectionBase<ELFT>(Name, Type, Flags) {}
 
 template <class ELFT>
 void OutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
   auto *S = cast<InputSection<ELFT>>(C);
   Sections.push_back(S);
   S->OutSec = this;
   uint32_t Align = S->getAlign();
   if (Align > this->Header.sh_addralign)
     this->Header.sh_addralign = Align;
 
   uintX_t Off = this->Header.sh_size;
   Off = alignTo(Off, Align);
   S->OutSecOff = Off;
   Off += S->getSize();
   this->Header.sh_size = Off;
 }
 
 template <class ELFT>
 typename ELFFile<ELFT>::uintX_t elf2::getSymVA(const SymbolBody &S) {
   switch (S.kind()) {
   case SymbolBody::DefinedSyntheticKind: {
     auto &D = cast<DefinedSynthetic<ELFT>>(S);
     return D.Section.getVA() + D.Value;
   }
   case SymbolBody::DefinedRegularKind: {
     const auto &DR = cast<DefinedRegular<ELFT>>(S);
     InputSectionBase<ELFT> *SC = DR.Section;
     if (!SC)
       return DR.Sym.st_value;
 
     // Symbol offsets for AMDGPU need to be the offset in bytes of the symbol
     // from the beginning of the section.
     if (Config->EMachine == EM_AMDGPU)
       return SC->getOffset(DR.Sym);
     if (DR.Sym.getType() == STT_TLS)
       return SC->OutSec->getVA() + SC->getOffset(DR.Sym) -
              Out<ELFT>::TlsPhdr->p_vaddr;
     return SC->OutSec->getVA() + SC->getOffset(DR.Sym);
   }
   case SymbolBody::DefinedCommonKind:
     return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(S).OffsetInBss;
   case SymbolBody::SharedKind: {
     auto &SS = cast<SharedSymbol<ELFT>>(S);
     if (SS.NeedsCopy)
       return Out<ELFT>::Bss->getVA() + SS.OffsetInBss;
     return 0;
   }
   case SymbolBody::UndefinedElfKind:
   case SymbolBody::UndefinedKind:
     return 0;
   case SymbolBody::LazyKind:
     assert(S.isUsedInRegularObj() && "Lazy symbol reached writer");
     return 0;
   }
   llvm_unreachable("Invalid symbol kind");
 }
 
 // Returns a VA which a relocatin RI refers to. Used only for local symbols.
 // For non-local symbols, use getSymVA instead.
 template <class ELFT, bool IsRela>
 typename ELFFile<ELFT>::uintX_t
 elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
                         const Elf_Rel_Impl<ELFT, IsRela> &RI,
                         typename ELFFile<ELFT>::uintX_t Addend) {
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
 
   // PPC64 has a special relocation representing the TOC base pointer
   // that does not have a corresponding symbol.
   if (Config->EMachine == EM_PPC64 && RI.getType(false) == R_PPC64_TOC)
     return getPPC64TocBase() + Addend;
 
   const Elf_Sym *Sym =
       File.getObj().getRelocationSymbol(&RI, File.getSymbolTable());
 
   if (!Sym)
     error("Unsupported relocation without symbol");
 
   InputSectionBase<ELFT> *Section = File.getSection(*Sym);
 
   if (Sym->getType() == STT_TLS)
     return (Section->OutSec->getVA() + Section->getOffset(*Sym) + Addend) -
            Out<ELFT>::TlsPhdr->p_vaddr;
 
   // According to the ELF spec reference to a local symbol from outside
   // the group are not allowed. Unfortunately .eh_frame breaks that rule
   // and must be treated specially. For now we just replace the symbol with
   // 0.
   if (Section == &InputSection<ELFT>::Discarded || !Section->isLive())
     return Addend;
 
   uintX_t VA = Section->OutSec->getVA();
   if (isa<InputSection<ELFT>>(Section))
     return VA + Section->getOffset(*Sym) + Addend;
 
   uintX_t Offset = Sym->st_value;
   if (Sym->getType() == STT_SECTION) {
     Offset += Addend;
     Addend = 0;
   }
   return VA + Section->getOffset(Offset) + Addend;
 }
 
 // Returns true if a symbol can be replaced at load-time by a symbol
 // with the same name defined in other ELF executable or DSO.
 bool elf2::canBePreempted(const SymbolBody *Body, bool NeedsGot) {
   if (!Body)
     return false;  // Body is a local symbol.
   if (Body->isShared())
     return true;
 
   if (Body->isUndefined()) {
     if (!Body->isWeak())
       return true;
 
     // This is an horrible corner case. Ideally we would like to say that any
     // undefined symbol can be preempted so that the dynamic linker has a
     // chance of finding it at runtime.
     //
     // The problem is that the code sequence used to test for weak undef
     // functions looks like
     // if (func) func()
     // If the code is -fPIC the first reference is a load from the got and
     // everything works.
     // If the code is not -fPIC there is no reasonable way to solve it:
     // * A relocation writing to the text segment will fail (it is ro).
     // * A copy relocation doesn't work for functions.
     // * The trick of using a plt entry as the address would fail here since
     //   the plt entry would have a non zero address.
     // Since we cannot do anything better, we just resolve the symbol to 0 and
     // don't produce a dynamic relocation.
     //
     // As an extra hack, assume that if we are producing a shared library the
     // user knows what he or she is doing and can handle a dynamic relocation.
     return Config->Shared || NeedsGot;
   }
   if (!Config->Shared)
     return false;
   return Body->getVisibility() == STV_DEFAULT;
 }
 
 template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
   for (InputSection<ELFT> *C : Sections)
     C->writeTo(Buf);
 }
 
 template <class ELFT>
 EHOutputSection<ELFT>::EHOutputSection(StringRef Name, uint32_t Type,
                                        uintX_t Flags)
     : OutputSectionBase<ELFT>(Name, Type, Flags) {
   Out<ELFT>::EhFrameHdr->assignEhFrame(this);
 }
 
 template <class ELFT>
 EHRegion<ELFT>::EHRegion(EHInputSection<ELFT> *S, unsigned Index)
     : S(S), Index(Index) {}
 
 template <class ELFT> StringRef EHRegion<ELFT>::data() const {
   ArrayRef<uint8_t> SecData = S->getSectionData();
   ArrayRef<std::pair<uintX_t, uintX_t>> Offsets = S->Offsets;
   size_t Start = Offsets[Index].first;
   size_t End =
       Index == Offsets.size() - 1 ? SecData.size() : Offsets[Index + 1].first;
   return StringRef((const char *)SecData.data() + Start, End - Start);
 }
 
 template <class ELFT>
 Cie<ELFT>::Cie(EHInputSection<ELFT> *S, unsigned Index)
     : EHRegion<ELFT>(S, Index) {}
 
 // Read a byte and advance D by one byte.
 static uint8_t readByte(ArrayRef<uint8_t> &D) {
   if (D.empty())
     error("corrupted or unsupported CIE information");
   uint8_t B = D.front();
   D = D.slice(1);
   return B;
 }
 
 static void skipLeb128(ArrayRef<uint8_t> &D) {
   while (!D.empty()) {
     uint8_t Val = D.front();
     D = D.slice(1);
     if ((Val & 0x80) == 0)
       return;
   }
   error("corrupted or unsupported CIE information");
 }
 
 template <class ELFT> static unsigned getSizeForEncoding(unsigned Enc) {
   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
   switch (Enc & 0x0f) {
   default:
     error("unknown FDE encoding");
   case dwarf::DW_EH_PE_absptr:
   case dwarf::DW_EH_PE_signed:
     return sizeof(uintX_t);
   case dwarf::DW_EH_PE_udata2:
   case dwarf::DW_EH_PE_sdata2:
     return 2;
   case dwarf::DW_EH_PE_udata4:
   case dwarf::DW_EH_PE_sdata4:
     return 4;
   case dwarf::DW_EH_PE_udata8:
   case dwarf::DW_EH_PE_sdata8:
     return 8;
   }
 }
 
 template <class ELFT>
 uint8_t EHOutputSection<ELFT>::getFdeEncoding(ArrayRef<uint8_t> D) {
   auto Check = [](bool C) {
     if (!C)
       error("corrupted or unsupported CIE information");
   };
 
   Check(D.size() >= 8);
   D = D.slice(8);
 
   uint8_t Version = readByte(D);
   if (Version != 1 && Version != 3)
     error("FDE version 1 or 3 expected, but got " + Twine((unsigned)Version));
 
   auto AugEnd = std::find(D.begin() + 1, D.end(), '\0');
   Check(AugEnd != D.end());
   ArrayRef<uint8_t> AugString(D.begin(), AugEnd - D.begin());
   D = D.slice(AugString.size() + 1);
 
   // Code alignment factor should always be 1 for .eh_frame.
   if (readByte(D) != 1)
     error("CIE code alignment must be 1");
   // Skip data alignment factor
   skipLeb128(D);
 
   // Skip the return address register. In CIE version 1 this is a single
   // byte. In CIE version 3 this is an unsigned LEB128.
   if (Version == 1)
     readByte(D);
   else
     skipLeb128(D);
 
   while (!AugString.empty()) {
     switch (readByte(AugString)) {
     case 'z':
       skipLeb128(D);
       break;
     case 'R':
       return readByte(D);
     case 'P': {
       uint8_t Enc = readByte(D);
       if ((Enc & 0xf0) == dwarf::DW_EH_PE_aligned)
         error("DW_EH_PE_aligned encoding for address of a personality routine "
               "handler not supported");
       unsigned EncSize = getSizeForEncoding<ELFT>(Enc);
       Check(D.size() >= EncSize);
       D = D.slice(EncSize);
       break;
     }
     case 'S':
     case 'L':
       // L: Language Specific Data Area (LSDA) encoding
       // S: This CIE represents a stack frame for the invocation of a signal
       //    handler
       break;
     default:
       error("unknown .eh_frame augmentation string value");
     }
   }
   return dwarf::DW_EH_PE_absptr;
 }
 
 template <class ELFT>
 template <bool IsRela>
 void EHOutputSection<ELFT>::addSectionAux(
     EHInputSection<ELFT> *S,
     iterator_range<const Elf_Rel_Impl<ELFT, IsRela> *> Rels) {
   const endianness E = ELFT::TargetEndianness;
 
   S->OutSec = this;
   uint32_t Align = S->getAlign();
   if (Align > this->Header.sh_addralign)
     this->Header.sh_addralign = Align;
 
   Sections.push_back(S);
 
   ArrayRef<uint8_t> SecData = S->getSectionData();
   ArrayRef<uint8_t> D = SecData;
   uintX_t Offset = 0;
   auto RelI = Rels.begin();
   auto RelE = Rels.end();
 
   DenseMap<unsigned, unsigned> OffsetToIndex;
   while (!D.empty()) {
     unsigned Index = S->Offsets.size();
     S->Offsets.push_back(std::make_pair(Offset, -1));
 
     uintX_t Length = readEntryLength(D);
     // If CIE/FDE data length is zero then Length is 4, this
     // shall be considered a terminator and processing shall end.
     if (Length == 4)
       break;
     StringRef Entry((const char *)D.data(), Length);
 
     while (RelI != RelE && RelI->r_offset < Offset)
       ++RelI;
     uintX_t NextOffset = Offset + Length;
     bool HasReloc = RelI != RelE && RelI->r_offset < NextOffset;
 
     uint32_t ID = read32<E>(D.data() + 4);
     if (ID == 0) {
       // CIE
       Cie<ELFT> C(S, Index);
       if (Config->EhFrameHdr)
         C.FdeEncoding = getFdeEncoding(D);
 
       StringRef Personality;
       if (HasReloc) {
         uint32_t SymIndex = RelI->getSymbol(Config->Mips64EL);
         SymbolBody &Body = *S->getFile()->getSymbolBody(SymIndex)->repl();
         Personality = Body.getName();
       }
 
       std::pair<StringRef, StringRef> CieInfo(Entry, Personality);
       auto P = CieMap.insert(std::make_pair(CieInfo, Cies.size()));
       if (P.second) {
         Cies.push_back(C);
         this->Header.sh_size += alignTo(Length, sizeof(uintX_t));
       }
       OffsetToIndex[Offset] = P.first->second;
     } else {
       if (!HasReloc)
         error("FDE doesn't reference another section");
       InputSectionBase<ELFT> *Target = S->getRelocTarget(*RelI);
       if (Target != &InputSection<ELFT>::Discarded && Target->isLive()) {
         uint32_t CieOffset = Offset + 4 - ID;
         auto I = OffsetToIndex.find(CieOffset);
         if (I == OffsetToIndex.end())
           error("Invalid CIE reference");
         Cies[I->second].Fdes.push_back(EHRegion<ELFT>(S, Index));
         Out<ELFT>::EhFrameHdr->reserveFde();
         this->Header.sh_size += alignTo(Length, sizeof(uintX_t));
       }
     }
 
     Offset = NextOffset;
     D = D.slice(Length);
   }
 }
 
 template <class ELFT>
 typename EHOutputSection<ELFT>::uintX_t
 EHOutputSection<ELFT>::readEntryLength(ArrayRef<uint8_t> D) {
   const endianness E = ELFT::TargetEndianness;
 
   if (D.size() < 4)
     error("Truncated CIE/FDE length");
   uint64_t Len = read32<E>(D.data());
   if (Len < UINT32_MAX) {
     if (Len > (UINT32_MAX - 4))
       error("CIE/FIE size is too large");
     if (Len + 4 > D.size())
       error("CIE/FIE ends past the end of the section");
     return Len + 4;
   }
 
   if (D.size() < 12)
     error("Truncated CIE/FDE length");
   Len = read64<E>(D.data() + 4);
   if (Len > (UINT64_MAX - 12))
     error("CIE/FIE size is too large");
   if (Len + 12 > D.size())
     error("CIE/FIE ends past the end of the section");
   return Len + 12;
 }
 
 template <class ELFT>
 void EHOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
   auto *S = cast<EHInputSection<ELFT>>(C);
   const Elf_Shdr *RelSec = S->RelocSection;
   if (!RelSec)
     return addSectionAux(
         S, make_range((const Elf_Rela *)nullptr, (const Elf_Rela *)nullptr));
   ELFFile<ELFT> &Obj = S->getFile()->getObj();
   if (RelSec->sh_type == SHT_RELA)
     return addSectionAux(S, Obj.relas(RelSec));
   return addSectionAux(S, Obj.rels(RelSec));
 }
 
 template <class ELFT>
 static typename ELFFile<ELFT>::uintX_t writeAlignedCieOrFde(StringRef Data,
                                                             uint8_t *Buf) {
   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
   const endianness E = ELFT::TargetEndianness;
   uint64_t Len = alignTo(Data.size(), sizeof(uintX_t));
   write32<E>(Buf, Len - 4);
   memcpy(Buf + 4, Data.data() + 4, Data.size() - 4);
   return Len;
 }
 
 template <class ELFT> void EHOutputSection<ELFT>::writeTo(uint8_t *Buf) {
   const endianness E = ELFT::TargetEndianness;
   size_t Offset = 0;
   for (const Cie<ELFT> &C : Cies) {
     size_t CieOffset = Offset;
 
     uintX_t CIELen = writeAlignedCieOrFde<ELFT>(C.data(), Buf + Offset);
     C.S->Offsets[C.Index].second = Offset;
     Offset += CIELen;
 
     for (const EHRegion<ELFT> &F : C.Fdes) {
       uintX_t Len = writeAlignedCieOrFde<ELFT>(F.data(), Buf + Offset);
       write32<E>(Buf + Offset + 4, Offset + 4 - CieOffset); // Pointer
       F.S->Offsets[F.Index].second = Offset;
       Out<ELFT>::EhFrameHdr->addFde(C.FdeEncoding, Offset, Buf + Offset + 8);
       Offset += Len;
     }
   }
 
   for (EHInputSection<ELFT> *S : Sections) {
     const Elf_Shdr *RelSec = S->RelocSection;
     if (!RelSec)
       continue;
     ELFFile<ELFT> &EObj = S->getFile()->getObj();
     if (RelSec->sh_type == SHT_RELA)
       S->relocate(Buf, nullptr, EObj.relas(RelSec));
     else
       S->relocate(Buf, nullptr, EObj.rels(RelSec));
   }
 }
 
 template <class ELFT>
 MergeOutputSection<ELFT>::MergeOutputSection(StringRef Name, uint32_t Type,
                                              uintX_t Flags)
     : OutputSectionBase<ELFT>(Name, Type, Flags) {}
 
 template <class ELFT> void MergeOutputSection<ELFT>::writeTo(uint8_t *Buf) {
   if (shouldTailMerge()) {
     StringRef Data = Builder.data();
     memcpy(Buf, Data.data(), Data.size());
     return;
   }
   for (const std::pair<StringRef, size_t> &P : Builder.getMap()) {
     StringRef Data = P.first;
     memcpy(Buf + P.second, Data.data(), Data.size());
   }
 }
 
 static size_t findNull(StringRef S, size_t EntSize) {
   // Optimize the common case.
   if (EntSize == 1)
     return S.find(0);
 
   for (unsigned I = 0, N = S.size(); I != N; I += EntSize) {
     const char *B = S.begin() + I;
     if (std::all_of(B, B + EntSize, [](char C) { return C == 0; }))
       return I;
   }
   return StringRef::npos;
 }
 
 template <class ELFT>
 void MergeOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
   auto *S = cast<MergeInputSection<ELFT>>(C);
   S->OutSec = this;
   uint32_t Align = S->getAlign();
   if (Align > this->Header.sh_addralign)
     this->Header.sh_addralign = Align;
 
   ArrayRef<uint8_t> D = S->getSectionData();
   StringRef Data((const char *)D.data(), D.size());
   uintX_t EntSize = S->getSectionHdr()->sh_entsize;
 
   if (this->Header.sh_flags & SHF_STRINGS) {
     uintX_t Offset = 0;
     while (!Data.empty()) {
       size_t End = findNull(Data, EntSize);
       if (End == StringRef::npos)
         error("String is not null terminated");
       StringRef Entry = Data.substr(0, End + EntSize);
       uintX_t OutputOffset = Builder.add(Entry);
       if (shouldTailMerge())
         OutputOffset = -1;
       S->Offsets.push_back(std::make_pair(Offset, OutputOffset));
       uintX_t Size = End + EntSize;
       Data = Data.substr(Size);
       Offset += Size;
     }
   } else {
     for (unsigned I = 0, N = Data.size(); I != N; I += EntSize) {
       StringRef Entry = Data.substr(I, EntSize);
       size_t OutputOffset = Builder.add(Entry);
       S->Offsets.push_back(std::make_pair(I, OutputOffset));
     }
   }
 }
 
 template <class ELFT>
 unsigned MergeOutputSection<ELFT>::getOffset(StringRef Val) {
   return Builder.getOffset(Val);
 }
 
 template <class ELFT> bool MergeOutputSection<ELFT>::shouldTailMerge() const {
   return Config->Optimize >= 2 && this->Header.sh_flags & SHF_STRINGS;
 }
 
 template <class ELFT> void MergeOutputSection<ELFT>::finalize() {
   if (shouldTailMerge())
     Builder.finalize();
   this->Header.sh_size = Builder.getSize();
 }
 
 template <class ELFT>
 StringTableSection<ELFT>::StringTableSection(StringRef Name, bool Dynamic)
     : OutputSectionBase<ELFT>(Name, SHT_STRTAB,
                               Dynamic ? (uintX_t)SHF_ALLOC : 0),
       Dynamic(Dynamic) {
   this->Header.sh_addralign = 1;
 }
 
 // String tables are created in two phases. First you call reserve()
 // to reserve room in the string table, and then call addString() to actually
 // add that string.
 //
 // Why two phases? We want to know the size of the string table as early as
 // possible to fix file layout. So we have separated finalize(), which
 // determines the size of the section, from writeTo(), which writes the section
 // contents to the output buffer. If we merge reserve() with addString(),
 // we need a plumbing work for finalize() and writeTo() so that offsets
 // we obtained in the former function can be written in the latter.
 // This design eliminated that need.
 template <class ELFT> void StringTableSection<ELFT>::reserve(StringRef S) {
   Reserved += S.size() + 1; // +1 for NUL
 }
 
 // Adds a string to the string table. You must call reserve() with the
 // same string before calling addString().
 template <class ELFT> size_t StringTableSection<ELFT>::addString(StringRef S) {
   size_t Pos = Used;
   Strings.push_back(S);
   Used += S.size() + 1;
   Reserved -= S.size() + 1;
   assert((int64_t)Reserved >= 0);
   return Pos;
 }
 
 template <class ELFT> void StringTableSection<ELFT>::writeTo(uint8_t *Buf) {
   // ELF string tables start with NUL byte, so advance the pointer by one.
   ++Buf;
   for (StringRef S : Strings) {
     memcpy(Buf, S.data(), S.size());
     Buf += S.size() + 1;
   }
 }
 
 template <class ELFT>
 bool elf2::shouldKeepInSymtab(const ObjectFile<ELFT> &File, StringRef SymName,
                               const typename ELFFile<ELFT>::Elf_Sym &Sym) {
   if (Sym.getType() == STT_SECTION || Sym.getType() == STT_FILE)
     return false;
 
   InputSectionBase<ELFT> *Sec = File.getSection(Sym);
   // If sym references a section in a discarded group, don't keep it.
   if (Sec == &InputSection<ELFT>::Discarded)
     return false;
 
   if (Config->DiscardNone)
     return true;
 
   // In ELF assembly .L symbols are normally discarded by the assembler.
   // If the assembler fails to do so, the linker discards them if
   // * --discard-locals is used.
   // * The symbol is in a SHF_MERGE section, which is normally the reason for
   //   the assembler keeping the .L symbol.
   if (!SymName.startswith(".L") && !SymName.empty())
     return true;
 
   if (Config->DiscardLocals)
     return false;
 
   return !(Sec->getSectionHdr()->sh_flags & SHF_MERGE);
 }
 
 template <class ELFT>
 SymbolTableSection<ELFT>::SymbolTableSection(
     SymbolTable<ELFT> &Table, StringTableSection<ELFT> &StrTabSec)
     : OutputSectionBase<ELFT>(StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
                               StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
                               StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0),
       Table(Table), StrTabSec(StrTabSec) {
   this->Header.sh_entsize = sizeof(Elf_Sym);
   this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
 }
 
 // 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 bool sortMipsSymbols(SymbolBody *L, SymbolBody *R) {
   if (!L->isInGot() || !R->isInGot())
     return R->isInGot();
   return L->GotIndex < R->GotIndex;
 }
 
 template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
   if (this->Header.sh_size)
     return; // Already finalized.
 
   this->Header.sh_size = getNumSymbols() * sizeof(Elf_Sym);
   this->Header.sh_link = StrTabSec.SectionIndex;
   this->Header.sh_info = NumLocals + 1;
 
   if (!StrTabSec.isDynamic()) {
     std::stable_sort(Symbols.begin(), Symbols.end(),
                      [](SymbolBody *L, SymbolBody *R) {
                        return getSymbolBinding(L) == STB_LOCAL &&
                               getSymbolBinding(R) != STB_LOCAL;
                      });
     return;
   }
   if (Out<ELFT>::GnuHashTab)
     // NB: It also sorts Symbols to meet the GNU hash table requirements.
     Out<ELFT>::GnuHashTab->addSymbols(Symbols);
   else if (Config->EMachine == EM_MIPS)
     std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols);
   size_t I = 0;
   for (SymbolBody *B : Symbols)
     B->DynamicSymbolTableIndex = ++I;
 }
 
 template <class ELFT>
 void SymbolTableSection<ELFT>::addLocalSymbol(StringRef Name) {
   StrTabSec.reserve(Name);
   ++NumVisible;
   ++NumLocals;
 }
 
 template <class ELFT>
 void SymbolTableSection<ELFT>::addSymbol(SymbolBody *Body) {
   StrTabSec.reserve(Body->getName());
   Symbols.push_back(Body);
   ++NumVisible;
 }
 
 template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
   Buf += sizeof(Elf_Sym);
 
   // All symbols with STB_LOCAL binding precede the weak and global symbols.
   // .dynsym only contains global symbols.
   if (!Config->DiscardAll && !StrTabSec.isDynamic())
     writeLocalSymbols(Buf);
 
   writeGlobalSymbols(Buf);
 }
 
 template <class ELFT>
 void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
   // Iterate over all input object files to copy their local symbols
   // to the output symbol table pointed by Buf.
   for (const std::unique_ptr<ObjectFile<ELFT>> &File : Table.getObjectFiles()) {
     Elf_Sym_Range Syms = File->getLocalSymbols();
     for (const Elf_Sym &Sym : Syms) {
       ErrorOr<StringRef> SymNameOrErr = Sym.getName(File->getStringTable());
       error(SymNameOrErr);
       StringRef SymName = *SymNameOrErr;
       if (!shouldKeepInSymtab<ELFT>(*File, SymName, Sym))
         continue;
 
       auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
       uintX_t VA = 0;
       if (Sym.st_shndx == SHN_ABS) {
         ESym->st_shndx = SHN_ABS;
         VA = Sym.st_value;
       } else {
         InputSectionBase<ELFT> *Section = File->getSection(Sym);
         if (!Section->isLive())
           continue;
         const OutputSectionBase<ELFT> *OutSec = Section->OutSec;
         ESym->st_shndx = OutSec->SectionIndex;
         VA = Section->getOffset(Sym);
         // Symbol offsets for AMDGPU need to be the offset in bytes of the
         // symbol from the beginning of the section.
         if (Config->EMachine != EM_AMDGPU)
           VA += OutSec->getVA();
       }
       ESym->st_name = StrTabSec.addString(SymName);
       ESym->st_size = Sym.st_size;
       ESym->setBindingAndType(Sym.getBinding(), Sym.getType());
       ESym->st_value = VA;
       Buf += sizeof(*ESym);
     }
   }
 }
 
 template <class ELFT>
 static const typename llvm::object::ELFFile<ELFT>::Elf_Sym *
 getElfSym(SymbolBody &Body) {
   if (auto *EBody = dyn_cast<DefinedElf<ELFT>>(&Body))
     return &EBody->Sym;
   if (auto *EBody = dyn_cast<UndefinedElf<ELFT>>(&Body))
     return &EBody->Sym;
   return nullptr;
 }
 
 template <class ELFT>
 void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
   // Write the internal symbol table contents to the output symbol table
   // pointed by Buf.
   auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
   for (SymbolBody *Body : Symbols) {
     const OutputSectionBase<ELFT> *OutSec = nullptr;
 
     switch (Body->kind()) {
     case SymbolBody::DefinedSyntheticKind:
       OutSec = &cast<DefinedSynthetic<ELFT>>(Body)->Section;
       break;
     case SymbolBody::DefinedRegularKind: {
       auto *Sym = cast<DefinedRegular<ELFT>>(Body->repl());
       if (InputSectionBase<ELFT> *Sec = Sym->Section) {
         if (!Sec->isLive())
           continue;
         OutSec = Sec->OutSec;
       }
       break;
     }
     case SymbolBody::DefinedCommonKind:
       OutSec = Out<ELFT>::Bss;
       break;
     case SymbolBody::SharedKind: {
       if (cast<SharedSymbol<ELFT>>(Body)->NeedsCopy)
         OutSec = Out<ELFT>::Bss;
       break;
     }
     case SymbolBody::UndefinedElfKind:
     case SymbolBody::UndefinedKind:
     case SymbolBody::LazyKind:
       break;
     }
 
     StringRef Name = Body->getName();
     ESym->st_name = StrTabSec.addString(Name);
 
     unsigned char Type = STT_NOTYPE;
     uintX_t Size = 0;
     if (const Elf_Sym *InputSym = getElfSym<ELFT>(*Body)) {
       Type = InputSym->getType();
       Size = InputSym->st_size;
     } else if (auto *C = dyn_cast<DefinedCommon>(Body)) {
       Type = STT_OBJECT;
       Size = C->Size;
     }
 
     ESym->setBindingAndType(getSymbolBinding(Body), Type);
     ESym->st_size = Size;
     ESym->setVisibility(Body->getVisibility());
     ESym->st_value = getSymVA<ELFT>(*Body);
 
     if (OutSec)
       ESym->st_shndx = OutSec->SectionIndex;
     else if (isa<DefinedRegular<ELFT>>(Body))
       ESym->st_shndx = SHN_ABS;
 
     ++ESym;
   }
 }
 
 template <class ELFT>
 uint8_t SymbolTableSection<ELFT>::getSymbolBinding(SymbolBody *Body) {
   uint8_t Visibility = Body->getVisibility();
   if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
     return STB_LOCAL;
   if (const Elf_Sym *ESym = getElfSym<ELFT>(*Body))
     return ESym->getBinding();
   if (isa<DefinedSynthetic<ELFT>>(Body))
     return STB_LOCAL;
   return Body->isWeak() ? STB_WEAK : STB_GLOBAL;
 }
 
 template <class ELFT>
 MipsReginfoOutputSection<ELFT>::MipsReginfoOutputSection()
     : OutputSectionBase<ELFT>(".reginfo", SHT_MIPS_REGINFO, SHF_ALLOC) {
   this->Header.sh_addralign = 4;
   this->Header.sh_entsize = sizeof(Elf_Mips_RegInfo);
   this->Header.sh_size = sizeof(Elf_Mips_RegInfo);
 }
 
 template <class ELFT>
 void MipsReginfoOutputSection<ELFT>::writeTo(uint8_t *Buf) {
   auto *R = reinterpret_cast<Elf_Mips_RegInfo *>(Buf);
   R->ri_gp_value = getMipsGpAddr<ELFT>();
   R->ri_gprmask = GprMask;
 }
 
 template <class ELFT>
 void MipsReginfoOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
   // Copy input object file's .reginfo gprmask to output.
   auto *S = cast<MipsReginfoInputSection<ELFT>>(C);
   GprMask |= S->Reginfo->ri_gprmask;
 }
 
 namespace lld {
 namespace elf2 {
 template class OutputSectionBase<ELF32LE>;
 template class OutputSectionBase<ELF32BE>;
 template class OutputSectionBase<ELF64LE>;
 template class OutputSectionBase<ELF64BE>;
 
 template class EhFrameHeader<ELF32LE>;
 template class EhFrameHeader<ELF32BE>;
 template class EhFrameHeader<ELF64LE>;
 template class EhFrameHeader<ELF64BE>;
 
 template class GotPltSection<ELF32LE>;
 template class GotPltSection<ELF32BE>;
 template class GotPltSection<ELF64LE>;
 template class GotPltSection<ELF64BE>;
 
 template class GotSection<ELF32LE>;
 template class GotSection<ELF32BE>;
 template class GotSection<ELF64LE>;
 template class GotSection<ELF64BE>;
 
 template class PltSection<ELF32LE>;
 template class PltSection<ELF32BE>;
 template class PltSection<ELF64LE>;
 template class PltSection<ELF64BE>;
 
 template class RelocationSection<ELF32LE>;
 template class RelocationSection<ELF32BE>;
 template class RelocationSection<ELF64LE>;
 template class RelocationSection<ELF64BE>;
 
 template class InterpSection<ELF32LE>;
 template class InterpSection<ELF32BE>;
 template class InterpSection<ELF64LE>;
 template class InterpSection<ELF64BE>;
 
 template class GnuHashTableSection<ELF32LE>;
 template class GnuHashTableSection<ELF32BE>;
 template class GnuHashTableSection<ELF64LE>;
 template class GnuHashTableSection<ELF64BE>;
 
 template class HashTableSection<ELF32LE>;
 template class HashTableSection<ELF32BE>;
 template class HashTableSection<ELF64LE>;
 template class HashTableSection<ELF64BE>;
 
 template class DynamicSection<ELF32LE>;
 template class DynamicSection<ELF32BE>;
 template class DynamicSection<ELF64LE>;
 template class DynamicSection<ELF64BE>;
 
 template class OutputSection<ELF32LE>;
 template class OutputSection<ELF32BE>;
 template class OutputSection<ELF64LE>;
 template class OutputSection<ELF64BE>;
 
 template class EHOutputSection<ELF32LE>;
 template class EHOutputSection<ELF32BE>;
 template class EHOutputSection<ELF64LE>;
 template class EHOutputSection<ELF64BE>;
 
 template class MipsReginfoOutputSection<ELF32LE>;
 template class MipsReginfoOutputSection<ELF32BE>;
 template class MipsReginfoOutputSection<ELF64LE>;
 template class MipsReginfoOutputSection<ELF64BE>;
 
 template class MergeOutputSection<ELF32LE>;
 template class MergeOutputSection<ELF32BE>;
 template class MergeOutputSection<ELF64LE>;
 template class MergeOutputSection<ELF64BE>;
 
 template class StringTableSection<ELF32LE>;
 template class StringTableSection<ELF32BE>;
 template class StringTableSection<ELF64LE>;
 template class StringTableSection<ELF64BE>;
 
 template class SymbolTableSection<ELF32LE>;
 template class SymbolTableSection<ELF32BE>;
 template class SymbolTableSection<ELF64LE>;
 template class SymbolTableSection<ELF64BE>;
 
 template ELFFile<ELF32LE>::uintX_t getSymVA<ELF32LE>(const SymbolBody &);
 template ELFFile<ELF32BE>::uintX_t getSymVA<ELF32BE>(const SymbolBody &);
 template ELFFile<ELF64LE>::uintX_t getSymVA<ELF64LE>(const SymbolBody &);
 template ELFFile<ELF64BE>::uintX_t getSymVA<ELF64BE>(const SymbolBody &);
 
 template ELFFile<ELF32LE>::uintX_t
 getLocalRelTarget(const ObjectFile<ELF32LE> &,
                   const ELFFile<ELF32LE>::Elf_Rel &,
                   ELFFile<ELF32LE>::uintX_t Addend);
 template ELFFile<ELF32BE>::uintX_t
 getLocalRelTarget(const ObjectFile<ELF32BE> &,
                   const ELFFile<ELF32BE>::Elf_Rel &,
                   ELFFile<ELF32BE>::uintX_t Addend);
 template ELFFile<ELF64LE>::uintX_t
 getLocalRelTarget(const ObjectFile<ELF64LE> &,
                   const ELFFile<ELF64LE>::Elf_Rel &,
                   ELFFile<ELF64LE>::uintX_t Addend);
 template ELFFile<ELF64BE>::uintX_t
 getLocalRelTarget(const ObjectFile<ELF64BE> &,
                   const ELFFile<ELF64BE>::Elf_Rel &,
                   ELFFile<ELF64BE>::uintX_t Addend);
 
 template bool shouldKeepInSymtab<ELF32LE>(const ObjectFile<ELF32LE> &,
                                           StringRef,
                                           const ELFFile<ELF32LE>::Elf_Sym &);
 template bool shouldKeepInSymtab<ELF32BE>(const ObjectFile<ELF32BE> &,
                                           StringRef,
                                           const ELFFile<ELF32BE>::Elf_Sym &);
 template bool shouldKeepInSymtab<ELF64LE>(const ObjectFile<ELF64LE> &,
                                           StringRef,
                                           const ELFFile<ELF64LE>::Elf_Sym &);
 template bool shouldKeepInSymtab<ELF64BE>(const ObjectFile<ELF64BE> &,
                                           StringRef,
                                           const ELFFile<ELF64BE>::Elf_Sym &);
 }
 }
diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h
index 0deb00f..9360c3d 100644
--- a/ELF/OutputSections.h
+++ b/ELF/OutputSections.h
@@ -1,525 +1,542 @@
 //===- OutputSections.h -----------------------------------------*- C++ -*-===//
 //
 //                             The LLVM Linker
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
 #ifndef LLD_ELF_OUTPUT_SECTIONS_H
 #define LLD_ELF_OUTPUT_SECTIONS_H
 
 #include "lld/Core/LLVM.h"
 
 #include "llvm/ADT/MapVector.h"
 #include "llvm/MC/StringTableBuilder.h"
 #include "llvm/Object/ELF.h"
 
 #include "Config.h"
 
 #include <type_traits>
 
 namespace lld {
 namespace elf2 {
 
 class SymbolBody;
 template <class ELFT> class SymbolTable;
 template <class ELFT> class SymbolTableSection;
 template <class ELFT> class StringTableSection;
 template <class ELFT> class EHInputSection;
 template <class ELFT> class InputSection;
 template <class ELFT> class InputSectionBase;
 template <class ELFT> class MergeInputSection;
 template <class ELFT> class MipsReginfoInputSection;
 template <class ELFT> class OutputSection;
 template <class ELFT> class ObjectFile;
 template <class ELFT> class DefinedRegular;
 
 template <class ELFT>
 static inline typename llvm::object::ELFFile<ELFT>::uintX_t
 getAddend(const typename llvm::object::ELFFile<ELFT>::Elf_Rel &Rel) {
   return 0;
 }
 
 template <class ELFT>
 static inline typename llvm::object::ELFFile<ELFT>::uintX_t
 getAddend(const typename llvm::object::ELFFile<ELFT>::Elf_Rela &Rel) {
   return Rel.r_addend;
 }
 
 template <class ELFT>
 typename llvm::object::ELFFile<ELFT>::uintX_t getSymVA(const SymbolBody &S);
 
 template <class ELFT, bool IsRela>
 typename llvm::object::ELFFile<ELFT>::uintX_t
 getLocalRelTarget(const ObjectFile<ELFT> &File,
                   const llvm::object::Elf_Rel_Impl<ELFT, IsRela> &Rel,
                   typename llvm::object::ELFFile<ELFT>::uintX_t Addend);
 
 bool canBePreempted(const SymbolBody *Body, bool NeedsGot);
 
 template <class ELFT>
 bool shouldKeepInSymtab(
     const ObjectFile<ELFT> &File, StringRef Name,
     const typename llvm::object::ELFFile<ELFT>::Elf_Sym &Sym);
 
 // This represents a section in an output file.
 // Different sub classes represent different types of sections. Some contain
 // input sections, others are created by the linker.
 // The writer creates multiple OutputSections and assign them unique,
 // non-overlapping file offsets and VAs.
 template <class ELFT> class OutputSectionBase {
 public:
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
 
   OutputSectionBase(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
   void setVA(uintX_t VA) { Header.sh_addr = VA; }
   uintX_t getVA() const { return Header.sh_addr; }
   void setFileOffset(uintX_t Off) { Header.sh_offset = Off; }
   void writeHeaderTo(Elf_Shdr *SHdr);
   StringRef getName() { return Name; }
 
   virtual void addSection(InputSectionBase<ELFT> *C) {}
 
   unsigned SectionIndex;
 
   // Returns the size of the section in the output file.
   uintX_t getSize() const { return Header.sh_size; }
   void setSize(uintX_t Val) { Header.sh_size = Val; }
   uintX_t getFlags() { return Header.sh_flags; }
   uintX_t getFileOff() { return Header.sh_offset; }
   uintX_t getAlign() {
     // The ELF spec states that a value of 0 means the section has no alignment
     // constraits.
     return std::max<uintX_t>(Header.sh_addralign, 1);
   }
   uint32_t getType() { return Header.sh_type; }
   void updateAlign(uintX_t Align) {
     if (Align > Header.sh_addralign)
       Header.sh_addralign = Align;
   }
 
   virtual void finalize() {}
   virtual void writeTo(uint8_t *Buf) = 0;
   virtual ~OutputSectionBase() = default;
 
 protected:
   StringRef Name;
   Elf_Shdr Header;
 };
 
 template <class ELFT> class GotSection final : public OutputSectionBase<ELFT> {
   typedef OutputSectionBase<ELFT> Base;
   typedef typename Base::uintX_t uintX_t;
 
 public:
   GotSection();
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
   void addEntry(SymbolBody *Sym);
   void addMipsLocalEntry();
   bool addDynTlsEntry(SymbolBody *Sym);
   bool addCurrentModuleTlsIndex();
   bool empty() const { return MipsLocalEntries == 0 && Entries.empty(); }
   uintX_t getEntryAddr(const SymbolBody &B) const;
   uintX_t getMipsLocalFullAddr(const SymbolBody &B);
   uintX_t getMipsLocalPageAddr(uintX_t Addr);
   uintX_t getGlobalDynAddr(const SymbolBody &B) const;
   uintX_t getNumEntries() const { return Entries.size(); }
 
   // Returns the symbol which corresponds to the first entry of the global part
   // of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic
   // table properties.
   // Returns nullptr if the global part is empty.
   const SymbolBody *getMipsFirstGlobalEntry() const;
 
   // Returns the number of entries in the local part of GOT including
   // the number of reserved entries. This method is MIPS-specific.
   unsigned getMipsLocalEntriesNum() const;
 
   uint32_t getLocalTlsIndexVA() { return Base::getVA() + LocalTlsIndexOff; }
 
 private:
   std::vector<const SymbolBody *> Entries;
   uint32_t LocalTlsIndexOff = -1;
   uint32_t MipsLocalEntries = 0;
   llvm::DenseMap<uintX_t, size_t> MipsLocalGotPos;
 
   uintX_t getMipsLocalEntryAddr(uintX_t EntryValue);
 };
 
 template <class ELFT>
 class GotPltSection final : public OutputSectionBase<ELFT> {
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
 
 public:
   GotPltSection();
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
   void addEntry(SymbolBody *Sym);
   bool empty() const;
   uintX_t getEntryAddr(const SymbolBody &B) const;
 
 private:
   std::vector<const SymbolBody *> Entries;
 };
 
 template <class ELFT> class PltSection final : public OutputSectionBase<ELFT> {
   typedef OutputSectionBase<ELFT> Base;
   typedef typename Base::uintX_t uintX_t;
 
 public:
   PltSection();
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
   void addEntry(SymbolBody *Sym);
   bool empty() const { return Entries.empty(); }
   uintX_t getEntryAddr(const SymbolBody &B) const;
 
 private:
   std::vector<std::pair<const SymbolBody *, unsigned>> Entries;
 };
 
 template <class ELFT> struct DynamicReloc {
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
   InputSectionBase<ELFT> *C;
   const Elf_Rel *RI;
 };
 
 template <class ELFT>
 class SymbolTableSection final : public OutputSectionBase<ELFT> {
 public:
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
   SymbolTableSection(SymbolTable<ELFT> &Table,
                      StringTableSection<ELFT> &StrTabSec);
 
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
   void addLocalSymbol(StringRef Name);
   void addSymbol(SymbolBody *Body);
   StringTableSection<ELFT> &getStrTabSec() const { return StrTabSec; }
   unsigned getNumSymbols() const { return NumVisible + 1; }
 
   ArrayRef<SymbolBody *> getSymbols() const { return Symbols; }
 
 private:
   void writeLocalSymbols(uint8_t *&Buf);
   void writeGlobalSymbols(uint8_t *Buf);
 
   static uint8_t getSymbolBinding(SymbolBody *Body);
 
   SymbolTable<ELFT> &Table;
   StringTableSection<ELFT> &StrTabSec;
   std::vector<SymbolBody *> Symbols;
   unsigned NumVisible = 0;
   unsigned NumLocals = 0;
 };
 
 template <class ELFT>
 class RelocationSection final : public OutputSectionBase<ELFT> {
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
 
 public:
   RelocationSection(StringRef Name, bool IsRela);
   void addReloc(const DynamicReloc<ELFT> &Reloc) { Relocs.push_back(Reloc); }
   unsigned getRelocOffset();
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
   bool hasRelocs() const { return !Relocs.empty(); }
   bool isRela() const { return IsRela; }
 
   bool Static = false;
 
 private:
   bool applyTlsDynamicReloc(SymbolBody *Body, uint32_t Type, Elf_Rel *P,
                             Elf_Rel *N);
 
   std::vector<DynamicReloc<ELFT>> Relocs;
   const bool IsRela;
 };
 
 template <class ELFT>
 class OutputSection final : public OutputSectionBase<ELFT> {
 public:
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
   OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
   void addSection(InputSectionBase<ELFT> *C) override;
   void writeTo(uint8_t *Buf) override;
 
 private:
   std::vector<InputSection<ELFT> *> Sections;
 };
 
 template <class ELFT>
 class MergeOutputSection final : public OutputSectionBase<ELFT> {
   typedef typename OutputSectionBase<ELFT>::uintX_t uintX_t;
 
   bool shouldTailMerge() const;
 
 public:
   MergeOutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
   void addSection(InputSectionBase<ELFT> *S) override;
   void writeTo(uint8_t *Buf) override;
   unsigned getOffset(StringRef Val);
   void finalize() override;
 
 private:
   llvm::StringTableBuilder Builder{llvm::StringTableBuilder::RAW};
 };
 
 // FDE or CIE
 template <class ELFT> struct EHRegion {
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
   EHRegion(EHInputSection<ELFT> *S, unsigned Index);
   StringRef data() const;
   EHInputSection<ELFT> *S;
   unsigned Index;
 };
 
 template <class ELFT> struct Cie : public EHRegion<ELFT> {
   Cie(EHInputSection<ELFT> *S, unsigned Index);
   std::vector<EHRegion<ELFT>> Fdes;
   uint8_t FdeEncoding;
 };
 
 template <class ELFT>
 class EHOutputSection final : public OutputSectionBase<ELFT> {
 public:
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
   EHOutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
   void writeTo(uint8_t *Buf) override;
 
   template <bool IsRela>
   void addSectionAux(
       EHInputSection<ELFT> *S,
       llvm::iterator_range<const llvm::object::Elf_Rel_Impl<ELFT, IsRela> *>
           Rels);
 
   void addSection(InputSectionBase<ELFT> *S) override;
 
 private:
   uint8_t getFdeEncoding(ArrayRef<uint8_t> D);
   uintX_t readEntryLength(ArrayRef<uint8_t> D);
 
   std::vector<EHInputSection<ELFT> *> Sections;
   std::vector<Cie<ELFT>> Cies;
 
   // Maps CIE content + personality to a index in Cies.
   llvm::DenseMap<std::pair<StringRef, StringRef>, unsigned> CieMap;
 };
 
 template <class ELFT>
 class InterpSection final : public OutputSectionBase<ELFT> {
 public:
   InterpSection();
   void writeTo(uint8_t *Buf) override;
 };
 
 template <class ELFT>
 class StringTableSection final : public OutputSectionBase<ELFT> {
 public:
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
   StringTableSection(StringRef Name, bool Dynamic);
   void reserve(StringRef S);
   size_t addString(StringRef S);
   void writeTo(uint8_t *Buf) override;
   size_t getSize() const { return Used + Reserved; }
   void finalize() override { this->Header.sh_size = getSize(); }
   bool isDynamic() const { return Dynamic; }
 
 private:
   const bool Dynamic;
   std::vector<StringRef> Strings;
   size_t Used = 1; // ELF string tables start with a NUL byte, so 1.
   size_t Reserved = 0;
 };
 
 template <class ELFT>
 class HashTableSection final : public OutputSectionBase<ELFT> {
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
 
 public:
   HashTableSection();
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
 };
 
 // Outputs GNU Hash section. For detailed explanation see:
 // https://blogs.oracle.com/ali/entry/gnu_hash_elf_sections
 template <class ELFT>
 class GnuHashTableSection final : public OutputSectionBase<ELFT> {
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Off Elf_Off;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
 
 public:
   GnuHashTableSection();
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
 
   // Adds symbols to the hash table.
   // Sorts the input to satisfy GNU hash section requirements.
   void addSymbols(std::vector<SymbolBody *> &Symbols);
 
 private:
   static unsigned calcNBuckets(unsigned NumHashed);
   static unsigned calcMaskWords(unsigned NumHashed);
 
   void writeHeader(uint8_t *&Buf);
   void writeBloomFilter(uint8_t *&Buf);
   void writeHashTable(uint8_t *Buf);
 
   struct HashedSymbolData {
     SymbolBody *Body;
     uint32_t Hash;
   };
 
   std::vector<HashedSymbolData> HashedSymbols;
 
   unsigned MaskWords;
   unsigned NBuckets;
   unsigned Shift2;
 };
 
 template <class ELFT>
 class DynamicSection final : public OutputSectionBase<ELFT> {
   typedef OutputSectionBase<ELFT> Base;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Dyn Elf_Dyn;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+  typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+
+  struct Entry {
+    int32_t Tag;
+    union {
+      OutputSectionBase<ELFT> *OutSec;
+      uint64_t Val;
+      const SymbolBody *Sym;
+    };
+    enum KindT { SecAddr, SymAddr, PlainInt } Kind;
+    Entry(int32_t Tag, OutputSectionBase<ELFT> *OutSec)
+        : Tag(Tag), OutSec(OutSec), Kind(SecAddr) {}
+    Entry(int32_t Tag, uint64_t Val) : Tag(Tag), Val(Val), Kind(PlainInt) {}
+    Entry(int32_t Tag, const SymbolBody *Sym)
+        : Tag(Tag), Sym(Sym), Kind(SymAddr) {}
+  };
+  std::vector<Entry> Entries;
 
 public:
   DynamicSection(SymbolTable<ELFT> &SymTab);
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
 
   OutputSectionBase<ELFT> *PreInitArraySec = nullptr;
   OutputSectionBase<ELFT> *InitArraySec = nullptr;
   OutputSectionBase<ELFT> *FiniArraySec = nullptr;
 
 private:
   SymbolTable<ELFT> &SymTab;
   const SymbolBody *InitSym = nullptr;
   const SymbolBody *FiniSym = nullptr;
   uint32_t DtFlags = 0;
   uint32_t DtFlags1 = 0;
 };
 
 template <class ELFT>
 class MipsReginfoOutputSection final : public OutputSectionBase<ELFT> {
   typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
 
 public:
   MipsReginfoOutputSection();
   void writeTo(uint8_t *Buf) override;
   void addSection(InputSectionBase<ELFT> *S) override;
 
 private:
   uint32_t GprMask = 0;
 };
 
 // --eh-frame-hdr option tells linker to construct a header for all the
 // .eh_frame sections. This header is placed to a section named .eh_frame_hdr
 // and also to a PT_GNU_EH_FRAME segment.
 // At runtime the unwinder then can find all the PT_GNU_EH_FRAME segments by
 // calling dl_iterate_phdr.
 // This section contains a lookup table for quick binary search of FDEs.
 // Detailed info about internals can be found in Ian Lance Taylor's blog:
 // http://www.airs.com/blog/archives/460 (".eh_frame")
 // http://www.airs.com/blog/archives/462 (".eh_frame_hdr")
 template <class ELFT>
 class EhFrameHeader final : public OutputSectionBase<ELFT> {
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
 
 public:
   EhFrameHeader();
   void writeTo(uint8_t *Buf) override;
 
   void addFde(uint8_t Enc, size_t Off, uint8_t *PCRel);
   void assignEhFrame(EHOutputSection<ELFT> *Sec);
   void reserveFde();
 
   bool Live = false;
 
 private:
   struct FdeData {
     uint8_t Enc;
     size_t Off;
     uint8_t *PCRel;
   };
 
   uintX_t getFdePc(uintX_t EhVA, const FdeData &F);
 
   EHOutputSection<ELFT> *Sec = nullptr;
   std::vector<FdeData> FdeList;
 };
 
 // All output sections that are hadnled by the linker specially are
 // globally accessible. Writer initializes them, so don't use them
 // until Writer is initialized.
 template <class ELFT> struct Out {
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Phdr Elf_Phdr;
   static DynamicSection<ELFT> *Dynamic;
   static EhFrameHeader<ELFT> *EhFrameHdr;
   static GnuHashTableSection<ELFT> *GnuHashTab;
   static GotPltSection<ELFT> *GotPlt;
   static GotSection<ELFT> *Got;
   static HashTableSection<ELFT> *HashTab;
   static InterpSection<ELFT> *Interp;
   static OutputSection<ELFT> *Bss;
   static OutputSection<ELFT> *MipsRldMap;
   static OutputSectionBase<ELFT> *Opd;
   static uint8_t *OpdBuf;
   static PltSection<ELFT> *Plt;
   static RelocationSection<ELFT> *RelaDyn;
   static RelocationSection<ELFT> *RelaPlt;
   static StringTableSection<ELFT> *DynStrTab;
   static StringTableSection<ELFT> *ShStrTab;
   static StringTableSection<ELFT> *StrTab;
   static SymbolTableSection<ELFT> *DynSymTab;
   static SymbolTableSection<ELFT> *SymTab;
   static Elf_Phdr *TlsPhdr;
 };
 
 template <class ELFT> DynamicSection<ELFT> *Out<ELFT>::Dynamic;
 template <class ELFT> EhFrameHeader<ELFT> *Out<ELFT>::EhFrameHdr;
 template <class ELFT> GnuHashTableSection<ELFT> *Out<ELFT>::GnuHashTab;
 template <class ELFT> GotPltSection<ELFT> *Out<ELFT>::GotPlt;
 template <class ELFT> GotSection<ELFT> *Out<ELFT>::Got;
 template <class ELFT> HashTableSection<ELFT> *Out<ELFT>::HashTab;
 template <class ELFT> InterpSection<ELFT> *Out<ELFT>::Interp;
 template <class ELFT> OutputSection<ELFT> *Out<ELFT>::Bss;
 template <class ELFT> OutputSection<ELFT> *Out<ELFT>::MipsRldMap;
 template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::Opd;
 template <class ELFT> uint8_t *Out<ELFT>::OpdBuf;
 template <class ELFT> PltSection<ELFT> *Out<ELFT>::Plt;
 template <class ELFT> RelocationSection<ELFT> *Out<ELFT>::RelaDyn;
 template <class ELFT> RelocationSection<ELFT> *Out<ELFT>::RelaPlt;
 template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::DynStrTab;
 template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::ShStrTab;
 template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::StrTab;
 template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab;
 template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::SymTab;
 template <class ELFT> typename Out<ELFT>::Elf_Phdr *Out<ELFT>::TlsPhdr;
 
 } // namespace elf2
 } // namespace lld
 
 #endif // LLD_ELF_OUTPUT_SECTIONS_H
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 622ca04..04d9214 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -1,1354 +1,1353 @@
 //===- Writer.cpp ---------------------------------------------------------===//
 //
 //                             The LLVM Linker
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
 #include "Writer.h"
 #include "Config.h"
 #include "OutputSections.h"
 #include "SymbolTable.h"
 #include "Target.h"
 
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/StringSaver.h"
 
 using namespace llvm;
 using namespace llvm::ELF;
 using namespace llvm::object;
 
 using namespace lld;
 using namespace lld::elf2;
 
 namespace {
 // The writer writes a SymbolTable result to a file.
 template <class ELFT> class Writer {
 public:
   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
   typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
   typedef typename ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
   typedef typename ELFFile<ELFT>::Elf_Phdr Elf_Phdr;
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
   typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
   Writer(SymbolTable<ELFT> &S) : Symtab(S) {}
   void run();
 
 private:
   void copyLocalSymbols();
   void addReservedSymbols();
   void createSections();
   void addPredefinedSections();
 
   template <bool isRela>
   void scanRelocs(InputSectionBase<ELFT> &C,
                   iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels);
 
   void scanRelocs(InputSection<ELFT> &C);
   void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec);
   void updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr, uintX_t VA);
   void assignAddresses();
   void buildSectionMap();
   void fixAbsoluteSymbols();
   void openFile(StringRef OutputPath);
   void writeHeader();
   void writeSections();
   bool isDiscarded(InputSectionBase<ELFT> *IS) const;
   StringRef getOutputSectionName(StringRef S) const;
   bool needsInterpSection() const {
     return !Symtab.getSharedFiles().empty() && !Config->DynamicLinker.empty();
   }
   bool isOutputDynamic() const {
     return !Symtab.getSharedFiles().empty() || Config->Shared;
   }
   int getPhdrsNum() const;
 
   OutputSection<ELFT> *getBss();
   void addCommonSymbols(std::vector<DefinedCommon *> &Syms);
   void addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms);
 
   std::unique_ptr<llvm::FileOutputBuffer> Buffer;
 
   BumpPtrAllocator Alloc;
   std::vector<OutputSectionBase<ELFT> *> OutputSections;
   std::vector<std::unique_ptr<OutputSectionBase<ELFT>>> OwningSections;
   unsigned getNumSections() const { return OutputSections.size() + 1; }
 
   void addRelIpltSymbols();
   void addStartEndSymbols();
   void addStartStopSymbols(OutputSectionBase<ELFT> *Sec);
   void setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags, uintX_t FileOff,
                uintX_t VA, uintX_t Size, uintX_t Align);
   void copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *From);
 
   bool HasRelro = false;
   SymbolTable<ELFT> &Symtab;
   std::vector<Elf_Phdr> Phdrs;
 
   uintX_t FileSize;
   uintX_t SectionHeaderOff;
 
   llvm::StringMap<llvm::StringRef> InputToOutputSection;
 
   // Flag to force GOT to be in output if we have relocations
   // that relies on its address.
   bool HasGotOffRel = false;
 };
 } // anonymous namespace
 
 template <class ELFT> static bool shouldUseRela() { return ELFT::Is64Bits; }
 
 template <class ELFT> void elf2::writeResult(SymbolTable<ELFT> *Symtab) {
   // Initialize output sections that are handled by Writer specially.
   // Don't reorder because the order of initialization matters.
   InterpSection<ELFT> Interp;
   Out<ELFT>::Interp = &Interp;
   StringTableSection<ELFT> ShStrTab(".shstrtab", false);
   Out<ELFT>::ShStrTab = &ShStrTab;
   StringTableSection<ELFT> StrTab(".strtab", false);
   if (!Config->StripAll)
     Out<ELFT>::StrTab = &StrTab;
   StringTableSection<ELFT> DynStrTab(".dynstr", true);
   Out<ELFT>::DynStrTab = &DynStrTab;
   GotSection<ELFT> Got;
   Out<ELFT>::Got = &Got;
   GotPltSection<ELFT> GotPlt;
   if (Target->supportsLazyRelocations())
     Out<ELFT>::GotPlt = &GotPlt;
   PltSection<ELFT> Plt;
   Out<ELFT>::Plt = &Plt;
   std::unique_ptr<SymbolTableSection<ELFT>> SymTab;
   if (!Config->StripAll) {
     SymTab.reset(new SymbolTableSection<ELFT>(*Symtab, *Out<ELFT>::StrTab));
     Out<ELFT>::SymTab = SymTab.get();
   }
   SymbolTableSection<ELFT> DynSymTab(*Symtab, *Out<ELFT>::DynStrTab);
   Out<ELFT>::DynSymTab = &DynSymTab;
   HashTableSection<ELFT> HashTab;
   if (Config->SysvHash)
     Out<ELFT>::HashTab = &HashTab;
   GnuHashTableSection<ELFT> GnuHashTab;
   if (Config->GnuHash)
     Out<ELFT>::GnuHashTab = &GnuHashTab;
   bool IsRela = shouldUseRela<ELFT>();
   RelocationSection<ELFT> RelaDyn(IsRela ? ".rela.dyn" : ".rel.dyn", IsRela);
   Out<ELFT>::RelaDyn = &RelaDyn;
   RelocationSection<ELFT> RelaPlt(IsRela ? ".rela.plt" : ".rel.plt", IsRela);
   if (Target->supportsLazyRelocations())
     Out<ELFT>::RelaPlt = &RelaPlt;
   DynamicSection<ELFT> Dynamic(*Symtab);
   Out<ELFT>::Dynamic = &Dynamic;
   EhFrameHeader<ELFT> EhFrameHdr;
   Out<ELFT>::EhFrameHdr = &EhFrameHdr;
 
   Writer<ELFT>(*Symtab).run();
 }
 
 // The main function of the writer.
 template <class ELFT> void Writer<ELFT>::run() {
   buildSectionMap();
   if (!Config->DiscardAll)
     copyLocalSymbols();
   addReservedSymbols();
   createSections();
   assignAddresses();
   fixAbsoluteSymbols();
   openFile(Config->OutputFile);
   writeHeader();
   writeSections();
   error(Buffer->commit());
 }
 
 namespace {
 template <bool Is64Bits> struct SectionKey {
   typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
   StringRef Name;
   uint32_t Type;
   uintX_t Flags;
   uintX_t EntSize;
 };
 }
 namespace llvm {
 template <bool Is64Bits> struct DenseMapInfo<SectionKey<Is64Bits>> {
   static SectionKey<Is64Bits> getEmptyKey() {
     return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0,
                                 0};
   }
   static SectionKey<Is64Bits> getTombstoneKey() {
     return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getTombstoneKey(), 0,
                                 0, 0};
   }
   static unsigned getHashValue(const SectionKey<Is64Bits> &Val) {
     return hash_combine(Val.Name, Val.Type, Val.Flags, Val.EntSize);
   }
   static bool isEqual(const SectionKey<Is64Bits> &LHS,
                       const SectionKey<Is64Bits> &RHS) {
     return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) &&
            LHS.Type == RHS.Type && LHS.Flags == RHS.Flags &&
            LHS.EntSize == RHS.EntSize;
   }
 };
 }
 
 template <class ELFT, class RelT>
 static bool handleTlsRelocation(unsigned Type, SymbolBody *Body,
                                 InputSectionBase<ELFT> &C, RelT &RI) {
   if (Target->isTlsLocalDynamicReloc(Type)) {
     if (Target->isTlsOptimized(Type, nullptr))
       return true;
     if (Out<ELFT>::Got->addCurrentModuleTlsIndex())
       Out<ELFT>::RelaDyn->addReloc({&C, &RI});
     return true;
   }
 
   if (!Body || !Body->isTls())
     return false;
 
   if (Target->isTlsGlobalDynamicReloc(Type)) {
     bool Opt = Target->isTlsOptimized(Type, Body);
     if (!Opt && Out<ELFT>::Got->addDynTlsEntry(Body)) {
       Out<ELFT>::RelaDyn->addReloc({&C, &RI});
       Out<ELFT>::RelaDyn->addReloc({nullptr, nullptr});
       Body->setUsedInDynamicReloc();
       return true;
     }
     if (!canBePreempted(Body, true))
       return true;
   }
   return !Target->isTlsDynReloc(Type, *Body);
 }
 
 // The reason we have to do this early scan is as follows
 // * To mmap the output file, we need to know the size
 // * For that, we need to know how many dynamic relocs we will have.
 // It might be possible to avoid this by outputting the file with write:
 // * Write the allocated output sections, computing addresses.
 // * Apply relocations, recording which ones require a dynamic reloc.
 // * Write the dynamic relocations.
 // * Write the rest of the file.
 template <class ELFT>
 template <bool isRela>
 void Writer<ELFT>::scanRelocs(
     InputSectionBase<ELFT> &C,
     iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) {
   typedef Elf_Rel_Impl<ELFT, isRela> RelType;
   const ObjectFile<ELFT> &File = *C.getFile();
   for (const RelType &RI : Rels) {
     uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
     SymbolBody *Body = File.getSymbolBody(SymIndex);
     uint32_t Type = RI.getType(Config->Mips64EL);
 
     // Ignore "hint" relocation because it is for optional code optimization.
     if (Target->isHintReloc(Type))
       continue;
 
     if (Target->isGotRelative(Type))
       HasGotOffRel = true;
 
     // Set "used" bit for --as-needed.
     if (Body && Body->isUndefined() && !Body->isWeak())
       if (auto *S = dyn_cast<SharedSymbol<ELFT>>(Body->repl()))
         S->File->IsUsed = true;
 
     if (Body)
       Body = Body->repl();
 
     if (handleTlsRelocation<ELFT>(Type, Body, C, RI))
       continue;
 
     if (Target->relocNeedsDynRelative(Type)) {
       RelType *Rel = new (Alloc) RelType;
       Rel->setSymbolAndType(0, Target->getRelativeReloc(), Config->Mips64EL);
       Rel->r_offset = RI.r_offset;
       Out<ELFT>::RelaDyn->addReloc({&C, Rel});
     }
 
     bool NeedsGot = false;
     bool NeedsMipsLocalGot = false;
     bool NeedsPlt = false;
     if (Config->EMachine == EM_MIPS && needsMipsLocalGot(Type, Body)) {
       NeedsMipsLocalGot = true;
       // FIXME (simon): Do not add so many redundant entries.
       Out<ELFT>::Got->addMipsLocalEntry();
     } else if (Body) {
       if (auto *E = dyn_cast<SharedSymbol<ELFT>>(Body)) {
         if (E->NeedsCopy)
           continue;
         if (Target->needsCopyRel(Type, *Body))
           E->NeedsCopy = true;
       }
       NeedsPlt = Target->relocNeedsPlt(Type, *Body);
       if (NeedsPlt) {
         if (Body->isInPlt())
           continue;
         Out<ELFT>::Plt->addEntry(Body);
       }
       NeedsGot = Target->relocNeedsGot(Type, *Body);
       if (NeedsGot) {
         if (NeedsPlt && Target->supportsLazyRelocations()) {
           Out<ELFT>::GotPlt->addEntry(Body);
         } else {
           if (Body->isInGot())
             continue;
           Out<ELFT>::Got->addEntry(Body);
         }
       }
     }
 
     // An STT_GNU_IFUNC symbol always uses a PLT entry, and all references
     // to the symbol go through the PLT. This is true even for a local
     // symbol, although local symbols normally do not require PLT entries.
     if (Body && isGnuIFunc<ELFT>(*Body)) {
       Body->setUsedInDynamicReloc();
       Out<ELFT>::RelaPlt->addReloc({&C, &RI});
       continue;
     }
 
     if (Config->EMachine == EM_MIPS) {
       if (Type == R_MIPS_LO16)
         // Ignore R_MIPS_LO16 relocation. If it is a pair for R_MIPS_GOT16 we
         // already completed all required action (GOT entry allocation) when
         // handle R_MIPS_GOT16a. If it is a pair for R_MIPS_HI16 against
         // _gp_disp it does not require dynamic relocation. If its a pair for
         // R_MIPS_HI16 against a regular symbol it does not require dynamic
         // relocation too because that case is possible for executable file
         // linking only.
         continue;
       if (NeedsGot || NeedsMipsLocalGot) {
         // MIPS ABI has special rules to process GOT entries
         // and doesn't require relocation entries for them.
         // 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
         if (NeedsGot)
           Body->setUsedInDynamicReloc();
         continue;
       }
       if (Body == Config->MipsGpDisp)
         // MIPS _gp_disp designates offset between start of function and gp
         // pointer into GOT therefore any relocations against it do not require
         // dynamic relocation.
         continue;
     }
 
     // Here we are creating a relocation for the dynamic linker based on
     // a relocation from an object file, but some relocations need no
     // load-time fixup when the final target is known. Skip such relocation.
     bool CBP = canBePreempted(Body, NeedsGot);
     bool NoDynrel = Target->isRelRelative(Type) || Target->isSizeReloc(Type) ||
                     !Config->Shared;
     if (!CBP && NoDynrel)
       continue;
 
     if (CBP)
       Body->setUsedInDynamicReloc();
     if (NeedsPlt && Target->supportsLazyRelocations())
       Out<ELFT>::RelaPlt->addReloc({&C, &RI});
     else
       Out<ELFT>::RelaDyn->addReloc({&C, &RI});
   }
 }
 
 template <class ELFT> void Writer<ELFT>::scanRelocs(InputSection<ELFT> &C) {
   if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC))
     return;
 
   for (const Elf_Shdr *RelSec : C.RelocSections)
     scanRelocs(C, *RelSec);
 }
 
 template <class ELFT>
 void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &S,
                               const Elf_Shdr &RelSec) {
   ELFFile<ELFT> &EObj = S.getFile()->getObj();
   if (RelSec.sh_type == SHT_RELA)
     scanRelocs(S, EObj.relas(&RelSec));
   else
     scanRelocs(S, EObj.rels(&RelSec));
 }
 
 template <class ELFT>
 static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) {
   if (Config->Shared && !Config->NoUndefined)
     return;
 
   std::string Msg = "undefined symbol: " + Sym->getName().str();
   if (ELFFileBase<ELFT> *File = Symtab.findFile(Sym))
     Msg += " in " + File->getName().str();
   if (Config->NoInhibitExec)
     warning(Msg);
   else
     error(Msg);
 }
 
 // Local symbols are not in the linker's symbol table. This function scans
 // each object file's symbol table to copy local symbols to the output.
 template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
   if (!Out<ELFT>::SymTab)
     return;
   for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
     for (const Elf_Sym &Sym : F->getLocalSymbols()) {
       ErrorOr<StringRef> SymNameOrErr = Sym.getName(F->getStringTable());
       error(SymNameOrErr);
       StringRef SymName = *SymNameOrErr;
       if (!shouldKeepInSymtab<ELFT>(*F, SymName, Sym))
         continue;
       Out<ELFT>::SymTab->addLocalSymbol(SymName);
     }
   }
 }
 
 // PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections that
 // we would like to make sure appear is a specific order to maximize their
 // coverage by a single signed 16-bit offset from the TOC base pointer.
 // Conversely, the special .tocbss section should be first among all SHT_NOBITS
 // sections. This will put it next to the loaded special PPC64 sections (and,
 // thus, within reach of the TOC base pointer).
 static int getPPC64SectionRank(StringRef SectionName) {
   return StringSwitch<int>(SectionName)
            .Case(".tocbss", 0)
            .Case(".branch_lt", 2)
            .Case(".toc", 3)
            .Case(".toc1", 4)
            .Case(".opd", 5)
            .Default(1);
 }
 
 template <class ELFT> static bool isRelroSection(OutputSectionBase<ELFT> *Sec) {
   typename OutputSectionBase<ELFT>::uintX_t Flags = Sec->getFlags();
   if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE))
     return false;
   if (Flags & SHF_TLS)
     return true;
   uint32_t Type = Sec->getType();
   if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY ||
       Type == SHT_PREINIT_ARRAY)
     return true;
   if (Sec == Out<ELFT>::GotPlt)
     return Config->ZNow;
   if (Sec == Out<ELFT>::Dynamic || Sec == Out<ELFT>::Got)
     return true;
   StringRef S = Sec->getName();
   return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" ||
          S == ".eh_frame";
 }
 
 // Output section ordering is determined by this function.
 template <class ELFT>
 static bool compareOutputSections(OutputSectionBase<ELFT> *A,
                                   OutputSectionBase<ELFT> *B) {
   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
 
   uintX_t AFlags = A->getFlags();
   uintX_t BFlags = B->getFlags();
 
   // Allocatable sections go first to reduce the total PT_LOAD size and
   // so debug info doesn't change addresses in actual code.
   bool AIsAlloc = AFlags & SHF_ALLOC;
   bool BIsAlloc = BFlags & SHF_ALLOC;
   if (AIsAlloc != BIsAlloc)
     return AIsAlloc;
 
   // We don't have any special requirements for the relative order of
   // two non allocatable sections.
   if (!AIsAlloc)
     return false;
 
   // We want the read only sections first so that they go in the PT_LOAD
   // covering the program headers at the start of the file.
   bool AIsWritable = AFlags & SHF_WRITE;
   bool BIsWritable = BFlags & SHF_WRITE;
   if (AIsWritable != BIsWritable)
     return BIsWritable;
 
   // For a corresponding reason, put non exec sections first (the program
   // header PT_LOAD is not executable).
   bool AIsExec = AFlags & SHF_EXECINSTR;
   bool BIsExec = BFlags & SHF_EXECINSTR;
   if (AIsExec != BIsExec)
     return BIsExec;
 
   // If we got here we know that both A and B are in the same PT_LOAD.
 
   // The TLS initialization block needs to be a single contiguous block in a R/W
   // PT_LOAD, so stick TLS sections directly before R/W sections. The TLS NOBITS
   // sections are placed here as they don't take up virtual address space in the
   // PT_LOAD.
   bool AIsTls = AFlags & SHF_TLS;
   bool BIsTls = BFlags & SHF_TLS;
   if (AIsTls != BIsTls)
     return AIsTls;
 
   // The next requirement we have is to put nobits sections last. The
   // reason is that the only thing the dynamic linker will see about
   // them is a p_memsz that is larger than p_filesz. Seeing that it
   // zeros the end of the PT_LOAD, so that has to correspond to the
   // nobits sections.
   bool AIsNoBits = A->getType() == SHT_NOBITS;
   bool BIsNoBits = B->getType() == SHT_NOBITS;
   if (AIsNoBits != BIsNoBits)
     return BIsNoBits;
 
   // We place RelRo section before plain r/w ones.
   bool AIsRelRo = isRelroSection(A);
   bool BIsRelRo = isRelroSection(B);
   if (AIsRelRo != BIsRelRo)
     return AIsRelRo;
 
   // Some architectures have additional ordering restrictions for sections
   // within the same PT_LOAD.
   if (Config->EMachine == EM_PPC64)
     return getPPC64SectionRank(A->getName()) <
            getPPC64SectionRank(B->getName());
 
   return false;
 }
 
 template <class ELFT> OutputSection<ELFT> *Writer<ELFT>::getBss() {
   if (!Out<ELFT>::Bss) {
     Out<ELFT>::Bss =
         new OutputSection<ELFT>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
     OwningSections.emplace_back(Out<ELFT>::Bss);
     OutputSections.push_back(Out<ELFT>::Bss);
   }
   return Out<ELFT>::Bss;
 }
 
 // Until this function is called, common symbols do not belong to any section.
 // This function adds them to end of BSS section.
 template <class ELFT>
 void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) {
   if (Syms.empty())
     return;
 
   // Sort the common symbols by alignment as an heuristic to pack them better.
   std::stable_sort(Syms.begin(), Syms.end(),
                    [](const DefinedCommon *A, const DefinedCommon *B) {
                      return A->MaxAlignment > B->MaxAlignment;
                    });
 
   uintX_t Off = getBss()->getSize();
   for (DefinedCommon *C : Syms) {
     Off = alignTo(Off, C->MaxAlignment);
     C->OffsetInBss = Off;
     Off += C->Size;
   }
 
   Out<ELFT>::Bss->setSize(Off);
 }
 
 // Reserve space in .bss for copy relocations.
 template <class ELFT>
 void Writer<ELFT>::addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms) {
   if (Syms.empty())
     return;
   uintX_t Off = getBss()->getSize();
   for (SharedSymbol<ELFT> *C : Syms) {
     const Elf_Sym &Sym = C->Sym;
     const Elf_Shdr *Sec = C->File->getSection(Sym);
     uintX_t SecAlign = Sec->sh_addralign;
     unsigned TrailingZeros =
         std::min(countTrailingZeros(SecAlign),
                  countTrailingZeros((uintX_t)Sym.st_value));
     uintX_t Align = 1 << TrailingZeros;
     Out<ELFT>::Bss->updateAlign(Align);
     Off = alignTo(Off, Align);
     C->OffsetInBss = Off;
     Off += Sym.st_size;
   }
   Out<ELFT>::Bss->setSize(Off);
 }
 
 template <class ELFT>
 StringRef Writer<ELFT>::getOutputSectionName(StringRef S) const {
   auto It = InputToOutputSection.find(S);
   if (It != std::end(InputToOutputSection))
     return It->second;
 
   if (S.startswith(".text."))
     return ".text";
   if (S.startswith(".rodata."))
     return ".rodata";
   if (S.startswith(".data.rel.ro"))
     return ".data.rel.ro";
   if (S.startswith(".data."))
     return ".data";
   if (S.startswith(".bss."))
     return ".bss";
   return S;
 }
 
 template <class ELFT>
 void reportDiscarded(InputSectionBase<ELFT> *IS,
                      const std::unique_ptr<ObjectFile<ELFT>> &File) {
   if (!Config->PrintGcSections || !IS || IS->isLive())
     return;
   llvm::errs() << "removing unused section from '" << IS->getSectionName()
                << "' in file '" << File->getName() << "'\n";
 }
 
 template <class ELFT>
 bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *IS) const {
   if (!IS || !IS->isLive() || IS == &InputSection<ELFT>::Discarded)
     return true;
   return InputToOutputSection.lookup(IS->getSectionName()) == "/DISCARD/";
 }
 
 template <class ELFT>
 static bool compareSections(OutputSectionBase<ELFT> *A,
                             OutputSectionBase<ELFT> *B) {
   auto ItA = Config->OutputSections.find(A->getName());
   auto ItEnd = std::end(Config->OutputSections);
   if (ItA == ItEnd)
     return compareOutputSections(A, B);
   auto ItB = Config->OutputSections.find(B->getName());
   if (ItB == ItEnd)
     return compareOutputSections(A, B);
 
   return std::distance(ItA, ItB) > 0;
 }
 
 // The beginning and the ending of .rel[a].plt section are marked
 // with __rel[a]_iplt_{start,end} symbols if it is a statically linked
 // executable. The runtime needs these symbols in order to resolve
 // all IRELATIVE relocs on startup. For dynamic executables, we don't
 // need these symbols, since IRELATIVE relocs are resolved through GOT
 // and PLT. For details, see http://www.airs.com/blog/archives/403.
 template <class ELFT>
 void Writer<ELFT>::addRelIpltSymbols() {
   if (isOutputDynamic() || !Out<ELFT>::RelaPlt)
     return;
   bool IsRela = shouldUseRela<ELFT>();
 
   StringRef S = IsRela ? "__rela_iplt_start" : "__rel_iplt_start";
   if (Symtab.find(S))
     Symtab.addAbsolute(S, ElfSym<ELFT>::RelaIpltStart);
 
   S = IsRela ? "__rela_iplt_end" : "__rel_iplt_end";
   if (Symtab.find(S))
     Symtab.addAbsolute(S, ElfSym<ELFT>::RelaIpltEnd);
 }
 
 template <class ELFT> static bool includeInSymtab(const SymbolBody &B) {
   if (!B.isUsedInRegularObj())
     return false;
 
   // Don't include synthetic symbols like __init_array_start in every output.
   if (auto *U = dyn_cast<DefinedRegular<ELFT>>(&B))
     if (&U->Sym == &ElfSym<ELFT>::Ignored)
       return false;
 
   return true;
 }
 
 static bool includeInDynamicSymtab(const SymbolBody &B) {
   uint8_t V = B.getVisibility();
   if (V != STV_DEFAULT && V != STV_PROTECTED)
     return false;
   if (Config->ExportDynamic || Config->Shared)
     return true;
   return B.isUsedInDynamicReloc();
 }
 
 // This class knows how to create an output section for a given
 // input section. Output section type is determined by various
 // factors, including input section's sh_flags, sh_type and
 // linker scripts.
 namespace {
 template <class ELFT> class OutputSectionFactory {
   typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
 
 public:
   std::pair<OutputSectionBase<ELFT> *, bool> create(InputSectionBase<ELFT> *C,
                                                     StringRef OutsecName);
 
   OutputSectionBase<ELFT> *lookup(StringRef Name, uint32_t Type, uintX_t Flags);
 
 private:
   SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
                                        StringRef OutsecName);
 
   SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSectionBase<ELFT> *> Map;
 };
 }
 
 template <class ELFT>
 std::pair<OutputSectionBase<ELFT> *, bool>
 OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C,
                                    StringRef OutsecName) {
   SectionKey<ELFT::Is64Bits> Key = createKey(C, OutsecName);
   OutputSectionBase<ELFT> *&Sec = Map[Key];
   if (Sec)
     return {Sec, false};
 
   switch (C->SectionKind) {
   case InputSectionBase<ELFT>::Regular:
     Sec = new OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
     break;
   case InputSectionBase<ELFT>::EHFrame:
     Sec = new EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
     break;
   case InputSectionBase<ELFT>::Merge:
     Sec = new MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
     break;
   case InputSectionBase<ELFT>::MipsReginfo:
     Sec = new MipsReginfoOutputSection<ELFT>();
     break;
   }
   return {Sec, true};
 }
 
 template <class ELFT>
 OutputSectionBase<ELFT> *OutputSectionFactory<ELFT>::lookup(StringRef Name,
                                                             uint32_t Type,
                                                             uintX_t Flags) {
   return Map.lookup({Name, Type, Flags, 0});
 }
 
 template <class ELFT>
 SectionKey<ELFT::Is64Bits>
 OutputSectionFactory<ELFT>::createKey(InputSectionBase<ELFT> *C,
                                       StringRef OutsecName) {
   const Elf_Shdr *H = C->getSectionHdr();
   uintX_t Flags = H->sh_flags & ~SHF_GROUP;
 
   // For SHF_MERGE we create different output sections for each sh_entsize.
   // This makes each output section simple and keeps a single level
   // mapping from input to output.
   uintX_t EntSize = isa<MergeInputSection<ELFT>>(C) ? H->sh_entsize : 0;
 
   // GNU as can give .eh_frame secion type SHT_PROGBITS or SHT_X86_64_UNWIND
   // depending on the construct. We want to canonicalize it so that
   // there is only one .eh_frame in the end.
   uint32_t Type = H->sh_type;
   if (Type == SHT_PROGBITS && Config->EMachine == EM_X86_64 &&
       isa<EHInputSection<ELFT>>(C))
     Type = SHT_X86_64_UNWIND;
 
   return SectionKey<ELFT::Is64Bits>{OutsecName, Type, Flags, EntSize};
 }
 
 // The linker is expected to define some symbols depending on
 // the linking result. This function defines such symbols.
 template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
   // __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For
   // static linking the linker is required to optimize away any references to
   // __tls_get_addr, so it's not defined anywhere. Create a hidden definition
   // to avoid the undefined symbol error.
   if (!isOutputDynamic())
     Symtab.addIgnored("__tls_get_addr");
 
   // If the "_end" symbol is referenced, it is expected to point to the address
   // right after the data segment. Usually, this symbol points to the end
   // of .bss section or to the end of .data section if .bss section is absent.
   // The order of the sections can be affected by linker script,
   // so it is hard to predict which section will be the last one.
   // So, if this symbol is referenced, we just add the placeholder here
   // and update its value later.
   if (Symtab.find("_end"))
     Symtab.addAbsolute("_end", ElfSym<ELFT>::End);
 
   // If there is an undefined symbol "end", we should initialize it
   // with the same value as "_end". In any other case it should stay intact,
   // because it is an allowable name for a user symbol.
   if (SymbolBody *B = Symtab.find("end"))
     if (B->isUndefined())
       Symtab.addAbsolute("end", ElfSym<ELFT>::End);
 }
 
 // Create output section objects and add them to OutputSections.
 template <class ELFT> void Writer<ELFT>::createSections() {
   // Add .interp first because some loaders want to see that section
   // on the first page of the executable file when loaded into memory.
   if (needsInterpSection())
     OutputSections.push_back(Out<ELFT>::Interp);
 
   // Create output sections for input object file sections.
   std::vector<OutputSectionBase<ELFT> *> RegularSections;
   OutputSectionFactory<ELFT> Factory;
   for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
     for (InputSectionBase<ELFT> *C : F->getSections()) {
       if (isDiscarded(C)) {
         reportDiscarded(C, F);
         continue;
       }
       OutputSectionBase<ELFT> *Sec;
       bool IsNew;
       std::tie(Sec, IsNew) =
           Factory.create(C, getOutputSectionName(C->getSectionName()));
       if (IsNew) {
         OwningSections.emplace_back(Sec);
         OutputSections.push_back(Sec);
         RegularSections.push_back(Sec);
       }
       Sec->addSection(C);
     }
   }
 
   Out<ELFT>::Bss = static_cast<OutputSection<ELFT> *>(
       Factory.lookup(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE));
 
   // If we have a .opd section (used under PPC64 for function descriptors),
   // store a pointer to it here so that we can use it later when processing
   // relocations.
   Out<ELFT>::Opd = Factory.lookup(".opd", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC);
 
   Out<ELFT>::Dynamic->PreInitArraySec = Factory.lookup(
       ".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE | SHF_ALLOC);
   Out<ELFT>::Dynamic->InitArraySec =
       Factory.lookup(".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC);
   Out<ELFT>::Dynamic->FiniArraySec =
       Factory.lookup(".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC);
 
   // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop
   // symbols for sections, so that the runtime can get the start and end
   // addresses of each section by section name. Add such symbols.
   addStartEndSymbols();
   for (OutputSectionBase<ELFT> *Sec : RegularSections)
     addStartStopSymbols(Sec);
 
   // Scan relocations. This must be done after every symbol is declared so that
   // we can correctly decide if a dynamic relocation is needed.
   for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
     for (InputSectionBase<ELFT> *C : F->getSections()) {
       if (isDiscarded(C))
         continue;
       if (auto *S = dyn_cast<InputSection<ELFT>>(C))
         scanRelocs(*S);
       else if (auto *S = dyn_cast<EHInputSection<ELFT>>(C))
         if (S->RelocSection)
           scanRelocs(*S, *S->RelocSection);
     }
   }
 
   // Define __rel[a]_iplt_{start,end} symbols if needed.
   addRelIpltSymbols();
 
   // Now that we have defined all possible symbols including linker-
   // synthesized ones. Visit all symbols to give the finishing touches.
   std::vector<DefinedCommon *> CommonSymbols;
   std::vector<SharedSymbol<ELFT> *> CopyRelSymbols;
   for (auto &P : Symtab.getSymbols()) {
     SymbolBody *Body = P.second->Body;
     if (auto *U = dyn_cast<Undefined>(Body))
       if (!U->isWeak() && !U->canKeepUndefined())
         reportUndefined<ELFT>(Symtab, Body);
 
     if (auto *C = dyn_cast<DefinedCommon>(Body))
       CommonSymbols.push_back(C);
     if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body))
       if (SC->NeedsCopy)
         CopyRelSymbols.push_back(SC);
 
     if (!includeInSymtab<ELFT>(*Body))
       continue;
     if (Out<ELFT>::SymTab)
       Out<ELFT>::SymTab->addSymbol(Body);
 
     if (isOutputDynamic() && includeInDynamicSymtab(*Body))
       Out<ELFT>::DynSymTab->addSymbol(Body);
   }
   addCommonSymbols(CommonSymbols);
   addCopyRelSymbols(CopyRelSymbols);
 
   // So far we have added sections from input object files.
   // This function adds linker-created Out<ELFT>::* sections.
   addPredefinedSections();
 
   std::stable_sort(OutputSections.begin(), OutputSections.end(),
                    compareSections<ELFT>);
 
   for (unsigned I = 0, N = OutputSections.size(); I < N; ++I) {
     OutputSections[I]->SectionIndex = I + 1;
     HasRelro |= (Config->ZRelro && isRelroSection(OutputSections[I]));
   }
 
   for (OutputSectionBase<ELFT> *Sec : OutputSections)
     Out<ELFT>::ShStrTab->reserve(Sec->getName());
 
   // Finalizers fix each section's size.
-  // .dynamic section's finalizer may add strings to .dynstr,
-  // so finalize that early.
-  // Likewise, .dynsym is finalized early since that may fill up .gnu.hash.
-  Out<ELFT>::Dynamic->finalize();
+  // .dynsym is finalized early since that may fill up .gnu.hash.
   if (isOutputDynamic())
     Out<ELFT>::DynSymTab->finalize();
 
-  // Fill other section headers.
+  // Fill other section headers. The dynamic string table in finalized
+  // once the .dynamic finalizer has added a few last strings.
   for (OutputSectionBase<ELFT> *Sec : OutputSections)
-    Sec->finalize();
+    if (Sec != Out<ELFT>::DynStrTab)
+      Sec->finalize();
 }
 
 // This function add Out<ELFT>::* sections to OutputSections.
 template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
   auto Add = [&](OutputSectionBase<ELFT> *C) {
     if (C)
       OutputSections.push_back(C);
   };
 
   // This order is not the same as the final output order
   // because we sort the sections using their attributes below.
   Add(Out<ELFT>::SymTab);
   Add(Out<ELFT>::ShStrTab);
   Add(Out<ELFT>::StrTab);
   if (isOutputDynamic()) {
     Add(Out<ELFT>::DynSymTab);
     Add(Out<ELFT>::GnuHashTab);
     Add(Out<ELFT>::HashTab);
     Add(Out<ELFT>::Dynamic);
     Add(Out<ELFT>::DynStrTab);
     if (Out<ELFT>::RelaDyn->hasRelocs())
       Add(Out<ELFT>::RelaDyn);
 
     // This is a MIPS specific section to hold a space within the data segment
     // of executable file which is pointed to by the DT_MIPS_RLD_MAP entry.
     // See "Dynamic section" in Chapter 5 in the following document:
     // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
     if (Config->EMachine == EM_MIPS && !Config->Shared) {
       Out<ELFT>::MipsRldMap = new OutputSection<ELFT>(".rld_map", SHT_PROGBITS,
                                                       SHF_ALLOC | SHF_WRITE);
       Out<ELFT>::MipsRldMap->setSize(ELFT::Is64Bits ? 8 : 4);
       Out<ELFT>::MipsRldMap->updateAlign(ELFT::Is64Bits ? 8 : 4);
       OwningSections.emplace_back(Out<ELFT>::MipsRldMap);
       Add(Out<ELFT>::MipsRldMap);
     }
   }
 
   // We always need to add rel[a].plt to output if it has entries.
   // Even during static linking it can contain R_[*]_IRELATIVE relocations.
   if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
     Add(Out<ELFT>::RelaPlt);
     Out<ELFT>::RelaPlt->Static = !isOutputDynamic();
   }
 
   bool needsGot = !Out<ELFT>::Got->empty();
   // We add the .got section to the result for dynamic MIPS target because
   // its address and properties are mentioned in the .dynamic section.
   if (Config->EMachine == EM_MIPS)
     needsGot |= isOutputDynamic();
   // If we have a relocation that is relative to GOT (such as GOTOFFREL),
   // we need to emit a GOT even if it's empty.
   if (HasGotOffRel)
     needsGot = true;
 
   if (needsGot)
     Add(Out<ELFT>::Got);
   if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
     Add(Out<ELFT>::GotPlt);
   if (!Out<ELFT>::Plt->empty())
     Add(Out<ELFT>::Plt);
 
   if (Out<ELFT>::EhFrameHdr->Live)
     Add(Out<ELFT>::EhFrameHdr);
 }
 
 // The linker is expected to define SECNAME_start and SECNAME_end
 // symbols for a few sections. This function defines them.
 template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
   auto Define = [&](StringRef Start, StringRef End,
                     OutputSectionBase<ELFT> *OS) {
     if (OS) {
       Symtab.addSynthetic(Start, *OS, 0);
       Symtab.addSynthetic(End, *OS, OS->getSize());
     } else {
       Symtab.addIgnored(Start);
       Symtab.addIgnored(End);
     }
   };
 
   Define("__preinit_array_start", "__preinit_array_end",
          Out<ELFT>::Dynamic->PreInitArraySec);
   Define("__init_array_start", "__init_array_end",
          Out<ELFT>::Dynamic->InitArraySec);
   Define("__fini_array_start", "__fini_array_end",
          Out<ELFT>::Dynamic->FiniArraySec);
 }
 
 static bool isAlpha(char C) {
   return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_';
 }
 
 static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); }
 
 // Returns true if S is valid as a C language identifier.
 static bool isValidCIdentifier(StringRef S) {
   if (S.empty() || !isAlpha(S[0]))
     return false;
   return std::all_of(S.begin() + 1, S.end(), isAlnum);
 }
 
 // If a section name is valid as a C identifier (which is rare because of
 // the leading '.'), linkers are expected to define __start_<secname> and
 // __stop_<secname> symbols. They are at beginning and end of the section,
 // respectively. This is not requested by the ELF standard, but GNU ld and
 // gold provide the feature, and used by many programs.
 template <class ELFT>
 void Writer<ELFT>::addStartStopSymbols(OutputSectionBase<ELFT> *Sec) {
   StringRef S = Sec->getName();
   if (!isValidCIdentifier(S))
     return;
   StringSaver Saver(Alloc);
   StringRef Start = Saver.save("__start_" + S);
   StringRef Stop = Saver.save("__stop_" + S);
   if (SymbolBody *B = Symtab.find(Start))
     if (B->isUndefined())
       Symtab.addSynthetic(Start, *Sec, 0);
   if (SymbolBody *B = Symtab.find(Stop))
     if (B->isUndefined())
       Symtab.addSynthetic(Stop, *Sec, Sec->getSize());
 }
 
 template <class ELFT> static bool needsPhdr(OutputSectionBase<ELFT> *Sec) {
   return Sec->getFlags() & SHF_ALLOC;
 }
 
 static uint32_t toPhdrFlags(uint64_t Flags) {
   uint32_t Ret = PF_R;
   if (Flags & SHF_WRITE)
     Ret |= PF_W;
   if (Flags & SHF_EXECINSTR)
     Ret |= PF_X;
   return Ret;
 }
 
 /// For AMDGPU we need to use custom segment kinds in order to specify which
 /// address space data should be loaded into.
 template <class ELFT>
 static uint32_t getAmdgpuPhdr(OutputSectionBase<ELFT> *Sec) {
   uint32_t Flags = Sec->getFlags();
   if (Flags & SHF_AMDGPU_HSA_CODE)
     return PT_AMDGPU_HSA_LOAD_CODE_AGENT;
   if ((Flags & SHF_AMDGPU_HSA_GLOBAL) && !(Flags & SHF_AMDGPU_HSA_AGENT))
     return PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM;
   return PT_LOAD;
 }
 
 template <class ELFT>
 void Writer<ELFT>::updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
                                uintX_t VA) {
   if (!GnuRelroPhdr->p_type)
     setPhdr(GnuRelroPhdr, PT_GNU_RELRO, PF_R, Cur->p_offset, Cur->p_vaddr,
             VA - Cur->p_vaddr, 1 /*p_align*/);
   GnuRelroPhdr->p_filesz = VA - Cur->p_vaddr;
   GnuRelroPhdr->p_memsz = VA - Cur->p_vaddr;
 }
 
 // Visits all sections to create PHDRs and to assign incremental,
 // non-overlapping addresses to output sections.
 template <class ELFT> void Writer<ELFT>::assignAddresses() {
   uintX_t VA = Target->getVAStart() + sizeof(Elf_Ehdr);
   uintX_t FileOff = sizeof(Elf_Ehdr);
 
   // Calculate and reserve the space for the program header first so that
   // the first section can start right after the program header.
   Phdrs.resize(getPhdrsNum());
   size_t PhdrSize = sizeof(Elf_Phdr) * Phdrs.size();
 
   // The first phdr entry is PT_PHDR which describes the program header itself.
   setPhdr(&Phdrs[0], PT_PHDR, PF_R, FileOff, VA, PhdrSize, /*Align=*/8);
   FileOff += PhdrSize;
   VA += PhdrSize;
 
   // PT_INTERP must be the second entry if exists.
   int PhdrIdx = 0;
   Elf_Phdr *Interp = nullptr;
   if (needsInterpSection())
     Interp = &Phdrs[++PhdrIdx];
 
   // Add the first PT_LOAD segment for regular output sections.
   setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, Target->getVAStart(), FileOff,
           Target->getPageSize());
 
   Elf_Phdr GnuRelroPhdr = {};
   Elf_Phdr TlsPhdr{};
   bool RelroAligned = false;
   uintX_t ThreadBssOffset = 0;
   // Create phdrs as we assign VAs and file offsets to all output sections.
   for (OutputSectionBase<ELFT> *Sec : OutputSections) {
     Elf_Phdr *PH = &Phdrs[PhdrIdx];
     if (needsPhdr<ELFT>(Sec)) {
       uintX_t Flags = toPhdrFlags(Sec->getFlags());
       bool InRelRo = Config->ZRelro && (Flags & PF_W) && isRelroSection(Sec);
       bool FirstNonRelRo = GnuRelroPhdr.p_type && !InRelRo && !RelroAligned;
       if (FirstNonRelRo || PH->p_flags != Flags) {
         VA = alignTo(VA, Target->getPageSize());
         FileOff = alignTo(FileOff, Target->getPageSize());
         if (FirstNonRelRo)
           RelroAligned = true;
       }
 
       if (PH->p_flags != Flags) {
         // Flags changed. Create a new PT_LOAD.
         PH = &Phdrs[++PhdrIdx];
         uint32_t PTType = (Config->EMachine != EM_AMDGPU) ? (uint32_t)PT_LOAD
                                                           : getAmdgpuPhdr(Sec);
         setPhdr(PH, PTType, Flags, FileOff, VA, 0, Target->getPageSize());
       }
 
       if (Sec->getFlags() & SHF_TLS) {
         if (!TlsPhdr.p_vaddr)
           setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign());
         if (Sec->getType() != SHT_NOBITS)
           VA = alignTo(VA, Sec->getAlign());
         uintX_t TVA = alignTo(VA + ThreadBssOffset, Sec->getAlign());
         Sec->setVA(TVA);
         TlsPhdr.p_memsz += Sec->getSize();
         if (Sec->getType() == SHT_NOBITS) {
           ThreadBssOffset = TVA - VA + Sec->getSize();
         } else {
           TlsPhdr.p_filesz += Sec->getSize();
           VA += Sec->getSize();
         }
         TlsPhdr.p_align = std::max<uintX_t>(TlsPhdr.p_align, Sec->getAlign());
       } else {
         VA = alignTo(VA, Sec->getAlign());
         Sec->setVA(VA);
         VA += Sec->getSize();
         if (InRelRo)
           updateRelro(PH, &GnuRelroPhdr, VA);
       }
     }
 
     FileOff = alignTo(FileOff, Sec->getAlign());
     Sec->setFileOffset(FileOff);
     if (Sec->getType() != SHT_NOBITS)
       FileOff += Sec->getSize();
     if (needsPhdr<ELFT>(Sec)) {
       PH->p_filesz = FileOff - PH->p_offset;
       PH->p_memsz = VA - PH->p_vaddr;
     }
   }
 
   if (TlsPhdr.p_vaddr) {
     // The TLS pointer goes after PT_TLS. At least glibc will align it,
     // so round up the size to make sure the offsets are correct.
     TlsPhdr.p_memsz = alignTo(TlsPhdr.p_memsz, TlsPhdr.p_align);
     Phdrs[++PhdrIdx] = TlsPhdr;
     Out<ELFT>::TlsPhdr = &Phdrs[PhdrIdx];
   }
 
   // Add an entry for .dynamic.
   if (isOutputDynamic()) {
     Elf_Phdr *PH = &Phdrs[++PhdrIdx];
     PH->p_type = PT_DYNAMIC;
     copyPhdr(PH, Out<ELFT>::Dynamic);
   }
 
   if (HasRelro) {
     Elf_Phdr *PH = &Phdrs[++PhdrIdx];
     *PH = GnuRelroPhdr;
   }
 
   if (Out<ELFT>::EhFrameHdr->Live) {
     Elf_Phdr *PH = &Phdrs[++PhdrIdx];
     PH->p_type = PT_GNU_EH_FRAME;
     copyPhdr(PH, Out<ELFT>::EhFrameHdr);
   }
 
   // PT_GNU_STACK is a special section to tell the loader to make the
   // pages for the stack non-executable.
   if (!Config->ZExecStack) {
     Elf_Phdr *PH = &Phdrs[++PhdrIdx];
     PH->p_type = PT_GNU_STACK;
     PH->p_flags = PF_R | PF_W;
   }
 
   // Fix up PT_INTERP as we now know the address of .interp section.
   if (Interp) {
     Interp->p_type = PT_INTERP;
     copyPhdr(Interp, Out<ELFT>::Interp);
   }
 
   // Add space for section headers.
   SectionHeaderOff = alignTo(FileOff, ELFT::Is64Bits ? 8 : 4);
   FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
 
   // Update "_end" and "end" symbols so that they
   // point to the end of the data segment.
   ElfSym<ELFT>::End.st_value = VA;
 }
 
 // Returns the number of PHDR entries.
 template <class ELFT> int Writer<ELFT>::getPhdrsNum() const {
   bool Tls = false;
   int I = 2; // 2 for PT_PHDR and first PT_LOAD
   if (needsInterpSection())
     ++I;
   if (isOutputDynamic())
     ++I;
   if (!Config->ZExecStack)
     ++I;
   uintX_t Last = PF_R;
   for (OutputSectionBase<ELFT> *Sec : OutputSections) {
     if (!needsPhdr<ELFT>(Sec))
       continue;
     if (Sec->getFlags() & SHF_TLS)
       Tls = true;
     uintX_t Flags = toPhdrFlags(Sec->getFlags());
     if (Last != Flags) {
       Last = Flags;
       ++I;
     }
   }
   if (Tls)
     ++I;
   if (HasRelro)
     ++I;
   if (Out<ELFT>::EhFrameHdr->Live)
     ++I;
   return I;
 }
 
 static uint32_t getELFFlags() {
   if (Config->EMachine != EM_MIPS)
     return 0;
   // FIXME: In fact ELF flags depends on ELF flags of input object files
   // and selected emulation. For now just use hard coded values.
   uint32_t V = EF_MIPS_ABI_O32 | EF_MIPS_CPIC | EF_MIPS_ARCH_32R2;
   if (Config->Shared)
     V |= EF_MIPS_PIC;
   return V;
 }
 
 template <class ELFT>
 static typename ELFFile<ELFT>::uintX_t getEntryAddr() {
   if (Config->EntrySym) {
     if (SymbolBody *E = Config->EntrySym->repl())
       return getSymVA<ELFT>(*E);
     return 0;
   }
   if (Config->EntryAddr != uint64_t(-1))
     return Config->EntryAddr;
   return 0;
 }
 
 // This function is called after we have assigned address and size
 // to each section. This function fixes some predefined absolute
 // symbol values that depend on section address and size.
 template <class ELFT> void Writer<ELFT>::fixAbsoluteSymbols() {
   // Update __rel[a]_iplt_{start,end} symbols so that they point
   // to beginning or ending of .rela.plt section, respectively.
   if (Out<ELFT>::RelaPlt) {
     uintX_t Start = Out<ELFT>::RelaPlt->getVA();
     ElfSym<ELFT>::RelaIpltStart.st_value = Start;
     ElfSym<ELFT>::RelaIpltEnd.st_value = Start + Out<ELFT>::RelaPlt->getSize();
   }
 
   // Update MIPS _gp absolute symbol so that it points to the static data.
   if (Config->EMachine == EM_MIPS)
     ElfSym<ELFT>::MipsGp.st_value = getMipsGpAddr<ELFT>();
 }
 
 template <class ELFT> void Writer<ELFT>::writeHeader() {
   uint8_t *Buf = Buffer->getBufferStart();
   memcpy(Buf, "\177ELF", 4);
 
   // Write the ELF header.
   auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf);
   EHdr->e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
   EHdr->e_ident[EI_DATA] = ELFT::TargetEndianness == llvm::support::little
                                ? ELFDATA2LSB
                                : ELFDATA2MSB;
   EHdr->e_ident[EI_VERSION] = EV_CURRENT;
 
   auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf);
   EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI();
 
   EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC;
   EHdr->e_machine = FirstObj.getEMachine();
   EHdr->e_version = EV_CURRENT;
   EHdr->e_entry = getEntryAddr<ELFT>();
   EHdr->e_phoff = sizeof(Elf_Ehdr);
   EHdr->e_shoff = SectionHeaderOff;
   EHdr->e_flags = getELFFlags();
   EHdr->e_ehsize = sizeof(Elf_Ehdr);
   EHdr->e_phentsize = sizeof(Elf_Phdr);
   EHdr->e_phnum = Phdrs.size();
   EHdr->e_shentsize = sizeof(Elf_Shdr);
   EHdr->e_shnum = getNumSections();
   EHdr->e_shstrndx = Out<ELFT>::ShStrTab->SectionIndex;
 
   // Write the program header table.
   memcpy(Buf + EHdr->e_phoff, &Phdrs[0], Phdrs.size() * sizeof(Phdrs[0]));
 
   // Write the section header table. Note that the first table entry is null.
   auto SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
   for (OutputSectionBase<ELFT> *Sec : OutputSections)
     Sec->writeHeaderTo(++SHdrs);
 }
 
 template <class ELFT> void Writer<ELFT>::openFile(StringRef Path) {
   ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
       FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable);
   error(BufferOrErr, "failed to open " + Path);
   Buffer = std::move(*BufferOrErr);
 }
 
 // Write section contents to a mmap'ed file.
 template <class ELFT> void Writer<ELFT>::writeSections() {
   uint8_t *Buf = Buffer->getBufferStart();
 
   // PPC64 needs to process relocations in the .opd section before processing
   // relocations in code-containing sections.
   if (OutputSectionBase<ELFT> *Sec = Out<ELFT>::Opd) {
     Out<ELFT>::OpdBuf = Buf + Sec->getFileOff();
     Sec->writeTo(Buf + Sec->getFileOff());
   }
 
   // Write all sections but string table sections. We know the sizes of the
   // string tables already, but they may not have actual strings yet (only
   // room may be reserved), because writeTo() is allowed to add actual
   // strings to the string tables.
   for (OutputSectionBase<ELFT> *Sec : OutputSections)
     if (Sec != Out<ELFT>::Opd && Sec->getType() != SHT_STRTAB)
       Sec->writeTo(Buf + Sec->getFileOff());
 
   // Write string table sections.
   for (OutputSectionBase<ELFT> *Sec : OutputSections)
     if (Sec != Out<ELFT>::Opd && Sec->getType() == SHT_STRTAB)
       Sec->writeTo(Buf + Sec->getFileOff());
 }
 
 template <class ELFT>
 void Writer<ELFT>::setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags,
                            uintX_t FileOff, uintX_t VA, uintX_t Size,
                            uintX_t Align) {
   PH->p_type = Type;
   PH->p_flags = Flags;
   PH->p_offset = FileOff;
   PH->p_vaddr = VA;
   PH->p_paddr = VA;
   PH->p_filesz = Size;
   PH->p_memsz = Size;
   PH->p_align = Align;
 }
 
 template <class ELFT>
 void Writer<ELFT>::copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *From) {
   PH->p_flags = toPhdrFlags(From->getFlags());
   PH->p_offset = From->getFileOff();
   PH->p_vaddr = From->getVA();
   PH->p_paddr = From->getVA();
   PH->p_filesz = From->getSize();
   PH->p_memsz = From->getSize();
   PH->p_align = From->getAlign();
 }
 
 template <class ELFT> void Writer<ELFT>::buildSectionMap() {
   for (const std::pair<StringRef, std::vector<StringRef>> &OutSec :
        Config->OutputSections)
     for (StringRef Name : OutSec.second)
       InputToOutputSection[Name] = OutSec.first;
 }
 
 template void elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
 template void elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
 template void elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
 template void elf2::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab);


More information about the llvm-commits mailing list