diff options
| author | Peter Collingbourne <peter@pcc.me.uk> | 2019-04-08 17:35:55 +0000 |
|---|---|---|
| committer | Peter Collingbourne <peter@pcc.me.uk> | 2019-04-08 17:35:55 +0000 |
| commit | cc1618e6689df872dcb005c5ceeecd38c56c36af (patch) | |
| tree | c72632180c2c1bd3f4fce361587de3744199bf55 | |
| parent | 1b62c758d0891ab42bf9bec6e9f26ec7bac67217 (diff) | |
| download | bcm5719-llvm-cc1618e6689df872dcb005c5ceeecd38c56c36af.tar.gz bcm5719-llvm-cc1618e6689df872dcb005c5ceeecd38c56c36af.zip | |
ELF: De-template SharedFile. NFCI.
Differential Revision: https://reviews.llvm.org/D60305
llvm-svn: 357925
| -rw-r--r-- | lld/ELF/Driver.cpp | 6 | ||||
| -rw-r--r-- | lld/ELF/InputFiles.cpp | 223 | ||||
| -rw-r--r-- | lld/ELF/InputFiles.h | 25 | ||||
| -rw-r--r-- | lld/ELF/MarkLive.cpp | 4 | ||||
| -rw-r--r-- | lld/ELF/Relocations.cpp | 4 | ||||
| -rw-r--r-- | lld/ELF/SymbolTable.cpp | 31 | ||||
| -rw-r--r-- | lld/ELF/SymbolTable.h | 7 | ||||
| -rw-r--r-- | lld/ELF/Symbols.h | 7 | ||||
| -rw-r--r-- | lld/ELF/SyntheticSections.cpp | 22 | ||||
| -rw-r--r-- | lld/ELF/SyntheticSections.h | 2 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 15 |
11 files changed, 165 insertions, 181 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 8a608910b80..7ee9b0b5bbf 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1289,10 +1289,10 @@ template <class ELFT> static void handleLibcall(StringRef Name) { // to DT_NEEDED. If that happens, we need to eliminate shared symbols // created from the DSO. Otherwise, they become dangling references // that point to a non-existent DSO. -template <class ELFT> static void demoteSharedSymbols() { +static void demoteSharedSymbols() { for (Symbol *Sym : Symtab->getSymbols()) { if (auto *S = dyn_cast<SharedSymbol>(Sym)) { - if (!S->getFile<ELFT>().IsNeeded) { + if (!S->getFile().IsNeeded) { bool Used = S->Used; replaceSymbol<Undefined>(S, nullptr, S->getName(), STB_WEAK, S->StOther, S->Type); @@ -1644,7 +1644,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { // and identical code folding. splitSections<ELFT>(); markLive<ELFT>(); - demoteSharedSymbols<ELFT>(); + demoteSharedSymbols(); mergeSections(); if (Config->ICF != ICFLevel::None) { findKeepUniqueSections<ELFT>(Args); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 8e6fe89d6eb..e09d6133353 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -43,7 +43,7 @@ std::vector<BinaryFile *> elf::BinaryFiles; std::vector<BitcodeFile *> elf::BitcodeFiles; std::vector<LazyObjFile *> elf::LazyObjFiles; std::vector<InputFile *> elf::ObjectFiles; -std::vector<InputFile *> elf::SharedFiles; +std::vector<SharedFile *> elf::SharedFiles; std::unique_ptr<TarWriter> elf::Tar; @@ -869,20 +869,83 @@ InputFile *ArchiveFile::fetch(const Archive::Symbol &Sym) { return File; } -template <class ELFT> -SharedFile<ELFT>::SharedFile(MemoryBufferRef M, StringRef DefaultSoName) +SharedFile::SharedFile(MemoryBufferRef M, StringRef DefaultSoName) : ELFFileBase(SharedKind, M), SoName(DefaultSoName), - IsNeeded(!Config->AsNeeded) { - parseHeader<ELFT>(); + IsNeeded(!Config->AsNeeded) {} + +// Parse the version definitions in the object file if present, and return a +// vector whose nth element contains a pointer to the Elf_Verdef for version +// identifier n. Version identifiers that are not definitions map to nullptr. +template <typename ELFT> +static std::vector<const void *> parseVerdefs(const uint8_t *Base, + const typename ELFT::Shdr *Sec) { + if (!Sec) + return {}; + + // We cannot determine the largest verdef identifier without inspecting + // every Elf_Verdef, but both bfd and gold assign verdef identifiers + // sequentially starting from 1, so we predict that the largest identifier + // will be VerdefCount. + unsigned VerdefCount = Sec->sh_info; + std::vector<const void *> Verdefs(VerdefCount + 1); + + // Build the Verdefs array by following the chain of Elf_Verdef objects + // from the start of the .gnu.version_d section. + const uint8_t *Verdef = Base + Sec->sh_offset; + for (unsigned I = 0; I != VerdefCount; ++I) { + auto *CurVerdef = reinterpret_cast<const typename ELFT::Verdef *>(Verdef); + Verdef += CurVerdef->vd_next; + unsigned VerdefIndex = CurVerdef->vd_ndx; + Verdefs.resize(VerdefIndex + 1); + Verdefs[VerdefIndex] = CurVerdef; + } + return Verdefs; } -// Partially parse the shared object file so that we can call -// getSoName on this object. -template <class ELFT> void SharedFile<ELFT>::parseDynamic() { +// 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 in this function. +template <typename ELFT> +static uint64_t getAlignment(ArrayRef<typename ELFT::Shdr> Sections, + const typename ELFT::Sym &Sym) { + uint64_t Ret = UINT64_MAX; + if (Sym.st_value) + Ret = 1ULL << countTrailingZeros((uint64_t)Sym.st_value); + if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size()) + Ret = std::min<uint64_t>(Ret, Sections[Sym.st_shndx].sh_addralign); + return (Ret > UINT32_MAX) ? 0 : Ret; +} + +// Fully parse the shared object file. +// +// This function parses symbol versions. If a DSO has version information, +// the file has a ".gnu.version_d" section which contains symbol version +// definitions. Each symbol is associated to one version through a table in +// ".gnu.version" section. That table is a parallel array for the symbol +// table, and each table entry contains an index in ".gnu.version_d". +// +// The special index 0 is reserved for VERF_NDX_LOCAL and 1 is for +// VER_NDX_GLOBAL. There's no table entry for these special versions in +// ".gnu.version_d". +// +// The file format for symbol versioning is perhaps a bit more complicated +// than necessary, but you can easily understand the code if you wrap your +// head around the data structure described above. +template <class ELFT> void SharedFile::parse() { + using Elf_Dyn = typename ELFT::Dyn; + using Elf_Shdr = typename ELFT::Shdr; + using Elf_Sym = typename ELFT::Sym; + using Elf_Verdef = typename ELFT::Verdef; + using Elf_Versym = typename ELFT::Versym; + ArrayRef<Elf_Dyn> DynamicTags; const ELFFile<ELFT> Obj = this->getObj<ELFT>(); ArrayRef<Elf_Shdr> Sections = CHECK(Obj.sections(), this); + const Elf_Shdr *VersymSec = nullptr; + const Elf_Shdr *VerdefSec = nullptr; + // Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d. for (const Elf_Shdr &Sec : Sections) { switch (Sec.sh_type) { @@ -896,16 +959,18 @@ template <class ELFT> void SharedFile<ELFT>::parseDynamic() { CHECK(Obj.template getSectionContentsAsArray<Elf_Dyn>(&Sec), this); break; case SHT_GNU_versym: - this->VersymSec = &Sec; + VersymSec = &Sec; break; case SHT_GNU_verdef: - this->VerdefSec = &Sec; + VerdefSec = &Sec; break; } } - if (this->VersymSec && this->getELFSyms<ELFT>().empty()) + if (VersymSec && this->getELFSyms<ELFT>().empty()) { error("SHT_GNU_versym should be associated with symbol table"); + return; + } // Search for a DT_SONAME tag to initialize this->SoName. for (const Elf_Dyn &Dyn : DynamicTags) { @@ -921,91 +986,38 @@ template <class ELFT> void SharedFile<ELFT>::parseDynamic() { SoName = this->StringTable.data() + Val; } } -} -// Parses ".gnu.version" section which is a parallel array for the symbol table. -// If a given file doesn't have ".gnu.version" section, returns VER_NDX_GLOBAL. -template <class ELFT> std::vector<uint32_t> SharedFile<ELFT>::parseVersyms() { - size_t Size = this->getELFSyms<ELFT>().size() - this->FirstGlobal; - if (!VersymSec) - return std::vector<uint32_t>(Size, VER_NDX_GLOBAL); - - const char *Base = this->MB.getBuffer().data(); - const Elf_Versym *Versym = - reinterpret_cast<const Elf_Versym *>(Base + VersymSec->sh_offset) + - this->FirstGlobal; - - std::vector<uint32_t> Ret(Size); - for (size_t I = 0; I < Size; ++I) - Ret[I] = Versym[I].vs_index; - return Ret; -} + // DSOs are uniquified not by filename but by soname. + DenseMap<StringRef, SharedFile *>::iterator It; + bool WasInserted; + std::tie(It, WasInserted) = Symtab->SoNames.try_emplace(SoName, this); + + // If a DSO appears more than once on the command line with and without + // --as-needed, --no-as-needed takes precedence over --as-needed because a + // user can add an extra DSO with --no-as-needed to force it to be added to + // the dependency list. + It->second->IsNeeded |= IsNeeded; + if (!WasInserted) + return; -// Parse the version definitions in the object file if present. Returns a vector -// whose nth element contains a pointer to the Elf_Verdef for version identifier -// n. Version identifiers that are not definitions map to nullptr. -template <class ELFT> -std::vector<const typename ELFT::Verdef *> SharedFile<ELFT>::parseVerdefs() { - if (!VerdefSec) - return {}; + SharedFiles.push_back(this); - // We cannot determine the largest verdef identifier without inspecting - // every Elf_Verdef, but both bfd and gold assign verdef identifiers - // sequentially starting from 1, so we predict that the largest identifier - // will be VerdefCount. - unsigned VerdefCount = VerdefSec->sh_info; - std::vector<const Elf_Verdef *> Verdefs(VerdefCount + 1); + Verdefs = parseVerdefs<ELFT>(Obj.base(), VerdefSec); - // Build the Verdefs array by following the chain of Elf_Verdef objects - // from the start of the .gnu.version_d section. - const char *Base = this->MB.getBuffer().data(); - const char *Verdef = Base + VerdefSec->sh_offset; - for (unsigned I = 0; I != VerdefCount; ++I) { - auto *CurVerdef = reinterpret_cast<const Elf_Verdef *>(Verdef); - Verdef += CurVerdef->vd_next; - unsigned VerdefIndex = CurVerdef->vd_ndx; - Verdefs.resize(VerdefIndex + 1); - Verdefs[VerdefIndex] = CurVerdef; + // Parse ".gnu.version" section which is a parallel array for the symbol + // table. If a given file doesn't have a ".gnu.version" section, we use + // VER_NDX_GLOBAL. + size_t Size = this->getELFSyms<ELFT>().size() - this->FirstGlobal; + std::vector<uint32_t> Versyms(Size, VER_NDX_GLOBAL); + if (VersymSec) { + ArrayRef<Elf_Versym> Versym = + CHECK(Obj.template getSectionContentsAsArray<Elf_Versym>(VersymSec), + this) + .slice(FirstGlobal); + for (size_t I = 0; I < Size; ++I) + Versyms[I] = Versym[I].vs_index; } - return Verdefs; -} - -// 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 in this function. -template <class ELFT> -uint32_t SharedFile<ELFT>::getAlignment(ArrayRef<Elf_Shdr> Sections, - const Elf_Sym &Sym) { - uint64_t Ret = UINT64_MAX; - if (Sym.st_value) - Ret = 1ULL << countTrailingZeros((uint64_t)Sym.st_value); - if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size()) - Ret = std::min<uint64_t>(Ret, Sections[Sym.st_shndx].sh_addralign); - return (Ret > UINT32_MAX) ? 0 : Ret; -} - -// Fully parse the shared object file. This must be called after parseDynamic(). -// -// This function parses symbol versions. If a DSO has version information, -// the file has a ".gnu.version_d" section which contains symbol version -// definitions. Each symbol is associated to one version through a table in -// ".gnu.version" section. That table is a parallel array for the symbol -// table, and each table entry contains an index in ".gnu.version_d". -// -// The special index 0 is reserved for VERF_NDX_LOCAL and 1 is for -// VER_NDX_GLOBAL. There's no table entry for these special versions in -// ".gnu.version_d". -// -// The file format for symbol versioning is perhaps a bit more complicated -// than necessary, but you can easily understand the code if you wrap your -// head around the data structure described above. -template <class ELFT> void SharedFile<ELFT>::parseRest() { - Verdefs = parseVerdefs(); // parse .gnu.version_d - std::vector<uint32_t> Versyms = parseVersyms(); // parse .gnu.version - ArrayRef<Elf_Shdr> Sections = CHECK(this->getObj<ELFT>().sections(), this); - // System libraries can have a lot of symbols with versions. Using a // fixed buffer for computing the versions name (foo@ver) can save a // lot of allocations. @@ -1043,9 +1055,9 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() { Name == "_gp_disp") continue; - uint64_t Alignment = getAlignment(Sections, Sym); + uint64_t Alignment = getAlignment<ELFT>(Sections, Sym); if (!(Versyms[I] & VERSYM_HIDDEN)) - Symtab->addShared(Name, *this, Sym, Alignment, Idx); + Symtab->addShared<ELFT>(Name, *this, Sym, Alignment, Idx); // Also add the symbol with the versioned name to handle undefined symbols // with explicit versions. @@ -1060,10 +1072,11 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() { } StringRef VerName = - this->StringTable.data() + Verdefs[Idx]->getAux()->vda_name; + this->StringTable.data() + + reinterpret_cast<const Elf_Verdef *>(Verdefs[Idx])->getAux()->vda_name; VersionedNameBuffer.clear(); Name = (Name + "@" + VerName).toStringRef(VersionedNameBuffer); - Symtab->addShared(Saver.save(Name), *this, Sym, Alignment, Idx); + Symtab->addShared<ELFT>(Saver.save(Name), *this, Sym, Alignment, Idx); } } @@ -1259,18 +1272,24 @@ InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName, } InputFile *elf::createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName) { + auto *F = make<SharedFile>(MB, DefaultSoName); switch (getELFKind(MB, "")) { case ELF32LEKind: - return make<SharedFile<ELF32LE>>(MB, DefaultSoName); + F->parseHeader<ELF32LE>(); + break; case ELF32BEKind: - return make<SharedFile<ELF32BE>>(MB, DefaultSoName); + F->parseHeader<ELF32BE>(); + break; case ELF64LEKind: - return make<SharedFile<ELF64LE>>(MB, DefaultSoName); + F->parseHeader<ELF64LE>(); + break; case ELF64BEKind: - return make<SharedFile<ELF64BE>>(MB, DefaultSoName); + F->parseHeader<ELF64BE>(); + break; default: llvm_unreachable("getELFKind"); } + return F; } MemoryBufferRef LazyObjFile::getBuffer() { @@ -1355,7 +1374,7 @@ template class elf::ObjFile<ELF32BE>; template class elf::ObjFile<ELF64LE>; template class elf::ObjFile<ELF64BE>; -template class elf::SharedFile<ELF32LE>; -template class elf::SharedFile<ELF32BE>; -template class elf::SharedFile<ELF64LE>; -template class elf::SharedFile<ELF64BE>; +template void SharedFile::parse<ELF32LE>(); +template void SharedFile::parse<ELF32BE>(); +template void SharedFile::parse<ELF64LE>(); +template void SharedFile::parse<ELF64BE>(); diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index c8f7f9ef669..8d3eed26625 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -328,19 +328,10 @@ public: }; // .so file. -template <class ELFT> class SharedFile : public ELFFileBase { - using Elf_Dyn = typename ELFT::Dyn; - using Elf_Shdr = typename ELFT::Shdr; - using Elf_Sym = typename ELFT::Sym; - using Elf_Sym_Range = typename ELFT::SymRange; - using Elf_Verdef = typename ELFT::Verdef; - using Elf_Versym = typename ELFT::Versym; - - const Elf_Shdr *VersymSec = nullptr; - const Elf_Shdr *VerdefSec = nullptr; - +class SharedFile : public ELFFileBase { public: - std::vector<const Elf_Verdef *> Verdefs; + // This is actually a vector of Elf_Verdef pointers. + std::vector<const void *> Verdefs; std::vector<StringRef> DtNeeded; std::string SoName; @@ -348,11 +339,7 @@ public: SharedFile(MemoryBufferRef M, StringRef DefaultSoName); - void parseDynamic(); - void parseRest(); - uint32_t getAlignment(ArrayRef<Elf_Shdr> Sections, const Elf_Sym &Sym); - std::vector<const Elf_Verdef *> parseVerdefs(); - std::vector<uint32_t> parseVersyms(); + template <typename ELFT> void parse(); struct NeededVer { // The string table offset of the version name in the output file. @@ -364,7 +351,7 @@ public: // Mapping from Elf_Verdef data structures to information about Elf_Vernaux // data structures in the output file. - std::map<const Elf_Verdef *, NeededVer> VerdefMap; + std::map<const void *, NeededVer> VerdefMap; // Used for --no-allow-shlib-undefined. bool AllNeededIsKnown; @@ -394,7 +381,7 @@ extern std::vector<BinaryFile *> BinaryFiles; extern std::vector<BitcodeFile *> BitcodeFiles; extern std::vector<LazyObjFile *> LazyObjFiles; extern std::vector<InputFile *> ObjectFiles; -extern std::vector<InputFile *> SharedFiles; +extern std::vector<SharedFile *> SharedFiles; } // namespace elf } // namespace lld diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index d8a519b35d9..d040a214aa6 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -103,7 +103,7 @@ void MarkLive<ELFT>::resolveReloc(InputSectionBase &Sec, RelTy &Rel, if (auto *SS = dyn_cast<SharedSymbol>(&Sym)) if (!SS->isWeak()) - SS->getFile<ELFT>().IsNeeded = true; + SS->getFile().IsNeeded = true; for (InputSectionBase *Sec : CNamedSections.lookup(Sym.getName())) enqueue(Sec, 0); @@ -276,7 +276,7 @@ template <class ELFT> void elf::markLive() { for (Symbol *Sym : Symtab->getSymbols()) if (auto *S = dyn_cast<SharedSymbol>(Sym)) if (S->IsUsedInRegularObj && !S->isWeak()) - S->getFile<ELFT>().IsNeeded = true; + S->getFile().IsNeeded = true; return; } diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 5f2089c6448..ac62666e461 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -482,7 +482,7 @@ template <class ELFT> static bool isReadOnly(SharedSymbol &SS) { using Elf_Phdr = typename ELFT::Phdr; // Determine if the symbol is read-only by scanning the DSO's program headers. - const SharedFile<ELFT> &File = SS.getFile<ELFT>(); + const SharedFile &File = SS.getFile(); for (const Elf_Phdr &Phdr : check(File.template getObj<ELFT>().program_headers())) if ((Phdr.p_type == ELF::PT_LOAD || Phdr.p_type == ELF::PT_GNU_RELRO) && @@ -501,7 +501,7 @@ template <class ELFT> static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &SS) { using Elf_Sym = typename ELFT::Sym; - SharedFile<ELFT> &File = SS.getFile<ELFT>(); + SharedFile &File = SS.getFile(); SmallSet<SharedSymbol *, 4> Ret; for (const Elf_Sym &S : File.template getGlobalELFSyms<ELFT>()) { diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index e25682f809c..c2a9d6dfb70 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -90,25 +90,8 @@ template <class ELFT> void SymbolTable::addFile(InputFile *File) { message(toString(File)); // .so file - if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) { - // DSOs are uniquified not by filename but by soname. - F->parseDynamic(); - if (errorCount()) - return; - - // If a DSO appears more than once on the command line with and without - // --as-needed, --no-as-needed takes precedence over --as-needed because a - // user can add an extra DSO with --no-as-needed to force it to be added to - // the dependency list. - DenseMap<StringRef, InputFile *>::iterator It; - bool WasInserted; - std::tie(It, WasInserted) = SoNames.try_emplace(F->SoName, F); - cast<SharedFile<ELFT>>(It->second)->IsNeeded |= F->IsNeeded; - if (!WasInserted) - return; - - SharedFiles.push_back(F); - F->parseRest(); + if (auto *F = dyn_cast<SharedFile>(File)) { + F->parse<ELFT>(); return; } @@ -485,7 +468,7 @@ Defined *SymbolTable::addDefined(StringRef Name, uint8_t StOther, uint8_t Type, } template <typename ELFT> -void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> &File, +void SymbolTable::addShared(StringRef Name, SharedFile &File, const typename ELFT::Sym &Sym, uint32_t Alignment, uint32_t VerdefIndex) { // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT @@ -802,15 +785,15 @@ template void SymbolTable::fetchLazy<ELF32BE>(Symbol *); template void SymbolTable::fetchLazy<ELF64LE>(Symbol *); template void SymbolTable::fetchLazy<ELF64BE>(Symbol *); -template void SymbolTable::addShared<ELF32LE>(StringRef, SharedFile<ELF32LE> &, +template void SymbolTable::addShared<ELF32LE>(StringRef, SharedFile &, const typename ELF32LE::Sym &, uint32_t Alignment, uint32_t); -template void SymbolTable::addShared<ELF32BE>(StringRef, SharedFile<ELF32BE> &, +template void SymbolTable::addShared<ELF32BE>(StringRef, SharedFile &, const typename ELF32BE::Sym &, uint32_t Alignment, uint32_t); -template void SymbolTable::addShared<ELF64LE>(StringRef, SharedFile<ELF64LE> &, +template void SymbolTable::addShared<ELF64LE>(StringRef, SharedFile &, const typename ELF64LE::Sym &, uint32_t Alignment, uint32_t); -template void SymbolTable::addShared<ELF64BE>(StringRef, SharedFile<ELF64BE> &, +template void SymbolTable::addShared<ELF64BE>(StringRef, SharedFile &, const typename ELF64BE::Sym &, uint32_t Alignment, uint32_t); diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index 9822ed75c3f..9f21c85f750 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -49,9 +49,8 @@ public: SectionBase *Section, InputFile *File); template <class ELFT> - void addShared(StringRef Name, SharedFile<ELFT> &F, - const typename ELFT::Sym &Sym, uint32_t Alignment, - uint32_t VerdefIndex); + void addShared(StringRef Name, SharedFile &F, const typename ELFT::Sym &Sym, + uint32_t Alignment, uint32_t VerdefIndex); template <class ELFT> void addLazyArchive(StringRef Name, ArchiveFile &F, @@ -80,7 +79,7 @@ public: void handleDynamicList(); // Set of .so files to not link the same shared object file more than once. - llvm::DenseMap<StringRef, InputFile *> SoNames; + llvm::DenseMap<StringRef, SharedFile *> SoNames; private: std::pair<Symbol *, bool> insertName(StringRef Name); diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 83aebf2aecd..d7647e79452 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -13,6 +13,7 @@ #ifndef LLD_ELF_SYMBOLS_H #define LLD_ELF_SYMBOLS_H +#include "InputFiles.h" #include "InputSection.h" #include "lld/Common/LLVM.h" #include "lld/Common/Strings.h" @@ -30,8 +31,6 @@ std::string toString(const elf::InputFile *); namespace elf { -template <class ELFT> class SharedFile; - // This is a StringRef-like container that doesn't run strlen(). // // ELF string tables contain a lot of null-terminated strings. Most of them @@ -266,9 +265,7 @@ public: this->Type = llvm::ELF::STT_FUNC; } - template <class ELFT> SharedFile<ELFT> &getFile() const { - return *cast<SharedFile<ELFT>>(File); - } + SharedFile &getFile() const { return *cast<SharedFile>(File); } uint32_t Alignment; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 7dd1683fedd..922238fefdc 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1263,11 +1263,9 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { addInt(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, In.DynStrTab->addString(Config->Rpath)); - for (InputFile *File : SharedFiles) { - SharedFile<ELFT> *F = cast<SharedFile<ELFT>>(File); - if (F->IsNeeded) - addInt(DT_NEEDED, In.DynStrTab->addString(F->SoName)); - } + for (SharedFile *File : SharedFiles) + if (File->IsNeeded) + addInt(DT_NEEDED, In.DynStrTab->addString(File->SoName)); if (!Config->SoName.empty()) addInt(DT_SONAME, In.DynStrTab->addString(Config->SoName)); @@ -2792,7 +2790,7 @@ VersionNeedBaseSection::VersionNeedBaseSection() } template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) { - auto &File = cast<SharedFile<ELFT>>(*SS->File); + auto &File = cast<SharedFile>(*SS->File); if (SS->VerdefIndex == VER_NDX_GLOBAL) { SS->VersionId = VER_NDX_GLOBAL; return; @@ -2803,8 +2801,9 @@ template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) { // for the soname. if (File.VerdefMap.empty()) 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]; + auto *Ver = reinterpret_cast<const typename ELFT::Verdef *>( + File.Verdefs[SS->VerdefIndex]); + typename SharedFile::NeededVer &NV = File.VerdefMap[Ver]; // If we don't already know that we need an Elf_Vernaux for this Elf_Verdef, // prepare to create one by allocating a version identifier and creating a @@ -2822,7 +2821,7 @@ template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) { auto *Verneed = reinterpret_cast<Elf_Verneed *>(Buf); auto *Vernaux = reinterpret_cast<Elf_Vernaux *>(Verneed + Needed.size()); - for (std::pair<SharedFile<ELFT> *, size_t> &P : Needed) { + for (std::pair<SharedFile *, size_t> &P : Needed) { // Create an Elf_Verneed for this DSO. Verneed->vn_version = 1; Verneed->vn_cnt = P.first->VerdefMap.size(); @@ -2839,7 +2838,8 @@ template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) { // pointers, but is deterministic because the pointers refer to Elf_Verdef // data structures within a single input file. for (auto &NV : P.first->VerdefMap) { - Vernaux->vna_hash = NV.first->vd_hash; + Vernaux->vna_hash = + reinterpret_cast<const typename ELFT::Verdef *>(NV.first)->vd_hash; Vernaux->vna_flags = 0; Vernaux->vna_other = NV.second.Index; Vernaux->vna_name = NV.second.StrTab; @@ -2860,7 +2860,7 @@ template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() { template <class ELFT> size_t VersionNeedSection<ELFT>::getSize() const { unsigned Size = Needed.size() * sizeof(Elf_Verneed); - for (const std::pair<SharedFile<ELFT> *, size_t> &P : Needed) + for (const std::pair<SharedFile *, size_t> &P : Needed) Size += P.first->VerdefMap.size() * sizeof(Elf_Vernaux); return Size; } diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index ab42f7d2a1a..15e7d688749 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -809,7 +809,7 @@ class VersionNeedSection final : public VersionNeedBaseSection { // A vector of shared files that need Elf_Verneed data structures and the // string table offsets of their sonames. - std::vector<std::pair<SharedFile<ELFT> *, size_t>> Needed; + std::vector<std::pair<SharedFile *, size_t>> Needed; public: void addSymbol(Symbol *Sym) override; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index f8e17cd0515..5432da6964f 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1628,15 +1628,14 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // ld.bfd traces all DT_NEEDED to emulate the logic of the dynamic linker to // catch more cases. That is too much for us. Our approach resembles the one // used in ld.gold, achieves a good balance to be useful but not too smart. - for (InputFile *File : SharedFiles) { - SharedFile<ELFT> *F = cast<SharedFile<ELFT>>(File); - F->AllNeededIsKnown = llvm::all_of(F->DtNeeded, [&](StringRef Needed) { - return Symtab->SoNames.count(Needed); - }); - } + for (SharedFile *File : SharedFiles) + File->AllNeededIsKnown = + llvm::all_of(File->DtNeeded, [&](StringRef Needed) { + return Symtab->SoNames.count(Needed); + }); for (Symbol *Sym : Symtab->getSymbols()) if (Sym->isUndefined() && !Sym->isWeak()) - if (auto *F = dyn_cast_or_null<SharedFile<ELFT>>(Sym->File)) + if (auto *F = dyn_cast_or_null<SharedFile>(Sym->File)) if (F->AllNeededIsKnown) error(toString(F) + ": undefined reference to " + toString(*Sym)); } @@ -1651,7 +1650,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { if (Sym->includeInDynsym()) { In.DynSymTab->addSymbol(Sym); - if (auto *File = dyn_cast_or_null<SharedFile<ELFT>>(Sym->File)) + if (auto *File = dyn_cast_or_null<SharedFile>(Sym->File)) if (File->IsNeeded && !Sym->isUndefined()) In.VerNeed->addSymbol(Sym); } |

