ELF: De-template SharedFile. NFCI.

Differential Revision: https://reviews.llvm.org/D60305

llvm-svn: 357925
This commit is contained in:
Peter Collingbourne 2019-04-08 17:35:55 +00:00
parent 1b62c758d0
commit cc1618e668
11 changed files with 167 additions and 183 deletions

View File

@ -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);

View File

@ -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() {
// 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;
SharedFiles.push_back(this);
Verdefs = parseVerdefs<ELFT>(Obj.base(), VerdefSec);
// 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;
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;
}
// 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 {};
// 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);
// 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;
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>();

View File

@ -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

View File

@ -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;
}

View File

@ -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>()) {

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}