forked from OSchip/llvm-project
ELF: De-template ELFFileBase. NFCI.
Differential Revision: https://reviews.llvm.org/D60304 llvm-svn: 357806
This commit is contained in:
parent
c8f78f8dd3
commit
883ab235ee
|
@ -350,7 +350,7 @@ bool MIPS<ELFT>::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,
|
|||
if (Type != R_MIPS_26 && Type != R_MIPS_PC26_S2 &&
|
||||
Type != R_MICROMIPS_26_S1 && Type != R_MICROMIPS_PC26_S1)
|
||||
return false;
|
||||
auto *F = dyn_cast_or_null<ELFFileBase<ELFT>>(File);
|
||||
auto *F = dyn_cast_or_null<ObjFile<ELFT>>(File);
|
||||
if (!F)
|
||||
return false;
|
||||
// If current file has PIC code, LA25 stub is not required.
|
||||
|
|
|
@ -356,8 +356,8 @@ uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,
|
|||
}
|
||||
|
||||
template <class ELFT> static bool isN32Abi(const InputFile *F) {
|
||||
if (auto *EF = dyn_cast<ELFFileBase<ELFT>>(F))
|
||||
return EF->getObj().getHeader()->e_flags & EF_MIPS_ABI2;
|
||||
if (auto *EF = dyn_cast<ELFFileBase>(F))
|
||||
return EF->template getObj<ELFT>().getHeader()->e_flags & EF_MIPS_ABI2;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ LLDDwarfObj<ELFT>::findAux(const InputSectionBase &Sec, uint64_t Pos,
|
|||
|
||||
const ObjFile<ELFT> *File = Sec.getFile<ELFT>();
|
||||
uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL);
|
||||
const typename ELFT::Sym &Sym = File->getELFSyms()[SymIndex];
|
||||
const typename ELFT::Sym &Sym = File->template getELFSyms<ELFT>()[SymIndex];
|
||||
uint32_t SecIndex = File->getSectionIndex(Sym);
|
||||
|
||||
// Broken debug info can point to a non-Defined symbol.
|
||||
|
|
|
@ -241,45 +241,46 @@ std::string lld::toString(const InputFile *F) {
|
|||
return F->ToStringCache;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB) {
|
||||
ELFFileBase::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB) {}
|
||||
|
||||
template <class ELFT> void ELFFileBase::parseHeader() {
|
||||
if (ELFT::TargetEndianness == support::little)
|
||||
EKind = ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind;
|
||||
else
|
||||
EKind = ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind;
|
||||
|
||||
EMachine = getObj().getHeader()->e_machine;
|
||||
OSABI = getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI];
|
||||
ABIVersion = getObj().getHeader()->e_ident[llvm::ELF::EI_ABIVERSION];
|
||||
EMachine = getObj<ELFT>().getHeader()->e_machine;
|
||||
OSABI = getObj<ELFT>().getHeader()->e_ident[llvm::ELF::EI_OSABI];
|
||||
ABIVersion = getObj<ELFT>().getHeader()->e_ident[llvm::ELF::EI_ABIVERSION];
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
typename ELFT::SymRange ELFFileBase<ELFT>::getGlobalELFSyms() {
|
||||
return makeArrayRef(ELFSyms.begin() + FirstGlobal, ELFSyms.end());
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void ELFFileBase<ELFT>::initSymtab(ArrayRef<Elf_Shdr> Sections,
|
||||
const Elf_Shdr *Symtab) {
|
||||
void ELFFileBase::initSymtab(ArrayRef<typename ELFT::Shdr> Sections,
|
||||
const typename ELFT::Shdr *Symtab) {
|
||||
FirstGlobal = Symtab->sh_info;
|
||||
ELFSyms = CHECK(getObj().symbols(Symtab), this);
|
||||
ArrayRef<typename ELFT::Sym> ELFSyms =
|
||||
CHECK(getObj<ELFT>().symbols(Symtab), this);
|
||||
if (FirstGlobal == 0 || FirstGlobal > ELFSyms.size())
|
||||
fatal(toString(this) + ": invalid sh_info in symbol table");
|
||||
this->ELFSyms = reinterpret_cast<const void *>(ELFSyms.data());
|
||||
this->NumELFSyms = ELFSyms.size();
|
||||
|
||||
StringTable =
|
||||
CHECK(getObj().getStringTableForSymtab(*Symtab, Sections), this);
|
||||
CHECK(getObj<ELFT>().getStringTableForSymtab(*Symtab, Sections), this);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
ObjFile<ELFT>::ObjFile(MemoryBufferRef M, StringRef ArchiveName)
|
||||
: ELFFileBase<ELFT>(Base::ObjKind, M) {
|
||||
: ELFFileBase(ObjKind, M) {
|
||||
parseHeader<ELFT>();
|
||||
this->ArchiveName = ArchiveName;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
uint32_t ObjFile<ELFT>::getSectionIndex(const Elf_Sym &Sym) const {
|
||||
return CHECK(this->getObj().getSectionIndex(&Sym, this->ELFSyms, SymtabSHNDX),
|
||||
this);
|
||||
return CHECK(
|
||||
this->getObj().getSectionIndex(&Sym, getELFSyms<ELFT>(), SymtabSHNDX),
|
||||
this);
|
||||
}
|
||||
|
||||
template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getLocalSymbols() {
|
||||
|
@ -312,12 +313,12 @@ StringRef ObjFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,
|
|||
const Elf_Shdr &Sec) {
|
||||
// Group signatures are stored as symbol names in object files.
|
||||
// sh_info contains a symbol index, so we fetch a symbol and read its name.
|
||||
if (this->ELFSyms.empty())
|
||||
this->initSymtab(
|
||||
if (this->getELFSyms<ELFT>().empty())
|
||||
this->initSymtab<ELFT>(
|
||||
Sections, CHECK(object::getSection<ELFT>(Sections, Sec.sh_link), this));
|
||||
|
||||
const Elf_Sym *Sym =
|
||||
CHECK(object::getSymbol<ELFT>(this->ELFSyms, Sec.sh_info), this);
|
||||
CHECK(object::getSymbol<ELFT>(this->getELFSyms<ELFT>(), Sec.sh_info), this);
|
||||
StringRef Signature = CHECK(Sym->getName(this->StringTable), this);
|
||||
|
||||
// As a special case, if a symbol is a section symbol and has no name,
|
||||
|
@ -392,7 +393,7 @@ template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() {
|
|||
for (const Elf_Shdr &Sec : ObjSections) {
|
||||
if (Sec.sh_type != SHT_SYMTAB)
|
||||
continue;
|
||||
this->initSymtab(ObjSections, &Sec);
|
||||
this->initSymtab<ELFT>(ObjSections, &Sec);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -475,10 +476,10 @@ void ObjFile<ELFT>::initializeSections(
|
|||
break;
|
||||
}
|
||||
case SHT_SYMTAB:
|
||||
this->initSymtab(ObjSections, &Sec);
|
||||
this->initSymtab<ELFT>(ObjSections, &Sec);
|
||||
break;
|
||||
case SHT_SYMTAB_SHNDX:
|
||||
this->SymtabSHNDX = CHECK(Obj.getSHNDXTable(Sec, ObjSections), this);
|
||||
SymtabSHNDX = CHECK(Obj.getSHNDXTable(Sec, ObjSections), this);
|
||||
break;
|
||||
case SHT_STRTAB:
|
||||
case SHT_NULL:
|
||||
|
@ -678,12 +679,12 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
|
|||
}
|
||||
|
||||
if (Sec.sh_type == SHT_RELA) {
|
||||
ArrayRef<Elf_Rela> Rels = CHECK(this->getObj().relas(&Sec), this);
|
||||
ArrayRef<Elf_Rela> Rels = CHECK(getObj().relas(&Sec), this);
|
||||
Target->FirstRelocation = Rels.begin();
|
||||
Target->NumRelocations = Rels.size();
|
||||
Target->AreRelocsRela = true;
|
||||
} else {
|
||||
ArrayRef<Elf_Rel> Rels = CHECK(this->getObj().rels(&Sec), this);
|
||||
ArrayRef<Elf_Rel> Rels = CHECK(getObj().rels(&Sec), this);
|
||||
Target->FirstRelocation = Rels.begin();
|
||||
Target->NumRelocations = Rels.size();
|
||||
Target->AreRelocsRela = false;
|
||||
|
@ -771,19 +772,19 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
|
|||
|
||||
template <class ELFT>
|
||||
StringRef ObjFile<ELFT>::getSectionName(const Elf_Shdr &Sec) {
|
||||
return CHECK(this->getObj().getSectionName(&Sec, SectionStringTable), this);
|
||||
return CHECK(getObj().getSectionName(&Sec, SectionStringTable), this);
|
||||
}
|
||||
|
||||
template <class ELFT> void ObjFile<ELFT>::initializeSymbols() {
|
||||
this->Symbols.reserve(this->ELFSyms.size());
|
||||
for (const Elf_Sym &Sym : this->ELFSyms)
|
||||
this->Symbols.reserve(this->getELFSyms<ELFT>().size());
|
||||
for (const Elf_Sym &Sym : this->getELFSyms<ELFT>())
|
||||
this->Symbols.push_back(createSymbol(&Sym));
|
||||
}
|
||||
|
||||
template <class ELFT> Symbol *ObjFile<ELFT>::createSymbol(const Elf_Sym *Sym) {
|
||||
int Binding = Sym->getBinding();
|
||||
|
||||
uint32_t SecIdx = this->getSectionIndex(*Sym);
|
||||
uint32_t SecIdx = getSectionIndex(*Sym);
|
||||
if (SecIdx >= this->Sections.size())
|
||||
fatal(toString(this) + ": invalid section index: " + Twine(SecIdx));
|
||||
|
||||
|
@ -870,14 +871,16 @@ InputFile *ArchiveFile::fetch(const Archive::Symbol &Sym) {
|
|||
|
||||
template <class ELFT>
|
||||
SharedFile<ELFT>::SharedFile(MemoryBufferRef M, StringRef DefaultSoName)
|
||||
: ELFFileBase<ELFT>(Base::SharedKind, M), SoName(DefaultSoName),
|
||||
IsNeeded(!Config->AsNeeded) {}
|
||||
: ELFFileBase(SharedKind, M), SoName(DefaultSoName),
|
||||
IsNeeded(!Config->AsNeeded) {
|
||||
parseHeader<ELFT>();
|
||||
}
|
||||
|
||||
// Partially parse the shared object file so that we can call
|
||||
// getSoName on this object.
|
||||
template <class ELFT> void SharedFile<ELFT>::parseDynamic() {
|
||||
ArrayRef<Elf_Dyn> DynamicTags;
|
||||
const ELFFile<ELFT> Obj = this->getObj();
|
||||
const ELFFile<ELFT> Obj = this->getObj<ELFT>();
|
||||
ArrayRef<Elf_Shdr> Sections = CHECK(Obj.sections(), this);
|
||||
|
||||
// Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d.
|
||||
|
@ -886,7 +889,7 @@ template <class ELFT> void SharedFile<ELFT>::parseDynamic() {
|
|||
default:
|
||||
continue;
|
||||
case SHT_DYNSYM:
|
||||
this->initSymtab(Sections, &Sec);
|
||||
this->initSymtab<ELFT>(Sections, &Sec);
|
||||
break;
|
||||
case SHT_DYNAMIC:
|
||||
DynamicTags =
|
||||
|
@ -901,7 +904,7 @@ template <class ELFT> void SharedFile<ELFT>::parseDynamic() {
|
|||
}
|
||||
}
|
||||
|
||||
if (this->VersymSec && this->ELFSyms.empty())
|
||||
if (this->VersymSec && this->getELFSyms<ELFT>().empty())
|
||||
error("SHT_GNU_versym should be associated with symbol table");
|
||||
|
||||
// Search for a DT_SONAME tag to initialize this->SoName.
|
||||
|
@ -923,7 +926,7 @@ template <class ELFT> void SharedFile<ELFT>::parseDynamic() {
|
|||
// 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->ELFSyms.size() - this->FirstGlobal;
|
||||
size_t Size = this->getELFSyms<ELFT>().size() - this->FirstGlobal;
|
||||
if (!VersymSec)
|
||||
return std::vector<uint32_t>(Size, VER_NDX_GLOBAL);
|
||||
|
||||
|
@ -1001,7 +1004,7 @@ uint32_t SharedFile<ELFT>::getAlignment(ArrayRef<Elf_Shdr> Sections,
|
|||
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().sections(), this);
|
||||
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
|
||||
|
@ -1009,7 +1012,7 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() {
|
|||
SmallString<0> VersionedNameBuffer;
|
||||
|
||||
// Add symbols to the symbol table.
|
||||
ArrayRef<Elf_Sym> Syms = this->getGlobalELFSyms();
|
||||
ArrayRef<Elf_Sym> Syms = this->getGlobalELFSyms<ELFT>();
|
||||
for (size_t I = 0; I < Syms.size(); ++I) {
|
||||
const Elf_Sym &Sym = Syms[I];
|
||||
|
||||
|
@ -1347,11 +1350,6 @@ template void LazyObjFile::parse<ELF32BE>();
|
|||
template void LazyObjFile::parse<ELF64LE>();
|
||||
template void LazyObjFile::parse<ELF64BE>();
|
||||
|
||||
template class elf::ELFFileBase<ELF32LE>;
|
||||
template class elf::ELFFileBase<ELF32BE>;
|
||||
template class elf::ELFFileBase<ELF64LE>;
|
||||
template class elf::ELFFileBase<ELF64BE>;
|
||||
|
||||
template class elf::ObjFile<ELF32LE>;
|
||||
template class elf::ObjFile<ELF32BE>;
|
||||
template class elf::ObjFile<ELF64LE>;
|
||||
|
|
|
@ -145,35 +145,38 @@ private:
|
|||
const Kind FileKind;
|
||||
};
|
||||
|
||||
template <typename ELFT> class ELFFileBase : public InputFile {
|
||||
class ELFFileBase : public InputFile {
|
||||
public:
|
||||
using Elf_Shdr = typename ELFT::Shdr;
|
||||
using Elf_Sym = typename ELFT::Sym;
|
||||
using Elf_Word = typename ELFT::Word;
|
||||
using Elf_Sym_Range = typename ELFT::SymRange;
|
||||
|
||||
ELFFileBase(Kind K, MemoryBufferRef M);
|
||||
template <typename ELFT> void parseHeader();
|
||||
static bool classof(const InputFile *F) { return F->isElf(); }
|
||||
|
||||
llvm::object::ELFFile<ELFT> getObj() const {
|
||||
template <typename ELFT> llvm::object::ELFFile<ELFT> getObj() const {
|
||||
return check(llvm::object::ELFFile<ELFT>::create(MB.getBuffer()));
|
||||
}
|
||||
|
||||
StringRef getStringTable() const { return StringTable; }
|
||||
|
||||
Elf_Sym_Range getGlobalELFSyms();
|
||||
Elf_Sym_Range getELFSyms() const { return ELFSyms; }
|
||||
template <typename ELFT> typename ELFT::SymRange getELFSyms() const {
|
||||
return typename ELFT::SymRange(
|
||||
reinterpret_cast<const typename ELFT::Sym *>(ELFSyms), NumELFSyms);
|
||||
}
|
||||
template <typename ELFT> typename ELFT::SymRange getGlobalELFSyms() const {
|
||||
return getELFSyms<ELFT>().slice(FirstGlobal);
|
||||
}
|
||||
|
||||
protected:
|
||||
ArrayRef<Elf_Sym> ELFSyms;
|
||||
const void *ELFSyms = nullptr;
|
||||
size_t NumELFSyms = 0;
|
||||
uint32_t FirstGlobal = 0;
|
||||
StringRef StringTable;
|
||||
void initSymtab(ArrayRef<Elf_Shdr> Sections, const Elf_Shdr *Symtab);
|
||||
template <typename ELFT>
|
||||
void initSymtab(ArrayRef<typename ELFT::Shdr> Sections,
|
||||
const typename ELFT::Shdr *Symtab);
|
||||
};
|
||||
|
||||
// .o file.
|
||||
template <class ELFT> class ObjFile : public ELFFileBase<ELFT> {
|
||||
using Base = ELFFileBase<ELFT>;
|
||||
template <class ELFT> class ObjFile : public ELFFileBase {
|
||||
using Elf_Rel = typename ELFT::Rel;
|
||||
using Elf_Rela = typename ELFT::Rela;
|
||||
using Elf_Sym = typename ELFT::Sym;
|
||||
|
@ -185,7 +188,11 @@ template <class ELFT> class ObjFile : public ELFFileBase<ELFT> {
|
|||
const Elf_Shdr &Sec);
|
||||
|
||||
public:
|
||||
static bool classof(const InputFile *F) { return F->kind() == Base::ObjKind; }
|
||||
static bool classof(const InputFile *F) { return F->kind() == ObjKind; }
|
||||
|
||||
llvm::object::ELFFile<ELFT> getObj() const {
|
||||
return this->ELFFileBase::getObj<ELFT>();
|
||||
}
|
||||
|
||||
ArrayRef<Symbol *> getLocalSymbols();
|
||||
ArrayRef<Symbol *> getGlobalSymbols();
|
||||
|
@ -321,8 +328,7 @@ public:
|
|||
};
|
||||
|
||||
// .so file.
|
||||
template <class ELFT> class SharedFile : public ELFFileBase<ELFT> {
|
||||
using Base = ELFFileBase<ELFT>;
|
||||
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;
|
||||
|
@ -338,9 +344,7 @@ public:
|
|||
std::vector<StringRef> DtNeeded;
|
||||
std::string SoName;
|
||||
|
||||
static bool classof(const InputFile *F) {
|
||||
return F->kind() == Base::SharedKind;
|
||||
}
|
||||
static bool classof(const InputFile *F) { return F->kind() == SharedKind; }
|
||||
|
||||
SharedFile(MemoryBufferRef M, StringRef DefaultSoName);
|
||||
|
||||
|
|
|
@ -483,7 +483,8 @@ template <class ELFT> static bool isReadOnly(SharedSymbol &SS) {
|
|||
|
||||
// Determine if the symbol is read-only by scanning the DSO's program headers.
|
||||
const SharedFile<ELFT> &File = SS.getFile<ELFT>();
|
||||
for (const Elf_Phdr &Phdr : check(File.getObj().program_headers()))
|
||||
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) &&
|
||||
!(Phdr.p_flags & ELF::PF_W) && SS.Value >= Phdr.p_vaddr &&
|
||||
SS.Value < Phdr.p_vaddr + Phdr.p_memsz)
|
||||
|
@ -503,7 +504,7 @@ static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &SS) {
|
|||
SharedFile<ELFT> &File = SS.getFile<ELFT>();
|
||||
|
||||
SmallSet<SharedSymbol *, 4> Ret;
|
||||
for (const Elf_Sym &S : File.getGlobalELFSyms()) {
|
||||
for (const Elf_Sym &S : File.template getGlobalELFSyms<ELFT>()) {
|
||||
if (S.st_shndx == SHN_UNDEF || S.st_shndx == SHN_ABS ||
|
||||
S.getType() == STT_TLS || S.st_value != SS.Value)
|
||||
continue;
|
||||
|
|
Loading…
Reference in New Issue