1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

[llvm-readobj] - Split the printHashSymbols. NFCI.

This introduces `printHashTableSymbols` and
`printGNUHashTableSymbols` to split the `printHashSymbols`.

It makes the code more readable and consistent.

Differential revision: https://reviews.llvm.org/D83040
This commit is contained in:
Georgii Rymar 2020-07-02 15:01:35 +03:00
parent a7ecd67d40
commit 120dc4c2d4

View File

@ -851,6 +851,10 @@ private:
void printHashHistogram(const Elf_Hash &HashTable);
void printGnuHashHistogram(const Elf_GnuHash &GnuHashTable);
void printHashTableSymbols(const ELFO *Obj, const Elf_Hash &HashTable);
void printGnuHashTableSymbols(const ELFO *Obj,
const Elf_GnuHash &GnuHashTable);
struct Field {
std::string Str;
unsigned Column;
@ -4068,78 +4072,62 @@ void GNUStyle<ELFT>::printSymbols(const ELFO *Obj, bool PrintSymbols,
this->dumper()->printSymbolsHelper(false);
}
template <class ELFT> void GNUStyle<ELFT>::printHashSymbols(const ELFO *Obj) {
if (this->dumper()->getDynamicStringTable().empty())
return;
auto StringTable = this->dumper()->getDynamicStringTable();
Elf_Sym_Range DynSyms = this->dumper()->dynamic_symbols();
auto PrintHashTable = [&](const Elf_Hash *SysVHash) {
if (ELFT::Is64Bits)
OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
else
OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
OS << "\n";
const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0];
if (!FirstSym) {
Optional<DynRegionInfo> DynSymRegion = this->dumper()->getDynSymRegion();
this->reportUniqueWarning(
createError(Twine("unable to print symbols for the .hash table: the "
"dynamic symbol table ") +
(DynSymRegion ? "is empty" : "was not found")));
return;
}
auto Buckets = SysVHash->buckets();
auto Chains = SysVHash->chains();
for (uint32_t Buc = 0; Buc < SysVHash->nbucket; Buc++) {
if (Buckets[Buc] == ELF::STN_UNDEF)
continue;
std::vector<bool> Visited(SysVHash->nchain);
for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash->nchain; Ch = Chains[Ch]) {
if (Ch == ELF::STN_UNDEF)
break;
if (Visited[Ch]) {
reportWarning(
createError(".hash section is invalid: bucket " + Twine(Ch) +
": a cycle was detected in the linked chain"),
this->FileName);
break;
}
printHashedSymbol(Obj, FirstSym, Ch, StringTable, Buc);
Visited[Ch] = true;
}
}
};
if (const Elf_Hash *SysVHash = this->dumper()->getHashTable()) {
OS << "\n Symbol table of .hash for image:\n";
if (Error E = checkHashTable<ELFT>(Obj, SysVHash))
this->reportUniqueWarning(std::move(E));
else
PrintHashTable(SysVHash);
}
// Try printing the .gnu.hash table.
const Elf_GnuHash *GnuHash = this->dumper()->getGnuHashTable();
if (!GnuHash)
template <class ELFT>
void GNUStyle<ELFT>::printHashTableSymbols(const ELFO *Obj,
const Elf_Hash &SysVHash) {
StringRef StringTable = this->dumper()->getDynamicStringTable();
if (StringTable.empty())
return;
OS << "\n Symbol table of .gnu.hash for image:\n";
if (ELFT::Is64Bits)
OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
else
OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
OS << "\n";
if (Error E = checkGNUHashTable<ELFT>(Obj, GnuHash)) {
this->reportUniqueWarning(std::move(E));
Elf_Sym_Range DynSyms = this->dumper()->dynamic_symbols();
const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0];
if (!FirstSym) {
Optional<DynRegionInfo> DynSymRegion = this->dumper()->getDynSymRegion();
this->reportUniqueWarning(
createError(Twine("unable to print symbols for the .hash table: the "
"dynamic symbol table ") +
(DynSymRegion ? "is empty" : "was not found")));
return;
}
auto Buckets = SysVHash.buckets();
auto Chains = SysVHash.chains();
for (uint32_t Buc = 0; Buc < SysVHash.nbucket; Buc++) {
if (Buckets[Buc] == ELF::STN_UNDEF)
continue;
std::vector<bool> Visited(SysVHash.nchain);
for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash.nchain; Ch = Chains[Ch]) {
if (Ch == ELF::STN_UNDEF)
break;
if (Visited[Ch]) {
reportWarning(createError(".hash section is invalid: bucket " +
Twine(Ch) +
": a cycle was detected in the linked chain"),
this->FileName);
break;
}
printHashedSymbol(Obj, FirstSym, Ch, StringTable, Buc);
Visited[Ch] = true;
}
}
}
template <class ELFT>
void GNUStyle<ELFT>::printGnuHashTableSymbols(const ELFO *Obj,
const Elf_GnuHash &GnuHash) {
StringRef StringTable = this->dumper()->getDynamicStringTable();
if (StringTable.empty())
return;
Elf_Sym_Range DynSyms = this->dumper()->dynamic_symbols();
const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0];
if (!FirstSym) {
Optional<DynRegionInfo> DynSymRegion = this->dumper()->getDynSymRegion();
@ -4150,22 +4138,47 @@ template <class ELFT> void GNUStyle<ELFT>::printHashSymbols(const ELFO *Obj) {
return;
}
auto Buckets = GnuHash->buckets();
for (uint32_t Buc = 0; Buc < GnuHash->nbuckets; Buc++) {
ArrayRef<Elf_Word> Buckets = GnuHash.buckets();
for (uint32_t Buc = 0; Buc < GnuHash.nbuckets; Buc++) {
if (Buckets[Buc] == ELF::STN_UNDEF)
continue;
uint32_t Index = Buckets[Buc];
uint32_t GnuHashable = Index - GnuHash->symndx;
uint32_t GnuHashable = Index - GnuHash.symndx;
// Print whole chain
while (true) {
printHashedSymbol(Obj, FirstSym, Index++, StringTable, Buc);
// Chain ends at symbol with stopper bit
if ((GnuHash->values(DynSyms.size())[GnuHashable++] & 1) == 1)
if ((GnuHash.values(DynSyms.size())[GnuHashable++] & 1) == 1)
break;
}
}
}
template <class ELFT> void GNUStyle<ELFT>::printHashSymbols(const ELFO *Obj) {
if (const Elf_Hash *SysVHash = this->dumper()->getHashTable()) {
OS << "\n Symbol table of .hash for image:\n";
if (Error E = checkHashTable<ELFT>(Obj, SysVHash))
this->reportUniqueWarning(std::move(E));
else
printHashTableSymbols(Obj, *SysVHash);
}
// Try printing the .gnu.hash table.
if (const Elf_GnuHash *GnuHash = this->dumper()->getGnuHashTable()) {
OS << "\n Symbol table of .gnu.hash for image:\n";
if (ELFT::Is64Bits)
OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
else
OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
OS << "\n";
if (Error E = checkGNUHashTable<ELFT>(Obj, GnuHash))
this->reportUniqueWarning(std::move(E));
else
printGnuHashTableSymbols(Obj, *GnuHash);
}
}
static inline std::string printPhdrFlags(unsigned Flag) {
std::string Str;
Str = (Flag & PF_R) ? "R" : " ";