From 7f9694a42dacbf70e07f9a7d8f0f6564687884ad Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Sat, 28 Oct 2017 20:15:56 +0000 Subject: [PATCH] Pass symbol attributes instead of ElfSym to Shared symbol ctor. This change allows us to use less templates for Shared symbol and the functions that deals with shared symbols. llvm-svn: 316841 --- lld/ELF/InputFiles.cpp | 32 ++++++++++++++++++-------------- lld/ELF/InputFiles.h | 3 +-- lld/ELF/MapFile.cpp | 18 ++++++------------ lld/ELF/MapFile.h | 5 +---- lld/ELF/Relocations.cpp | 15 ++++++--------- lld/ELF/SymbolTable.cpp | 11 ++++++++--- lld/ELF/SymbolTable.h | 2 +- lld/ELF/Symbols.cpp | 25 ++----------------------- lld/ELF/Symbols.h | 32 ++++++++++---------------------- lld/ELF/SyntheticSections.cpp | 4 ++-- lld/ELF/Writer.cpp | 2 +- 11 files changed, 56 insertions(+), 93 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index f0ccda2..a848c4d 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -514,11 +514,9 @@ template void ObjFile::initializeSymbols() { } template -InputSectionBase *ObjFile::getSection(const Elf_Sym &Sym) const { - uint32_t Index = this->getSectionIndex(Sym); +InputSectionBase *ObjFile::getSection(uint32_t Index) const { if (Index == 0) return nullptr; - if (Index >= this->Sections.size()) fatal(toString(this) + ": invalid section index: " + Twine(Index)); @@ -533,7 +531,7 @@ InputSectionBase *ObjFile::getSection(const Elf_Sym &Sym) const { template SymbolBody *ObjFile::createSymbolBody(const Elf_Sym *Sym) { int Binding = Sym->getBinding(); - InputSectionBase *Sec = getSection(*Sym); + InputSectionBase *Sec = getSection(this->getSectionIndex(*Sym)); uint8_t StOther = Sym->st_other; uint8_t Type = Sym->getType(); @@ -629,14 +627,6 @@ SharedFile::SharedFile(MemoryBufferRef M, StringRef DefaultSoName) : ELFFileBase(Base::SharedKind, M), SoName(DefaultSoName), AsNeeded(Config->AsNeeded) {} -template -const typename ELFT::Shdr * -SharedFile::getSection(const Elf_Sym &Sym) const { - return check( - this->getObj().getSection(&Sym, this->ELFSyms, this->SymtabSHNDX), - toString(this)); -} - // Partially parse the shared object file so that we can call // getSoName on this object. template void SharedFile::parseSoName() { @@ -735,6 +725,10 @@ template void SharedFile::parseRest() { const Elf_Versym *Versym = nullptr; std::vector Verdefs = parseVerdefs(Versym); + ArrayRef Sections = + check(this->getObj().sections(), toString(this)); + + // Add symbols to the symbol table. Elf_Sym_Range Syms = this->getGlobalELFSyms(); for (const Elf_Sym &Sym : Syms) { unsigned VersymIndex = 0; @@ -765,15 +759,25 @@ template void SharedFile::parseRest() { V = Verdefs[VersymIndex]; } + // We do not usually care about alignments of data in shared object + // files because the loader takes care of it. However, if we promote a + // DSO symbol to point to .bss due to copy relocation, we need to keep + // the original alignment requirements. We infer it here. + uint32_t Alignment = 1 << countTrailingZeros((uint64_t)Sym.st_value); + if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size()) { + uint32_t SecAlign = Sections[Sym.st_shndx].sh_addralign; + Alignment = std::min(Alignment, SecAlign); + } + if (!Hidden) - Symtab->addShared(Name, this, Sym, V); + Symtab->addShared(Name, this, Sym, Alignment, V); // Also add the symbol with the versioned name to handle undefined symbols // with explicit versions. if (V) { StringRef VerName = this->StringTable.data() + V->getAux()->vda_name; Name = Saver.save(Name + "@" + VerName); - Symtab->addShared(Name, this, Sym, V); + Symtab->addShared(Name, this, Sym, Alignment, V); } } } diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index da1d7ee..5641dbb 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -167,7 +167,7 @@ public: ObjFile(MemoryBufferRef M, StringRef ArchiveName); void parse(llvm::DenseSet &ComdatGroups); - InputSectionBase *getSection(const Elf_Sym &Sym) const; + InputSectionBase *getSection(uint32_t Index) const; SymbolBody &getSymbolBody(uint32_t SymbolIndex) const { if (SymbolIndex >= this->Symbols.size()) @@ -294,7 +294,6 @@ template class SharedFile : public ELFFileBase { public: std::string SoName; - const Elf_Shdr *getSection(const Elf_Sym &Sym) const; llvm::ArrayRef getUndefinedSymbols() { return Undefs; } static bool classof(const InputFile *F) { diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp index ad80b06..591c4d8 100644 --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -49,7 +49,7 @@ static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size, static std::string indent(int Depth) { return std::string(Depth * 8, ' '); } // Returns a list of all symbols that we want to print out. -template static std::vector getSymbols() { +static std::vector getSymbols() { std::vector V; for (InputFile *File : ObjectFiles) { for (SymbolBody *B : File->getSymbols()) { @@ -90,13 +90,12 @@ static SymbolMapTy getSectionSyms(ArrayRef Syms) { // Construct a map from symbols to their stringified representations. // Demangling symbols (which is what toString() does) is slow, so // we do that in batch using parallel-for. -template static DenseMap getSymbolStrings(ArrayRef Syms) { std::vector Str(Syms.size()); parallelForEachN(0, Syms.size(), [&](size_t I) { raw_string_ostream OS(Str[I]); - writeHeader(OS, Syms[I]->getVA(), Syms[I]->template getSize(), 0); + writeHeader(OS, Syms[I]->getVA(), Syms[I]->getSize(), 0); OS << indent(2) << toString(*Syms[I]); }); @@ -106,7 +105,7 @@ getSymbolStrings(ArrayRef Syms) { return Ret; } -template void elf::writeMapFile() { +void elf::writeMapFile() { if (Config->MapFile.empty()) return; @@ -119,12 +118,12 @@ template void elf::writeMapFile() { } // Collect symbol info that we want to print out. - std::vector Syms = getSymbols(); + std::vector Syms = getSymbols(); SymbolMapTy SectionSyms = getSectionSyms(Syms); - DenseMap SymStr = getSymbolStrings(Syms); + DenseMap SymStr = getSymbolStrings(Syms); // Print out the header line. - int W = ELFT::Is64Bits ? 16 : 8; + int W = Config->Is64 ? 16 : 8; OS << left_justify("Address", W) << ' ' << left_justify("Size", W) << " Align Out In Symbol\n"; @@ -148,8 +147,3 @@ template void elf::writeMapFile() { } } } - -template void elf::writeMapFile(); -template void elf::writeMapFile(); -template void elf::writeMapFile(); -template void elf::writeMapFile(); diff --git a/lld/ELF/MapFile.h b/lld/ELF/MapFile.h index 1c63644..2d93e26 100644 --- a/lld/ELF/MapFile.h +++ b/lld/ELF/MapFile.h @@ -10,12 +10,9 @@ #ifndef LLD_ELF_MAPFILE_H #define LLD_ELF_MAPFILE_H -#include - namespace lld { namespace elf { -class OutputSection; -template void writeMapFile(); +void writeMapFile(); } // namespace elf } // namespace lld diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 94874fb..a6af92a 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -445,14 +445,13 @@ static RelExpr fromPlt(RelExpr Expr) { // Returns true if a given shared symbol is in a read-only segment in a DSO. template static bool isReadOnly(SharedSymbol *SS) { typedef typename ELFT::Phdr Elf_Phdr; - uint64_t Value = SS->getValue(); // Determine if the symbol is read-only by scanning the DSO's program headers. const SharedFile *File = SS->getFile(); for (const Elf_Phdr &Phdr : check(File->getObj().program_headers())) if ((Phdr.p_type == ELF::PT_LOAD || Phdr.p_type == ELF::PT_GNU_RELRO) && - !(Phdr.p_flags & ELF::PF_W) && Value >= Phdr.p_vaddr && - Value < Phdr.p_vaddr + Phdr.p_memsz) + !(Phdr.p_flags & ELF::PF_W) && SS->Value >= Phdr.p_vaddr && + SS->Value < Phdr.p_vaddr + Phdr.p_memsz) return true; return false; } @@ -467,12 +466,10 @@ static std::vector getSymbolsAt(SharedSymbol *SS) { typedef typename ELFT::Sym Elf_Sym; SharedFile *File = SS->getFile(); - uint64_t Shndx = SS->getShndx(); - uint64_t Value = SS->getValue(); std::vector Ret; for (const Elf_Sym &S : File->getGlobalELFSyms()) { - if (S.st_shndx != Shndx || S.st_value != Value) + if (S.st_shndx != SS->Shndx || S.st_value != SS->Value) continue; StringRef Name = check(S.getName(File->getStringTable())); SymbolBody *Sym = Symtab->find(Name); @@ -526,7 +523,7 @@ static std::vector getSymbolsAt(SharedSymbol *SS) { // define an accessor getV(). template static void addCopyRelSymbol(SharedSymbol *SS) { // Copy relocation against zero-sized symbol doesn't make sense. - uint64_t SymSize = SS->template getSize(); + uint64_t SymSize = SS->getSize(); if (SymSize == 0) fatal("cannot create a copy relocation for symbol " + toString(*SS)); @@ -534,7 +531,7 @@ template static void addCopyRelSymbol(SharedSymbol *SS) { // memory protection by reserving space in the .bss.rel.ro section. bool IsReadOnly = isReadOnly(SS); BssSection *Sec = make(IsReadOnly ? ".bss.rel.ro" : ".bss", - SymSize, SS->getAlignment()); + SymSize, SS->Alignment); if (IsReadOnly) InX::BssRelRo->getParent()->addSection(Sec); else @@ -1014,7 +1011,7 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef Rels) { // The size is not going to change, so we fold it in here. if (Expr == R_SIZE) - Addend += Body.getSize(); + Addend += Body.getSize(); // If the produced value is a constant, we just remember to write it // when outputting this section. We also have to do it if the format diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 7f7e6b2..34cd2f8 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -498,7 +498,7 @@ Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type, template void SymbolTable::addShared(StringRef Name, SharedFile *File, - const typename ELFT::Sym &Sym, + const typename ELFT::Sym &Sym, uint32_t Alignment, const typename ELFT::Verdef *Verdef) { // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT // as the visibility, which will leave the visibility in the symbol table @@ -516,8 +516,9 @@ void SymbolTable::addShared(StringRef Name, SharedFile *File, // in the same DSO. if (WasInserted || ((Body->isUndefined() || Body->isLazy()) && Body->getVisibility() == STV_DEFAULT)) { - replaceBody(S, File, Name, Sym.st_other, Sym.getType(), &Sym, - Verdef); + replaceBody(S, File, Name, Sym.st_other, Sym.getType(), + Sym.st_value, Sym.st_size, Alignment, + Sym.st_shndx, Verdef); if (!S->isWeak()) File->IsUsed = true; } @@ -881,15 +882,19 @@ template void SymbolTable::addLazyObject(StringRef, LazyObjFile &); template void SymbolTable::addShared(StringRef, SharedFile *, const typename ELF32LE::Sym &, + uint32_t Alignment, const typename ELF32LE::Verdef *); template void SymbolTable::addShared(StringRef, SharedFile *, const typename ELF32BE::Sym &, + uint32_t Alignment, const typename ELF32BE::Verdef *); template void SymbolTable::addShared(StringRef, SharedFile *, const typename ELF64LE::Sym &, + uint32_t Alignment, const typename ELF64LE::Verdef *); template void SymbolTable::addShared(StringRef, SharedFile *, const typename ELF64BE::Sym &, + uint32_t Alignment, const typename ELF64BE::Verdef *); template void SymbolTable::fetchIfLazy(StringRef); diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index 1d4ffb2..e2acc47 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -60,7 +60,7 @@ public: template void addShared(StringRef Name, SharedFile *F, - const typename ELFT::Sym &Sym, + const typename ELFT::Sym &Sym, uint32_t Alignment, const typename ELFT::Verdef *Verdef); template diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 5f5c383..307e2f2 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -174,13 +174,13 @@ uint64_t SymbolBody::getPltVA() const { PltIndex * Target->PltEntrySize; } -template typename ELFT::uint SymbolBody::getSize() const { +uint64_t SymbolBody::getSize() const { if (const auto *C = dyn_cast(this)) return C->Size; if (const auto *DR = dyn_cast(this)) return DR->Size; if (const auto *S = dyn_cast(this)) - return S->getSize(); + return S->Size; return 0; } @@ -261,17 +261,6 @@ template bool DefinedRegular::isMipsPIC() const { (Hdr->e_flags & EF_MIPS_PIC); } -// If a shared symbol is referred via a copy relocation, its alignment -// becomes part of the ABI. This function returns a symbol alignment. -// Because symbols don't have alignment attributes, we need to infer that. -template uint32_t SharedSymbol::getAlignment() const { - SharedFile *File = getFile(); - uint32_t SecAlign = File->getSection(getSym())->sh_addralign; - uint64_t SymValue = getSym().st_value; - uint32_t SymAlign = uint32_t(1) << countTrailingZeros(SymValue); - return std::min(SecAlign, SymAlign); -} - InputFile *Lazy::fetch() { if (auto *S = dyn_cast(this)) return S->fetch(); @@ -346,17 +335,7 @@ std::string lld::toString(const SymbolBody &B) { return B.getName(); } -template uint32_t SymbolBody::template getSize() const; -template uint32_t SymbolBody::template getSize() const; -template uint64_t SymbolBody::template getSize() const; -template uint64_t SymbolBody::template getSize() const; - template bool DefinedRegular::template isMipsPIC() const; template bool DefinedRegular::template isMipsPIC() const; template bool DefinedRegular::template isMipsPIC() const; template bool DefinedRegular::template isMipsPIC() const; - -template uint32_t SharedSymbol::template getAlignment() const; -template uint32_t SharedSymbol::template getAlignment() const; -template uint32_t SharedSymbol::template getAlignment() const; -template uint32_t SharedSymbol::template getAlignment() const; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index d234d97..7fb9852 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -93,7 +93,7 @@ public: uint64_t getGotPltOffset() const; uint64_t getGotPltVA() const; uint64_t getPltVA() const; - template typename ELFT::uint getSize() const; + uint64_t getSize() const; OutputSection *getOutputSection() const; uint32_t DynsymIndex = 0; @@ -218,10 +218,12 @@ class SharedSymbol : public Defined { public: static bool classof(const SymbolBody *S) { return S->kind() == SharedKind; } - SharedSymbol(StringRef Name, uint8_t StOther, uint8_t Type, - const void *ElfSym, const void *Verdef) + SharedSymbol(StringRef Name, uint8_t StOther, uint8_t Type, uint64_t Value, + uint64_t Size, uint32_t Alignment, uint64_t Shndx, + const void *Verdef) : Defined(SharedKind, Name, /*IsLocal=*/false, StOther, Type), - Verdef(Verdef), ElfSym(ElfSym) { + Verdef(Verdef), Value(Value), Size(Size), Shndx(Shndx), + Alignment(Alignment) { // GNU ifunc is a mechanism to allow user-supplied functions to // resolve PLT slot values at load-time. This is contrary to the // regualr symbol resolution scheme in which symbols are resolved just @@ -246,18 +248,6 @@ public: return cast>(SymbolBody::getFile()); } - template uint64_t getShndx() const { - return getSym().st_shndx; - } - - template uint64_t getValue() const { - return getSym().st_value; - } - - template uint64_t getSize() const { - return getSym().st_size; - } - template uint32_t getAlignment() const; // This field is a pointer to the symbol's version definition. @@ -266,12 +256,10 @@ public: // If not null, there is a copy relocation to this section. InputSection *CopyRelSec = nullptr; -private: - template const typename ELFT::Sym &getSym() const { - return *(const typename ELFT::Sym *)ElfSym; - } - - const void *ElfSym; + uint64_t Value; // st_value + uint64_t Size; // st_size + uint64_t Shndx; // st_shndx + uint32_t Alignment; }; // This represents a symbol that is not yet in the link, but we know where to diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index c458f2d..adf8303 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -82,7 +82,7 @@ template void elf::createCommonSections() { // don't have to care about DefinedCommon symbols beyond this point. replaceBody(S, Sym->getFile(), Sym->getName(), static_cast(Sym->isLocal()), Sym->StOther, - Sym->Type, 0, Sym->getSize(), Section); + Sym->Type, 0, Sym->getSize(), Section); } } @@ -1615,7 +1615,7 @@ template void SymbolTableSection::writeTo(uint8_t *Buf) { if (ESym->st_shndx == SHN_UNDEF) ESym->st_size = 0; else - ESym->st_size = Body->getSize(); + ESym->st_size = Body->getSize(); // st_value is usually an address of a symbol, but that has a // special meaining for uninstantiated common symbols (this can diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 8b12673..1d2a4d2 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -248,7 +248,7 @@ template void Writer::run() { return; // Handle -Map option. - writeMapFile(); + writeMapFile(); if (errorCount()) return; -- 2.7.4