diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:05:49 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:05:49 +0000 | 
| commit | e2fd426bdafe9f5c10066d3926ece6e342184a67 (patch) | |
| tree | bfbbb5fd38554e6b8988b7a217e9fd0623728d7d /ELF/SyntheticSections.cpp | |
| parent | 84c4061b34e048f47e5eb4fbabc1558495e8157c (diff) | |
Notes
Diffstat (limited to 'ELF/SyntheticSections.cpp')
| -rw-r--r-- | ELF/SyntheticSections.cpp | 506 | 
1 files changed, 291 insertions, 215 deletions
| diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp index ae02434572c2a..f459c1b6b4792 100644 --- a/ELF/SyntheticSections.cpp +++ b/ELF/SyntheticSections.cpp @@ -30,10 +30,11 @@  #include "lld/Common/Threads.h"  #include "lld/Common/Version.h"  #include "llvm/ADT/SetOperations.h" +#include "llvm/ADT/StringExtras.h"  #include "llvm/BinaryFormat/Dwarf.h"  #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" -#include "llvm/Object/Decompressor.h"  #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Support/Compression.h"  #include "llvm/Support/Endian.h"  #include "llvm/Support/LEB128.h"  #include "llvm/Support/MD5.h" @@ -104,7 +105,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {      Create = true;      std::string Filename = toString(Sec->File); -    const size_t Size = Sec->Data.size(); +    const size_t Size = Sec->data().size();      // Older version of BFD (such as the default FreeBSD linker) concatenate      // .MIPS.abiflags instead of merging. To allow for this case (or potential      // zero padding) we ignore everything after the first Elf_Mips_ABIFlags @@ -113,7 +114,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {              Twine(Size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags)));        return nullptr;      } -    auto *S = reinterpret_cast<const Elf_Mips_ABIFlags *>(Sec->Data.data()); +    auto *S = reinterpret_cast<const Elf_Mips_ABIFlags *>(Sec->data().data());      if (S->version != 0) {        error(Filename + ": unexpected .MIPS.abiflags version " +              Twine(S->version)); @@ -153,7 +154,7 @@ template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *Buf) {    Options->size = getSize();    if (!Config->Relocatable) -    Reginfo.ri_gp_value = InX::MipsGot->getGp(); +    Reginfo.ri_gp_value = In.MipsGot->getGp();    memcpy(Buf + sizeof(Elf_Mips_Options), &Reginfo, sizeof(Reginfo));  } @@ -176,7 +177,7 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {      Sec->Live = false;      std::string Filename = toString(Sec->File); -    ArrayRef<uint8_t> D = Sec->Data; +    ArrayRef<uint8_t> D = Sec->data();      while (!D.empty()) {        if (D.size() < sizeof(Elf_Mips_Options)) { @@ -210,7 +211,7 @@ MipsReginfoSection<ELFT>::MipsReginfoSection(Elf_Mips_RegInfo Reginfo)  template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *Buf) {    if (!Config->Relocatable) -    Reginfo.ri_gp_value = InX::MipsGot->getGp(); +    Reginfo.ri_gp_value = In.MipsGot->getGp();    memcpy(Buf, &Reginfo, sizeof(Reginfo));  } @@ -232,12 +233,12 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() {    for (InputSectionBase *Sec : Sections) {      Sec->Live = false; -    if (Sec->Data.size() != sizeof(Elf_Mips_RegInfo)) { +    if (Sec->data().size() != sizeof(Elf_Mips_RegInfo)) {        error(toString(Sec->File) + ": invalid size of .reginfo section");        return nullptr;      } -    auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->Data.data()); +    auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->data().data());      Reginfo.ri_gprmask |= R->ri_gprmask;      Sec->getFile<ELFT>()->MipsGp0 = R->ri_gp_value;    }; @@ -260,8 +261,8 @@ Defined *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,                                  uint64_t Size, InputSectionBase &Section) {    auto *S = make<Defined>(Section.File, Name, STB_LOCAL, STV_DEFAULT, Type,                            Value, Size, &Section); -  if (InX::SymTab) -    InX::SymTab->addSymbol(S); +  if (In.SymTab) +    In.SymTab->addSymbol(S);    return S;  } @@ -502,7 +503,7 @@ std::vector<EhFrameSection::FdeData> EhFrameSection::getFdeData() const {    uint8_t *Buf = getParent()->Loc + OutSecOff;    std::vector<FdeData> Ret; -  uint64_t VA = InX::EhFrameHdr->getVA(); +  uint64_t VA = In.EhFrameHdr->getVA();    for (CieRecord *Rec : CieRecords) {      uint8_t Enc = getFdeEncoding(Rec->Cie);      for (EhSectionPiece *Fde : Rec->Fdes) { @@ -937,7 +938,7 @@ template <class ELFT> void MipsGotSection::build() {        Symbol *S = P.first;        uint64_t Offset = P.second * Config->Wordsize;        if (S->IsPreemptible) -        InX::RelaDyn->addReloc(Target->TlsGotRel, this, Offset, S); +        In.RelaDyn->addReloc(Target->TlsGotRel, this, Offset, S);      }      for (std::pair<Symbol *, size_t> &P : Got.DynTlsSymbols) {        Symbol *S = P.first; @@ -945,7 +946,7 @@ template <class ELFT> void MipsGotSection::build() {        if (S == nullptr) {          if (!Config->Pic)            continue; -        InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S); +        In.RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S);        } else {          // When building a shared library we still need a dynamic relocation          // for the module index. Therefore only checking for @@ -953,13 +954,13 @@ template <class ELFT> void MipsGotSection::build() {          // thread-locals that have been marked as local through a linker script)          if (!S->IsPreemptible && !Config->Pic)            continue; -        InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S); +        In.RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S);          // However, we can skip writing the TLS offset reloc for non-preemptible          // symbols since it is known even in shared libraries          if (!S->IsPreemptible)            continue;          Offset += Config->Wordsize; -        InX::RelaDyn->addReloc(Target->TlsOffsetRel, this, Offset, S); +        In.RelaDyn->addReloc(Target->TlsOffsetRel, this, Offset, S);        }      } @@ -971,7 +972,7 @@ template <class ELFT> void MipsGotSection::build() {      // Dynamic relocations for "global" entries.      for (const std::pair<Symbol *, size_t> &P : Got.Global) {        uint64_t Offset = P.second * Config->Wordsize; -      InX::RelaDyn->addReloc(Target->RelativeRel, this, Offset, P.first); +      In.RelaDyn->addReloc(Target->RelativeRel, this, Offset, P.first);      }      if (!Config->Pic)        continue; @@ -981,14 +982,14 @@ template <class ELFT> void MipsGotSection::build() {        size_t PageCount = L.second.Count;        for (size_t PI = 0; PI < PageCount; ++PI) {          uint64_t Offset = (L.second.FirstIndex + PI) * Config->Wordsize; -        InX::RelaDyn->addReloc({Target->RelativeRel, this, Offset, L.first, -                                int64_t(PI * 0x10000)}); +        In.RelaDyn->addReloc({Target->RelativeRel, this, Offset, L.first, +                              int64_t(PI * 0x10000)});        }      }      for (const std::pair<GotEntry, size_t> &P : Got.Local16) {        uint64_t Offset = P.second * Config->Wordsize; -      InX::RelaDyn->addReloc({Target->RelativeRel, this, Offset, true, -                              P.first.first, P.first.second}); +      In.RelaDyn->addReloc({Target->RelativeRel, this, Offset, true, +                            P.first.first, P.first.second});      }    }  } @@ -1200,21 +1201,21 @@ DynamicSection<ELFT>::DynamicSection()    // Add strings to .dynstr early so that .dynstr's size will be    // fixed early.    for (StringRef S : Config->FilterList) -    addInt(DT_FILTER, InX::DynStrTab->addString(S)); +    addInt(DT_FILTER, In.DynStrTab->addString(S));    for (StringRef S : Config->AuxiliaryList) -    addInt(DT_AUXILIARY, InX::DynStrTab->addString(S)); +    addInt(DT_AUXILIARY, In.DynStrTab->addString(S));    if (!Config->Rpath.empty())      addInt(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, -           InX::DynStrTab->addString(Config->Rpath)); +           In.DynStrTab->addString(Config->Rpath));    for (InputFile *File : SharedFiles) {      SharedFile<ELFT> *F = cast<SharedFile<ELFT>>(File);      if (F->IsNeeded) -      addInt(DT_NEEDED, InX::DynStrTab->addString(F->SoName)); +      addInt(DT_NEEDED, In.DynStrTab->addString(F->SoName));    }    if (!Config->SoName.empty()) -    addInt(DT_SONAME, InX::DynStrTab->addString(Config->SoName)); +    addInt(DT_SONAME, In.DynStrTab->addString(Config->SoName));  }  template <class ELFT> @@ -1254,18 +1255,33 @@ void DynamicSection<ELFT>::addSym(int32_t Tag, Symbol *Sym) {    Entries.push_back({Tag, [=] { return Sym->getVA(); }});  } +// A Linker script may assign the RELA relocation sections to the same +// output section. When this occurs we cannot just use the OutputSection +// Size. Moreover the [DT_JMPREL, DT_JMPREL + DT_PLTRELSZ) is permitted to +// overlap with the [DT_RELA, DT_RELA + DT_RELASZ). +static uint64_t addPltRelSz() { +  size_t Size = In.RelaPlt->getSize(); +  if (In.RelaIplt->getParent() == In.RelaPlt->getParent() && +      In.RelaIplt->Name == In.RelaPlt->Name) +    Size += In.RelaIplt->getSize(); +  return Size; +} +  // Add remaining entries to complete .dynamic contents.  template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { -  if (this->Size) -    return; // Already finalized. -    // Set DT_FLAGS and DT_FLAGS_1.    uint32_t DtFlags = 0;    uint32_t DtFlags1 = 0;    if (Config->Bsymbolic)      DtFlags |= DF_SYMBOLIC; +  if (Config->ZGlobal) +    DtFlags1 |= DF_1_GLOBAL;    if (Config->ZInitfirst)      DtFlags1 |= DF_1_INITFIRST; +  if (Config->ZInterpose) +    DtFlags1 |= DF_1_INTERPOSE; +  if (Config->ZNodefaultlib) +    DtFlags1 |= DF_1_NODEFLIB;    if (Config->ZNodelete)      DtFlags1 |= DF_1_NODELETE;    if (Config->ZNodlopen) @@ -1297,10 +1313,12 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {    if (!Config->Shared && !Config->Relocatable && !Config->ZRodynamic)      addInt(DT_DEBUG, 0); -  this->Link = InX::DynStrTab->getParent()->SectionIndex; -  if (!InX::RelaDyn->empty()) { -    addInSec(InX::RelaDyn->DynamicTag, InX::RelaDyn); -    addSize(InX::RelaDyn->SizeDynamicTag, InX::RelaDyn->getParent()); +  if (OutputSection *Sec = In.DynStrTab->getParent()) +    this->Link = Sec->SectionIndex; + +  if (!In.RelaDyn->empty()) { +    addInSec(In.RelaDyn->DynamicTag, In.RelaDyn); +    addSize(In.RelaDyn->SizeDynamicTag, In.RelaDyn->getParent());      bool IsRela = Config->IsRela;      addInt(IsRela ? DT_RELAENT : DT_RELENT, @@ -1310,16 +1328,16 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {      // The problem is in the tight relation between dynamic      // relocations and GOT. So do not emit this tag on MIPS.      if (Config->EMachine != EM_MIPS) { -      size_t NumRelativeRels = InX::RelaDyn->getRelativeRelocCount(); +      size_t NumRelativeRels = In.RelaDyn->getRelativeRelocCount();        if (Config->ZCombreloc && NumRelativeRels)          addInt(IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels);      }    } -  if (InX::RelrDyn && !InX::RelrDyn->Relocs.empty()) { +  if (In.RelrDyn && !In.RelrDyn->Relocs.empty()) {      addInSec(Config->UseAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR, -             InX::RelrDyn); +             In.RelrDyn);      addSize(Config->UseAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ, -            InX::RelrDyn->getParent()); +            In.RelrDyn->getParent());      addInt(Config->UseAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT,             sizeof(Elf_Relr));    } @@ -1329,33 +1347,33 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {    // as RelaIplt have. And we still want to emit proper dynamic tags for that    // case, so here we always use RelaPlt as marker for the begining of    // .rel[a].plt section. -  if (InX::RelaPlt->getParent()->Live) { -    addInSec(DT_JMPREL, InX::RelaPlt); -    addSize(DT_PLTRELSZ, InX::RelaPlt->getParent()); +  if (In.RelaPlt->getParent()->Live) { +    addInSec(DT_JMPREL, In.RelaPlt); +    Entries.push_back({DT_PLTRELSZ, addPltRelSz});      switch (Config->EMachine) {      case EM_MIPS: -      addInSec(DT_MIPS_PLTGOT, InX::GotPlt); +      addInSec(DT_MIPS_PLTGOT, In.GotPlt);        break;      case EM_SPARCV9: -      addInSec(DT_PLTGOT, InX::Plt); +      addInSec(DT_PLTGOT, In.Plt);        break;      default: -      addInSec(DT_PLTGOT, InX::GotPlt); +      addInSec(DT_PLTGOT, In.GotPlt);        break;      }      addInt(DT_PLTREL, Config->IsRela ? DT_RELA : DT_REL);    } -  addInSec(DT_SYMTAB, InX::DynSymTab); +  addInSec(DT_SYMTAB, In.DynSymTab);    addInt(DT_SYMENT, sizeof(Elf_Sym)); -  addInSec(DT_STRTAB, InX::DynStrTab); -  addInt(DT_STRSZ, InX::DynStrTab->getSize()); +  addInSec(DT_STRTAB, In.DynStrTab); +  addInt(DT_STRSZ, In.DynStrTab->getSize());    if (!Config->ZText)      addInt(DT_TEXTREL, 0); -  if (InX::GnuHashTab) -    addInSec(DT_GNU_HASH, InX::GnuHashTab); -  if (InX::HashTab) -    addInSec(DT_HASH, InX::HashTab); +  if (In.GnuHashTab) +    addInSec(DT_GNU_HASH, In.GnuHashTab); +  if (In.HashTab) +    addInSec(DT_HASH, In.HashTab);    if (Out::PreinitArray) {      addOutSec(DT_PREINIT_ARRAY, Out::PreinitArray); @@ -1377,47 +1395,47 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {      if (B->isDefined())        addSym(DT_FINI, B); -  bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0; -  if (HasVerNeed || In<ELFT>::VerDef) -    addInSec(DT_VERSYM, In<ELFT>::VerSym); -  if (In<ELFT>::VerDef) { -    addInSec(DT_VERDEF, In<ELFT>::VerDef); +  bool HasVerNeed = InX<ELFT>::VerNeed->getNeedNum() != 0; +  if (HasVerNeed || In.VerDef) +    addInSec(DT_VERSYM, InX<ELFT>::VerSym); +  if (In.VerDef) { +    addInSec(DT_VERDEF, In.VerDef);      addInt(DT_VERDEFNUM, getVerDefNum());    }    if (HasVerNeed) { -    addInSec(DT_VERNEED, In<ELFT>::VerNeed); -    addInt(DT_VERNEEDNUM, In<ELFT>::VerNeed->getNeedNum()); +    addInSec(DT_VERNEED, InX<ELFT>::VerNeed); +    addInt(DT_VERNEEDNUM, InX<ELFT>::VerNeed->getNeedNum());    }    if (Config->EMachine == EM_MIPS) {      addInt(DT_MIPS_RLD_VERSION, 1);      addInt(DT_MIPS_FLAGS, RHF_NOTPOT);      addInt(DT_MIPS_BASE_ADDRESS, Target->getImageBase()); -    addInt(DT_MIPS_SYMTABNO, InX::DynSymTab->getNumSymbols()); +    addInt(DT_MIPS_SYMTABNO, In.DynSymTab->getNumSymbols()); -    add(DT_MIPS_LOCAL_GOTNO, [] { return InX::MipsGot->getLocalEntriesNum(); }); +    add(DT_MIPS_LOCAL_GOTNO, [] { return In.MipsGot->getLocalEntriesNum(); }); -    if (const Symbol *B = InX::MipsGot->getFirstGlobalEntry()) +    if (const Symbol *B = In.MipsGot->getFirstGlobalEntry())        addInt(DT_MIPS_GOTSYM, B->DynsymIndex);      else -      addInt(DT_MIPS_GOTSYM, InX::DynSymTab->getNumSymbols()); -    addInSec(DT_PLTGOT, InX::MipsGot); -    if (InX::MipsRldMap) { +      addInt(DT_MIPS_GOTSYM, In.DynSymTab->getNumSymbols()); +    addInSec(DT_PLTGOT, In.MipsGot); +    if (In.MipsRldMap) {        if (!Config->Pie) -        addInSec(DT_MIPS_RLD_MAP, InX::MipsRldMap); +        addInSec(DT_MIPS_RLD_MAP, In.MipsRldMap);        // Store the offset to the .rld_map section        // relative to the address of the tag. -      addInSecRelative(DT_MIPS_RLD_MAP_REL, InX::MipsRldMap); +      addInSecRelative(DT_MIPS_RLD_MAP_REL, In.MipsRldMap);      }    }    // Glink dynamic tag is required by the V2 abi if the plt section isn't empty. -  if (Config->EMachine == EM_PPC64 && !InX::Plt->empty()) { +  if (Config->EMachine == EM_PPC64 && !In.Plt->empty()) {      // The Glink tag points to 32 bytes before the first lazy symbol resolution      // stub, which starts directly after the header.      Entries.push_back({DT_PPC64_GLINK, [=] {                           unsigned Offset = Target->PltHeaderSize - 32; -                         return InX::Plt->getVA(0) + Offset; +                         return In.Plt->getVA(0) + Offset;                         }});    } @@ -1486,13 +1504,17 @@ void RelocationBaseSection::addReloc(const DynamicReloc &Reloc) {  }  void RelocationBaseSection::finalizeContents() { -  // If all relocations are R_*_RELATIVE they don't refer to any -  // dynamic symbol and we don't need a dynamic symbol table. If that -  // is the case, just use 0 as the link. -  Link = InX::DynSymTab ? InX::DynSymTab->getParent()->SectionIndex : 0; +  // When linking glibc statically, .rel{,a}.plt contains R_*_IRELATIVE +  // relocations due to IFUNC (e.g. strcpy). sh_link will be set to 0 in that +  // case. +  InputSection *SymTab = Config->Relocatable ? In.SymTab : In.DynSymTab; +  if (SymTab && SymTab->getParent()) +    getParent()->Link = SymTab->getParent()->SectionIndex; +  else +    getParent()->Link = 0; -  // Set required output section properties. -  getParent()->Link = Link; +  if (In.RelaIplt == this || In.RelaPlt == this) +    getParent()->Info = In.GotPlt->getParent()->SectionIndex;  }  RelrBaseSection::RelrBaseSection() @@ -1621,10 +1643,9 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {        NonRelatives.push_back(R);    } -  llvm::sort(Relatives.begin(), Relatives.end(), -             [](const Elf_Rel &A, const Elf_Rel &B) { -               return A.r_offset < B.r_offset; -             }); +  llvm::sort(Relatives, [](const Elf_Rel &A, const Elf_Rel &B) { +    return A.r_offset < B.r_offset; +  });    // Try to find groups of relative relocations which are spaced one word    // apart from one another. These generally correspond to vtable entries. The @@ -1702,10 +1723,9 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {    }    // Finally the non-relative relocations. -  llvm::sort(NonRelatives.begin(), NonRelatives.end(), -             [](const Elf_Rela &A, const Elf_Rela &B) { -               return A.r_offset < B.r_offset; -             }); +  llvm::sort(NonRelatives, [](const Elf_Rela &A, const Elf_Rela &B) { +    return A.r_offset < B.r_offset; +  });    if (!NonRelatives.empty()) {      Add(NonRelatives.size());      Add(HasAddendIfRela); @@ -1720,6 +1740,11 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {      }    } +  // Don't allow the section to shrink; otherwise the size of the section can +  // oscillate infinitely. +  if (RelocData.size() < OldSize) +    RelocData.append(OldSize - RelocData.size(), 0); +    // Returns whether the section size changed. We need to keep recomputing both    // section layout and the contents of this section until the size converges    // because changing this section's size can affect section layout, which in @@ -1843,10 +1868,13 @@ static bool sortMipsSymbols(const SymbolTableEntry &L,  }  void SymbolTableBaseSection::finalizeContents() { -  getParent()->Link = StrTabSec.getParent()->SectionIndex; +  if (OutputSection *Sec = StrTabSec.getParent()) +    getParent()->Link = Sec->SectionIndex; -  if (this->Type != SHT_DYNSYM) +  if (this->Type != SHT_DYNSYM) { +    sortSymTabSymbols();      return; +  }    // If it is a .dynsym, there should be no local symbols, but we need    // to do a few things for the dynamic linker. @@ -1855,9 +1883,9 @@ void SymbolTableBaseSection::finalizeContents() {    // Because the first symbol entry is a null entry, 1 is the first.    getParent()->Info = 1; -  if (InX::GnuHashTab) { +  if (In.GnuHashTab) {      // NB: It also sorts Symbols to meet the GNU hash table requirements. -    InX::GnuHashTab->addSymbols(Symbols); +    In.GnuHashTab->addSymbols(Symbols);    } else if (Config->EMachine == EM_MIPS) {      std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols);    } @@ -1874,9 +1902,7 @@ void SymbolTableBaseSection::finalizeContents() {  // Aside from above, we put local symbols in groups starting with the STT_FILE  // symbol. That is convenient for purpose of identifying where are local symbols  // coming from. -void SymbolTableBaseSection::postThunkContents() { -  assert(this->Type == SHT_SYMTAB); - +void SymbolTableBaseSection::sortSymTabSymbols() {    // Move all local symbols before global symbols.    auto E = std::stable_partition(        Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) { @@ -1948,7 +1974,8 @@ static uint32_t getSymSectionIndex(Symbol *Sym) {    if (!isa<Defined>(Sym) || Sym->NeedsPltAddr)      return SHN_UNDEF;    if (const OutputSection *OS = Sym->getOutputSection()) -    return OS->SectionIndex >= SHN_LORESERVE ? SHN_XINDEX : OS->SectionIndex; +    return OS->SectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX +                                             : OS->SectionIndex;    return SHN_ABS;  } @@ -2038,7 +2065,7 @@ void SymtabShndxSection::writeTo(uint8_t *Buf) {    // with an entry in .symtab. If the corresponding entry contains SHN_XINDEX,    // we need to write actual index, otherwise, we must write SHN_UNDEF(0).    Buf += 4; // Ignore .symtab[0] entry. -  for (const SymbolTableEntry &Entry : InX::SymTab->getSymbols()) { +  for (const SymbolTableEntry &Entry : In.SymTab->getSymbols()) {      if (getSymSectionIndex(Entry.Sym) == SHN_XINDEX)        write32(Buf, Entry.Sym->getOutputSection()->SectionIndex);      Buf += 4; @@ -2059,11 +2086,11 @@ bool SymtabShndxSection::empty() const {  }  void SymtabShndxSection::finalizeContents() { -  getParent()->Link = InX::SymTab->getParent()->SectionIndex; +  getParent()->Link = In.SymTab->getParent()->SectionIndex;  }  size_t SymtabShndxSection::getSize() const { -  return InX::SymTab->getNumSymbols() * 4; +  return In.SymTab->getNumSymbols() * 4;  }  // .hash and .gnu.hash sections contain on-disk hash tables that map @@ -2102,7 +2129,8 @@ GnuHashTableSection::GnuHashTableSection()  }  void GnuHashTableSection::finalizeContents() { -  getParent()->Link = InX::DynSymTab->getParent()->SectionIndex; +  if (OutputSection *Sec = In.DynSymTab->getParent()) +    getParent()->Link = Sec->SectionIndex;    // Computes bloom filter size in word size. We want to allocate 12    // bits for each symbol. It must be a power of two. @@ -2127,7 +2155,7 @@ void GnuHashTableSection::writeTo(uint8_t *Buf) {    // Write a header.    write32(Buf, NBuckets); -  write32(Buf + 4, InX::DynSymTab->getNumSymbols() - Symbols.size()); +  write32(Buf + 4, In.DynSymTab->getNumSymbols() - Symbols.size());    write32(Buf + 8, MaskWords);    write32(Buf + 12, Shift2);    Buf += 16; @@ -2148,6 +2176,8 @@ void GnuHashTableSection::writeTo(uint8_t *Buf) {  void GnuHashTableSection::writeBloomFilter(uint8_t *Buf) {    unsigned C = Config->Is64 ? 64 : 32;    for (const Entry &Sym : Symbols) { +    // When C = 64, we choose a word with bits [6:...] and set 1 to two bits in +    // the word using bits [0:5] and [26:31].      size_t I = (Sym.Hash / C) & (MaskWords - 1);      uint64_t Val = readUint(Buf + I * Config->Wordsize);      Val |= uint64_t(1) << (Sym.Hash % C); @@ -2232,13 +2262,14 @@ HashTableSection::HashTableSection()  }  void HashTableSection::finalizeContents() { -  getParent()->Link = InX::DynSymTab->getParent()->SectionIndex; +  if (OutputSection *Sec = In.DynSymTab->getParent()) +    getParent()->Link = Sec->SectionIndex;    unsigned NumEntries = 2;                       // nbucket and nchain. -  NumEntries += InX::DynSymTab->getNumSymbols(); // The chain entries. +  NumEntries += In.DynSymTab->getNumSymbols();   // The chain entries.    // Create as many buckets as there are symbols. -  NumEntries += InX::DynSymTab->getNumSymbols(); +  NumEntries += In.DynSymTab->getNumSymbols();    this->Size = NumEntries * 4;  } @@ -2246,7 +2277,7 @@ void HashTableSection::writeTo(uint8_t *Buf) {    // See comment in GnuHashTableSection::writeTo.    memset(Buf, 0, Size); -  unsigned NumSymbols = InX::DynSymTab->getNumSymbols(); +  unsigned NumSymbols = In.DynSymTab->getNumSymbols();    uint32_t *P = reinterpret_cast<uint32_t *>(Buf);    write32(P++, NumSymbols); // nbucket @@ -2255,7 +2286,7 @@ void HashTableSection::writeTo(uint8_t *Buf) {    uint32_t *Buckets = P;    uint32_t *Chains = P + NumSymbols; -  for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) { +  for (const SymbolTableEntry &S : In.DynSymTab->getSymbols()) {      Symbol *Sym = S.Sym;      StringRef Name = Sym->getName();      unsigned I = Sym->DynsymIndex; @@ -2270,7 +2301,8 @@ void HashTableSection::writeTo(uint8_t *Buf) {  PltSection::PltSection(bool IsIplt)      : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16,                         Config->EMachine == EM_PPC64 ? ".glink" : ".plt"), -      HeaderSize(IsIplt ? 0 : Target->PltHeaderSize), IsIplt(IsIplt) { +      HeaderSize(!IsIplt || Config->ZRetpolineplt ? Target->PltHeaderSize : 0), +      IsIplt(IsIplt) {    // The PLT needs to be writable on SPARC as the dynamic linker will    // modify the instructions in the PLT entries.    if (Config->EMachine == EM_SPARCV9) @@ -2278,9 +2310,9 @@ PltSection::PltSection(bool IsIplt)  }  void PltSection::writeTo(uint8_t *Buf) { -  // At beginning of PLT but not the IPLT, we have code to call the dynamic +  // At beginning of PLT or retpoline IPLT, we have code to call the dynamic    // linker to resolve dynsyms at runtime. Write such code. -  if (!IsIplt) +  if (HeaderSize > 0)      Target->writePltHeader(Buf);    size_t Off = HeaderSize;    // The IPlt is immediately after the Plt, account for this in RelOff @@ -2298,9 +2330,9 @@ void PltSection::writeTo(uint8_t *Buf) {  template <class ELFT> void PltSection::addEntry(Symbol &Sym) {    Sym.PltIndex = Entries.size(); -  RelocationBaseSection *PltRelocSection = InX::RelaPlt; +  RelocationBaseSection *PltRelocSection = In.RelaPlt;    if (IsIplt) { -    PltRelocSection = InX::RelaIplt; +    PltRelocSection = In.RelaIplt;      Sym.IsInIplt = true;    }    unsigned RelOff = @@ -2326,14 +2358,14 @@ void PltSection::addSymbols() {  }  unsigned PltSection::getPltRelocOff() const { -  return IsIplt ? InX::Plt->getSize() : 0; +  return IsIplt ? In.Plt->getSize() : 0;  }  // The string hash function for .gdb_index.  static uint32_t computeGdbHash(StringRef S) {    uint32_t H = 0;    for (uint8_t C : S) -    H = H * 67 + tolower(C) - 113; +    H = H * 67 + toLower(C) - 113;    return H;  } @@ -2371,7 +2403,7 @@ static std::vector<InputSection *> getDebugInfoSections() {  static std::vector<GdbIndexSection::CuEntry> readCuList(DWARFContext &Dwarf) {    std::vector<GdbIndexSection::CuEntry> Ret; -  for (std::unique_ptr<DWARFCompileUnit> &Cu : Dwarf.compile_units()) +  for (std::unique_ptr<DWARFUnit> &Cu : Dwarf.compile_units())      Ret.push_back({Cu->getOffset(), Cu->getLength() + 4});    return Ret;  } @@ -2381,12 +2413,15 @@ readAddressAreas(DWARFContext &Dwarf, InputSection *Sec) {    std::vector<GdbIndexSection::AddressEntry> Ret;    uint32_t CuIdx = 0; -  for (std::unique_ptr<DWARFCompileUnit> &Cu : Dwarf.compile_units()) { -    DWARFAddressRangesVector Ranges; -    Cu->collectAddressRanges(Ranges); +  for (std::unique_ptr<DWARFUnit> &Cu : Dwarf.compile_units()) { +    Expected<DWARFAddressRangesVector> Ranges = Cu->collectAddressRanges(); +    if (!Ranges) { +      error(toString(Sec) + ": " + toString(Ranges.takeError())); +      return {}; +    }      ArrayRef<InputSectionBase *> Sections = Sec->File->getSections(); -    for (DWARFAddressRange &R : Ranges) { +    for (DWARFAddressRange &R : *Ranges) {        InputSectionBase *S = Sections[R.SectionIndex];        if (!S || S == &InputSection::Discarded || !S->Live)          continue; @@ -2399,21 +2434,35 @@ readAddressAreas(DWARFContext &Dwarf, InputSection *Sec) {      }      ++CuIdx;    } +    return Ret;  } -static std::vector<GdbIndexSection::NameTypeEntry> -readPubNamesAndTypes(DWARFContext &Dwarf, uint32_t Idx) { -  StringRef Sec1 = Dwarf.getDWARFObj().getGnuPubNamesSection(); -  StringRef Sec2 = Dwarf.getDWARFObj().getGnuPubTypesSection(); - -  std::vector<GdbIndexSection::NameTypeEntry> Ret; -  for (StringRef Sec : {Sec1, Sec2}) { -    DWARFDebugPubTable Table(Sec, Config->IsLE, true); -    for (const DWARFDebugPubTable::Set &Set : Table.getData()) +template <class ELFT> +static std::vector<GdbIndexSection::NameAttrEntry> +readPubNamesAndTypes(const LLDDwarfObj<ELFT> &Obj, +                     const std::vector<GdbIndexSection::CuEntry> &CUs) { +  const DWARFSection &PubNames = Obj.getGnuPubNamesSection(); +  const DWARFSection &PubTypes = Obj.getGnuPubTypesSection(); + +  std::vector<GdbIndexSection::NameAttrEntry> Ret; +  for (const DWARFSection *Pub : {&PubNames, &PubTypes}) { +    DWARFDebugPubTable Table(Obj, *Pub, Config->IsLE, true); +    for (const DWARFDebugPubTable::Set &Set : Table.getData()) { +      // The value written into the constant pool is Kind << 24 | CuIndex. As we +      // don't know how many compilation units precede this object to compute +      // CuIndex, we compute (Kind << 24 | CuIndexInThisObject) instead, and add +      // the number of preceding compilation units later. +      uint32_t I = +          lower_bound(CUs, Set.Offset, +                      [](GdbIndexSection::CuEntry CU, uint32_t Offset) { +                        return CU.CuOffset < Offset; +                      }) - +          CUs.begin();        for (const DWARFDebugPubTable::Entry &Ent : Set.Entries)          Ret.push_back({{Ent.Name, computeGdbHash(Ent.Name)}, -                       (Ent.Descriptor.toBits() << 24) | Idx}); +                       (Ent.Descriptor.toBits() << 24) | I}); +    }    }    return Ret;  } @@ -2421,9 +2470,18 @@ readPubNamesAndTypes(DWARFContext &Dwarf, uint32_t Idx) {  // Create a list of symbols from a given list of symbol names and types  // by uniquifying them by name.  static std::vector<GdbIndexSection::GdbSymbol> -createSymbols(ArrayRef<std::vector<GdbIndexSection::NameTypeEntry>> NameTypes) { +createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> NameAttrs, +              const std::vector<GdbIndexSection::GdbChunk> &Chunks) {    typedef GdbIndexSection::GdbSymbol GdbSymbol; -  typedef GdbIndexSection::NameTypeEntry NameTypeEntry; +  typedef GdbIndexSection::NameAttrEntry NameAttrEntry; + +  // For each chunk, compute the number of compilation units preceding it. +  uint32_t CuIdx = 0; +  std::vector<uint32_t> CuIdxs(Chunks.size()); +  for (uint32_t I = 0, E = Chunks.size(); I != E; ++I) { +    CuIdxs[I] = CuIdx; +    CuIdx += Chunks[I].CompilationUnits.size(); +  }    // The number of symbols we will handle in this function is of the order    // of millions for very large executables, so we use multi-threading to @@ -2441,21 +2499,24 @@ createSymbols(ArrayRef<std::vector<GdbIndexSection::NameTypeEntry>> NameTypes) {    // Instantiate GdbSymbols while uniqufying them by name.    std::vector<std::vector<GdbSymbol>> Symbols(NumShards);    parallelForEachN(0, Concurrency, [&](size_t ThreadId) { -    for (ArrayRef<NameTypeEntry> Entries : NameTypes) { -      for (const NameTypeEntry &Ent : Entries) { +    uint32_t I = 0; +    for (ArrayRef<NameAttrEntry> Entries : NameAttrs) { +      for (const NameAttrEntry &Ent : Entries) {          size_t ShardId = Ent.Name.hash() >> Shift;          if ((ShardId & (Concurrency - 1)) != ThreadId)            continue; +        uint32_t V = Ent.CuIndexAndAttrs + CuIdxs[I];          size_t &Idx = Map[ShardId][Ent.Name];          if (Idx) { -          Symbols[ShardId][Idx - 1].CuVector.push_back(Ent.Type); +          Symbols[ShardId][Idx - 1].CuVector.push_back(V);            continue;          }          Idx = Symbols[ShardId].size() + 1; -        Symbols[ShardId].push_back({Ent.Name, {Ent.Type}, 0, 0}); +        Symbols[ShardId].push_back({Ent.Name, {V}, 0, 0});        } +      ++I;      }    }); @@ -2498,7 +2559,7 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() {        S->Live = false;    std::vector<GdbChunk> Chunks(Sections.size()); -  std::vector<std::vector<NameTypeEntry>> NameTypes(Sections.size()); +  std::vector<std::vector<NameAttrEntry>> NameAttrs(Sections.size());    parallelForEachN(0, Sections.size(), [&](size_t I) {      ObjFile<ELFT> *File = Sections[I]->getFile<ELFT>(); @@ -2507,12 +2568,14 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() {      Chunks[I].Sec = Sections[I];      Chunks[I].CompilationUnits = readCuList(Dwarf);      Chunks[I].AddressAreas = readAddressAreas(Dwarf, Sections[I]); -    NameTypes[I] = readPubNamesAndTypes(Dwarf, I); +    NameAttrs[I] = readPubNamesAndTypes<ELFT>( +        static_cast<const LLDDwarfObj<ELFT> &>(Dwarf.getDWARFObj()), +        Chunks[I].CompilationUnits);    });    auto *Ret = make<GdbIndexSection>();    Ret->Chunks = std::move(Chunks); -  Ret->Symbols = createSymbols(NameTypes); +  Ret->Symbols = createSymbols(NameAttrs, Ret->Chunks);    Ret->initOutputSize();    return Ret;  } @@ -2570,8 +2633,9 @@ void GdbIndexSection::writeTo(uint8_t *Buf) {    // Write the string pool.    Hdr->ConstantPoolOff = Buf - Start; -  for (GdbSymbol &Sym : Symbols) +  parallelForEach(Symbols, [&](GdbSymbol &Sym) {      memcpy(Buf + Sym.NameOff, Sym.Name.data(), Sym.Name.size()); +  });    // Write the CU vectors.    for (GdbSymbol &Sym : Symbols) { @@ -2584,7 +2648,7 @@ void GdbIndexSection::writeTo(uint8_t *Buf) {    }  } -bool GdbIndexSection::empty() const { return !Out::DebugInfo; } +bool GdbIndexSection::empty() const { return Chunks.empty(); }  EhFrameHeader::EhFrameHeader()      : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".eh_frame_hdr") {} @@ -2596,13 +2660,13 @@ EhFrameHeader::EhFrameHeader()  void EhFrameHeader::writeTo(uint8_t *Buf) {    typedef EhFrameSection::FdeData FdeData; -  std::vector<FdeData> Fdes = InX::EhFrame->getFdeData(); +  std::vector<FdeData> Fdes = In.EhFrame->getFdeData();    Buf[0] = 1;    Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;    Buf[2] = DW_EH_PE_udata4;    Buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; -  write32(Buf + 4, InX::EhFrame->getParent()->Addr - this->getVA() - 4); +  write32(Buf + 4, In.EhFrame->getParent()->Addr - this->getVA() - 4);    write32(Buf + 8, Fdes.size());    Buf += 12; @@ -2615,13 +2679,12 @@ void EhFrameHeader::writeTo(uint8_t *Buf) {  size_t EhFrameHeader::getSize() const {    // .eh_frame_hdr has a 12 bytes header followed by an array of FDEs. -  return 12 + InX::EhFrame->NumFdes * 8; +  return 12 + In.EhFrame->NumFdes * 8;  } -bool EhFrameHeader::empty() const { return InX::EhFrame->empty(); } +bool EhFrameHeader::empty() const { return In.EhFrame->empty(); } -template <class ELFT> -VersionDefinitionSection<ELFT>::VersionDefinitionSection() +VersionDefinitionSection::VersionDefinitionSection()      : SyntheticSection(SHF_ALLOC, SHT_GNU_verdef, sizeof(uint32_t),                         ".gnu.version_d") {} @@ -2631,12 +2694,13 @@ static StringRef getFileDefName() {    return Config->OutputFile;  } -template <class ELFT> void VersionDefinitionSection<ELFT>::finalizeContents() { -  FileDefNameOff = InX::DynStrTab->addString(getFileDefName()); +void VersionDefinitionSection::finalizeContents() { +  FileDefNameOff = In.DynStrTab->addString(getFileDefName());    for (VersionDefinition &V : Config->VersionDefinitions) -    V.NameOff = InX::DynStrTab->addString(V.Name); +    V.NameOff = In.DynStrTab->addString(V.Name); -  getParent()->Link = InX::DynStrTab->getParent()->SectionIndex; +  if (OutputSection *Sec = In.DynStrTab->getParent()) +    getParent()->Link = Sec->SectionIndex;    // sh_info should be set to the number of definitions. This fact is missed in    // documentation, but confirmed by binutils community: @@ -2644,68 +2708,68 @@ template <class ELFT> void VersionDefinitionSection<ELFT>::finalizeContents() {    getParent()->Info = getVerDefNum();  } -template <class ELFT> -void VersionDefinitionSection<ELFT>::writeOne(uint8_t *Buf, uint32_t Index, -                                              StringRef Name, size_t NameOff) { -  auto *Verdef = reinterpret_cast<Elf_Verdef *>(Buf); -  Verdef->vd_version = 1; -  Verdef->vd_cnt = 1; -  Verdef->vd_aux = sizeof(Elf_Verdef); -  Verdef->vd_next = sizeof(Elf_Verdef) + sizeof(Elf_Verdaux); -  Verdef->vd_flags = (Index == 1 ? VER_FLG_BASE : 0); -  Verdef->vd_ndx = Index; -  Verdef->vd_hash = hashSysV(Name); - -  auto *Verdaux = reinterpret_cast<Elf_Verdaux *>(Buf + sizeof(Elf_Verdef)); -  Verdaux->vda_name = NameOff; -  Verdaux->vda_next = 0; +void VersionDefinitionSection::writeOne(uint8_t *Buf, uint32_t Index, +                                        StringRef Name, size_t NameOff) { +  uint16_t Flags = Index == 1 ? VER_FLG_BASE : 0; + +  // Write a verdef. +  write16(Buf, 1);                  // vd_version +  write16(Buf + 2, Flags);          // vd_flags +  write16(Buf + 4, Index);          // vd_ndx +  write16(Buf + 6, 1);              // vd_cnt +  write32(Buf + 8, hashSysV(Name)); // vd_hash +  write32(Buf + 12, 20);            // vd_aux +  write32(Buf + 16, 28);            // vd_next + +  // Write a veraux. +  write32(Buf + 20, NameOff); // vda_name +  write32(Buf + 24, 0);       // vda_next  } -template <class ELFT> -void VersionDefinitionSection<ELFT>::writeTo(uint8_t *Buf) { +void VersionDefinitionSection::writeTo(uint8_t *Buf) {    writeOne(Buf, 1, getFileDefName(), FileDefNameOff);    for (VersionDefinition &V : Config->VersionDefinitions) { -    Buf += sizeof(Elf_Verdef) + sizeof(Elf_Verdaux); +    Buf += EntrySize;      writeOne(Buf, V.Id, V.Name, V.NameOff);    }    // Need to terminate the last version definition. -  Elf_Verdef *Verdef = reinterpret_cast<Elf_Verdef *>(Buf); -  Verdef->vd_next = 0; +  write32(Buf + 16, 0); // vd_next  } -template <class ELFT> size_t VersionDefinitionSection<ELFT>::getSize() const { -  return (sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum(); +size_t VersionDefinitionSection::getSize() const { +  return EntrySize * getVerDefNum();  } +// .gnu.version is a table where each entry is 2 byte long.  template <class ELFT>  VersionTableSection<ELFT>::VersionTableSection()      : SyntheticSection(SHF_ALLOC, SHT_GNU_versym, sizeof(uint16_t),                         ".gnu.version") { -  this->Entsize = sizeof(Elf_Versym); +  this->Entsize = 2;  }  template <class ELFT> void VersionTableSection<ELFT>::finalizeContents() {    // At the moment of june 2016 GNU docs does not mention that sh_link field    // should be set, but Sun docs do. Also readelf relies on this field. -  getParent()->Link = InX::DynSymTab->getParent()->SectionIndex; +  getParent()->Link = In.DynSymTab->getParent()->SectionIndex;  }  template <class ELFT> size_t VersionTableSection<ELFT>::getSize() const { -  return sizeof(Elf_Versym) * (InX::DynSymTab->getSymbols().size() + 1); +  return (In.DynSymTab->getSymbols().size() + 1) * 2;  }  template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) { -  auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1; -  for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) { -    OutVersym->vs_index = S.Sym->VersionId; -    ++OutVersym; +  Buf += 2; +  for (const SymbolTableEntry &S : In.DynSymTab->getSymbols()) { +    write16(Buf, S.Sym->VersionId); +    Buf += 2;    }  }  template <class ELFT> bool VersionTableSection<ELFT>::empty() const { -  return !In<ELFT>::VerDef && In<ELFT>::VerNeed->empty(); +  return !In.VerDef && InX<ELFT>::VerNeed->empty();  }  template <class ELFT> @@ -2729,7 +2793,7 @@ template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) {    // to create one by adding it to our needed list and creating a dynstr entry    // for the soname.    if (File.VerdefMap.empty()) -    Needed.push_back({&File, InX::DynStrTab->addString(File.SoName)}); +    Needed.push_back({&File, In.DynStrTab->addString(File.SoName)});    const typename ELFT::Verdef *Ver = File.Verdefs[SS->VerdefIndex];    typename SharedFile<ELFT>::NeededVer &NV = File.VerdefMap[Ver]; @@ -2737,8 +2801,8 @@ template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) {    // prepare to create one by allocating a version identifier and creating a    // dynstr entry for the version name.    if (NV.Index == 0) { -    NV.StrTab = InX::DynStrTab->addString(File.getStringTable().data() + -                                          Ver->getAux()->vda_name); +    NV.StrTab = In.DynStrTab->addString(File.getStringTable().data() + +                                        Ver->getAux()->vda_name);      NV.Index = NextIndex++;    }    SS->VersionId = NV.Index; @@ -2780,7 +2844,8 @@ template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) {  }  template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() { -  getParent()->Link = InX::DynStrTab->getParent()->SectionIndex; +  if (OutputSection *Sec = In.DynStrTab->getParent()) +    getParent()->Link = Sec->SectionIndex;    getParent()->Info = Needed.size();  } @@ -2896,12 +2961,6 @@ static MergeSyntheticSection *createMergeSynthetic(StringRef Name,    return make<MergeNoTailSection>(Name, Type, Flags, Alignment);  } -// Debug sections may be compressed by zlib. Decompress if exists. -void elf::decompressSections() { -  parallelForEach(InputSections, -                  [](InputSectionBase *Sec) { Sec->maybeDecompress(); }); -} -  template <class ELFT> void elf::splitSections() {    // splitIntoPieces needs to be called on each MergeInputSection    // before calling finalizeContents(). @@ -2929,8 +2988,10 @@ void elf::mergeSections() {      // We do not want to handle sections that are not alive, so just remove      // them instead of trying to merge. -    if (!MS->Live) +    if (!MS->Live) { +      S = nullptr;        continue; +    }      StringRef OutsecName = getOutputSectionName(MS);      uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize); @@ -3038,34 +3099,54 @@ bool ThunkSection::assignOffsets() {    return Changed;  } -InputSection *InX::ARMAttributes; -BssSection *InX::Bss; -BssSection *InX::BssRelRo; -BuildIdSection *InX::BuildId; -EhFrameHeader *InX::EhFrameHdr; -EhFrameSection *InX::EhFrame; -SyntheticSection *InX::Dynamic; -StringTableSection *InX::DynStrTab; -SymbolTableBaseSection *InX::DynSymTab; -InputSection *InX::Interp; -GdbIndexSection *InX::GdbIndex; -GotSection *InX::Got; -GotPltSection *InX::GotPlt; -GnuHashTableSection *InX::GnuHashTab; -HashTableSection *InX::HashTab; -IgotPltSection *InX::IgotPlt; -MipsGotSection *InX::MipsGot; -MipsRldMapSection *InX::MipsRldMap; -PltSection *InX::Plt; -PltSection *InX::Iplt; -RelocationBaseSection *InX::RelaDyn; -RelrBaseSection *InX::RelrDyn; -RelocationBaseSection *InX::RelaPlt; -RelocationBaseSection *InX::RelaIplt; -StringTableSection *InX::ShStrTab; -StringTableSection *InX::StrTab; -SymbolTableBaseSection *InX::SymTab; -SymtabShndxSection *InX::SymTabShndx; +// If linking position-dependent code then the table will store the addresses +// directly in the binary so the section has type SHT_PROGBITS. If linking +// position-independent code the section has type SHT_NOBITS since it will be +// allocated and filled in by the dynamic linker. +PPC64LongBranchTargetSection::PPC64LongBranchTargetSection() +    : SyntheticSection(SHF_ALLOC | SHF_WRITE, +                       Config->Pic ? SHT_NOBITS : SHT_PROGBITS, 8, +                       ".branch_lt") {} + +void PPC64LongBranchTargetSection::addEntry(Symbol &Sym) { +  assert(Sym.PPC64BranchltIndex == 0xffff); +  Sym.PPC64BranchltIndex = Entries.size(); +  Entries.push_back(&Sym); +} + +size_t PPC64LongBranchTargetSection::getSize() const { +  return Entries.size() * 8; +} + +void PPC64LongBranchTargetSection::writeTo(uint8_t *Buf) { +  assert(Target->GotPltEntrySize == 8); +  // If linking non-pic we have the final addresses of the targets and they get +  // written to the table directly. For pic the dynamic linker will allocate +  // the section and fill it it. +  if (Config->Pic) +    return; + +  for (const Symbol *Sym : Entries) { +    assert(Sym->getVA()); +    // Need calls to branch to the local entry-point since a long-branch +    // must be a local-call. +    write64(Buf, +            Sym->getVA() + getPPC64GlobalEntryToLocalEntryOffset(Sym->StOther)); +    Buf += Target->GotPltEntrySize; +  } +} + +bool PPC64LongBranchTargetSection::empty() const { +  // `removeUnusedSyntheticSections()` is called before thunk allocation which +  // is too early to determine if this section will be empty or not. We need +  // Finalized to keep the section alive until after thunk creation. Finalized +  // only gets set to true once `finalizeSections()` is called after thunk +  // creation. Becuase of this, if we don't create any long-branch thunks we end +  // up with an empty .branch_lt section in the binary. +  return Finalized && Entries.empty(); +} + +InStruct elf::In;  template GdbIndexSection *GdbIndexSection::create<ELF32LE>();  template GdbIndexSection *GdbIndexSection::create<ELF32BE>(); @@ -3141,8 +3222,3 @@ template class elf::VersionNeedSection<ELF32LE>;  template class elf::VersionNeedSection<ELF32BE>;  template class elf::VersionNeedSection<ELF64LE>;  template class elf::VersionNeedSection<ELF64BE>; - -template class elf::VersionDefinitionSection<ELF32LE>; -template class elf::VersionDefinitionSection<ELF32BE>; -template class elf::VersionDefinitionSection<ELF64LE>; -template class elf::VersionDefinitionSection<ELF64BE>; | 
