diff options
Diffstat (limited to 'ELF/SyntheticSections.cpp')
| -rw-r--r-- | ELF/SyntheticSections.cpp | 77 | 
1 files changed, 59 insertions, 18 deletions
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp index 38859e1650bf9..ae02434572c2a 100644 --- a/ELF/SyntheticSections.cpp +++ b/ELF/SyntheticSections.cpp @@ -335,7 +335,7 @@ void BuildIdSection::writeBuildId(ArrayRef<uint8_t> Buf) {    switch (Config->BuildId) {    case BuildIdKind::Fast:      computeHash(Buf, [](uint8_t *Dest, ArrayRef<uint8_t> Arr) { -      write64le(Dest, xxHash64(toStringRef(Arr))); +      write64le(Dest, xxHash64(Arr));      });      break;    case BuildIdKind::Md5: @@ -1935,6 +1935,23 @@ SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &StrTabSec)    this->Entsize = sizeof(Elf_Sym);  } +static BssSection *getCommonSec(Symbol *Sym) { +  if (!Config->DefineCommon) +    if (auto *D = dyn_cast<Defined>(Sym)) +      return dyn_cast_or_null<BssSection>(D->Section); +  return nullptr; +} + +static uint32_t getSymSectionIndex(Symbol *Sym) { +  if (getCommonSec(Sym)) +    return SHN_COMMON; +  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 SHN_ABS; +} +  // Write the internal symbol table contents to the output symbol table.  template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {    // The first entry is a null entry as per the ELF spec. @@ -1956,22 +1973,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {      }      ESym->st_name = Ent.StrTabOffset; - -    // Set a section index. -    BssSection *CommonSec = nullptr; -    if (!Config->DefineCommon) -      if (auto *D = dyn_cast<Defined>(Sym)) -        CommonSec = dyn_cast_or_null<BssSection>(D->Section); -    if (CommonSec) -      ESym->st_shndx = SHN_COMMON; -    else if (Sym->NeedsPltAddr) -      ESym->st_shndx = SHN_UNDEF; -    else if (const OutputSection *OutSec = Sym->getOutputSection()) -      ESym->st_shndx = OutSec->SectionIndex; -    else if (isa<Defined>(Sym)) -      ESym->st_shndx = SHN_ABS; -    else -      ESym->st_shndx = SHN_UNDEF; +    ESym->st_shndx = getSymSectionIndex(Ent.Sym);      // Copy symbol size if it is a defined symbol. st_size is not significant      // for undefined symbols, so whether copying it or not is up to us if that's @@ -1986,7 +1988,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {      // st_value is usually an address of a symbol, but that has a      // special meaining for uninstantiated common symbols (this can      // occur if -r is given). -    if (CommonSec) +    if (BssSection *CommonSec = getCommonSec(Ent.Sym))        ESym->st_value = CommonSec->Alignment;      else        ESym->st_value = Sym->getVA(); @@ -2026,6 +2028,44 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {    }  } +SymtabShndxSection::SymtabShndxSection() +    : SyntheticSection(0, SHT_SYMTAB_SHNDX, 4, ".symtab_shndxr") { +  this->Entsize = 4; +} + +void SymtabShndxSection::writeTo(uint8_t *Buf) { +  // We write an array of 32 bit values, where each value has 1:1 association +  // with an entry in .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()) { +    if (getSymSectionIndex(Entry.Sym) == SHN_XINDEX) +      write32(Buf, Entry.Sym->getOutputSection()->SectionIndex); +    Buf += 4; +  } +} + +bool SymtabShndxSection::empty() const { +  // SHT_SYMTAB can hold symbols with section indices values up to +  // SHN_LORESERVE. If we need more, we want to use extension SHT_SYMTAB_SHNDX +  // section. Problem is that we reveal the final section indices a bit too +  // late, and we do not know them here. For simplicity, we just always create +  // a .symtab_shndxr section when the amount of output sections is huge. +  size_t Size = 0; +  for (BaseCommand *Base : Script->SectionCommands) +    if (isa<OutputSection>(Base)) +      ++Size; +  return Size < SHN_LORESERVE; +} + +void SymtabShndxSection::finalizeContents() { +  getParent()->Link = InX::SymTab->getParent()->SectionIndex; +} + +size_t SymtabShndxSection::getSize() const { +  return InX::SymTab->getNumSymbols() * 4; +} +  // .hash and .gnu.hash sections contain on-disk hash tables that map  // symbol names to their dynamic symbol table indices. Their purpose  // is to help the dynamic linker resolve symbols quickly. If ELF files @@ -3025,6 +3065,7 @@ RelocationBaseSection *InX::RelaIplt;  StringTableSection *InX::ShStrTab;  StringTableSection *InX::StrTab;  SymbolTableBaseSection *InX::SymTab; +SymtabShndxSection *InX::SymTabShndx;  template GdbIndexSection *GdbIndexSection::create<ELF32LE>();  template GdbIndexSection *GdbIndexSection::create<ELF32BE>();  | 
