Change how we store the symbol table.

Instead of remembering a raw Elf_Shdr, store the symbol table proper
and the index of the first non local.

This moves error handling upfront and simplifies it.

llvm-svn: 285933
This commit is contained in:
Rafael Espindola 2016-11-03 16:55:44 +00:00
parent 2a6eb47202
commit 6dcf4c6859
2 changed files with 20 additions and 27 deletions

View File

@ -127,28 +127,24 @@ ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef MB)
template <class ELFT>
typename ELFT::SymRange ELFFileBase<ELFT>::getElfSymbols(bool OnlyGlobals) {
if (!Symtab)
return Elf_Sym_Range(nullptr, nullptr);
Elf_Sym_Range Syms = check(ELFObj.symbols(Symtab));
uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
uint32_t FirstNonLocal = Symtab->sh_info;
if (FirstNonLocal == 0 || FirstNonLocal > NumSymbols)
fatal(getFilename(this) + ": invalid sh_info in symbol table");
if (OnlyGlobals)
return makeArrayRef(Syms.begin() + FirstNonLocal, Syms.end());
return makeArrayRef(Syms.begin(), Syms.end());
return makeArrayRef(Symbols.begin() + FirstNonLocal, Symbols.end());
return Symbols;
}
template <class ELFT>
uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const {
return check(ELFObj.getSectionIndex(&Sym, Symtab, SymtabSHNDX));
return check(ELFObj.getSectionIndex(&Sym, Symbols, SymtabSHNDX));
}
template <class ELFT>
void ELFFileBase<ELFT>::initSymtab(ArrayRef<Elf_Shdr> Sections,
const Elf_Shdr *Symtab) {
this->Symtab = Symtab;
FirstNonLocal = Symtab->sh_info;
Symbols = check(ELFObj.symbols(Symtab));
if (FirstNonLocal == 0 || FirstNonLocal > Symbols.size())
fatal(getFilename(this) + ": invalid sh_info in symbol table");
StringTable = check(ELFObj.getStringTableForSymtab(*Symtab, Sections));
}
@ -158,23 +154,19 @@ elf::ObjectFile<ELFT>::ObjectFile(MemoryBufferRef M)
template <class ELFT>
ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getNonLocalSymbols() {
if (!this->Symtab)
return this->SymbolBodies;
uint32_t FirstNonLocal = this->Symtab->sh_info;
return makeArrayRef(this->SymbolBodies).slice(FirstNonLocal);
return makeArrayRef(this->SymbolBodies).slice(this->FirstNonLocal);
}
template <class ELFT>
ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getLocalSymbols() {
if (!this->Symtab)
if (this->SymbolBodies.empty())
return this->SymbolBodies;
uint32_t FirstNonLocal = this->Symtab->sh_info;
return makeArrayRef(this->SymbolBodies).slice(1, FirstNonLocal - 1);
return makeArrayRef(this->SymbolBodies).slice(1, this->FirstNonLocal - 1);
}
template <class ELFT>
ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getSymbols() {
if (!this->Symtab)
if (this->SymbolBodies.empty())
return this->SymbolBodies;
return makeArrayRef(this->SymbolBodies).slice(1);
}
@ -202,11 +194,11 @@ template <class ELFT>
StringRef
elf::ObjectFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,
const Elf_Shdr &Sec) {
const ELFFile<ELFT> &Obj = this->ELFObj;
if (!this->Symtab)
if (this->Symbols.empty())
this->initSymtab(Sections,
check(object::getSection<ELFT>(Sections, Sec.sh_link)));
const Elf_Sym *Sym = check(Obj.getSymbol(this->Symtab, Sec.sh_info));
const Elf_Sym *Sym =
check(object::getSymbol<ELFT>(this->Symbols, Sec.sh_info));
return check(Sym->getName(this->StringTable));
}
@ -558,7 +550,7 @@ SharedFile<ELFT>::SharedFile(MemoryBufferRef M)
template <class ELFT>
const typename ELFT::Shdr *
SharedFile<ELFT>::getSection(const Elf_Sym &Sym) const {
return check(this->ELFObj.getSection(&Sym, this->Symtab, this->SymtabSHNDX));
return check(this->ELFObj.getSection(&Sym, this->Symbols, this->SymtabSHNDX));
}
// Partially parse the shared object file so that we can call
@ -592,7 +584,7 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() {
}
}
if (this->VersymSec && !this->Symtab)
if (this->VersymSec && this->Symbols.empty())
error("SHT_GNU_versym should be associated with symbol table");
// DSOs are identified by soname, and they usually contain
@ -634,7 +626,7 @@ SharedFile<ELFT>::parseVerdefs(const Elf_Versym *&Versym) {
// The location of the first global versym entry.
Versym = reinterpret_cast<const Elf_Versym *>(this->ELFObj.base() +
VersymSec->sh_offset) +
this->Symtab->sh_info;
this->FirstNonLocal;
// We cannot determine the largest verdef identifier without inspecting
// every Elf_Verdef, but both bfd and gold assign verdef identifiers

View File

@ -111,7 +111,8 @@ public:
protected:
llvm::object::ELFFile<ELFT> ELFObj;
const Elf_Shdr *Symtab = nullptr;
ArrayRef<Elf_Sym> Symbols;
uint32_t FirstNonLocal = 0;
ArrayRef<Elf_Word> SymtabSHNDX;
StringRef StringTable;
void initSymtab(ArrayRef<Elf_Shdr> Sections, const Elf_Shdr *Symtab);