1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[llvm-readobj] - Don't crash when a broken GNU hash table is dumped with --hash-symbols.

Start using the `checkGNUHashTable` helper which was recently introduced to report
a proper warning when a GNU hash table goes past the end of the file.

Differential revision: https://reviews.llvm.org/D82449
This commit is contained in:
Georgii Rymar 2020-06-24 13:23:04 +03:00
parent cd7882baaf
commit 2c089a8181
2 changed files with 90 additions and 21 deletions

View File

@ -448,3 +448,64 @@ ProgramHeaders:
Sections:
- Section: .hash
- Section: .dynamic
## Check we report a proper warning when a GNU hash table goes past the end of the file.
## Case A: the 'nbuckets' field is set so that the table goes past the end of the file.
# RUN: yaml2obj --docnum=8 -D MASKWORDS=4294967295 -D NBUCKETS=3 %s -o %t.err.maskwords
# RUN: llvm-readelf --hash-symbols %t.err.maskwords 2>&1 | \
# RUN: FileCheck %s -DFILE=%t.err.maskwords -DMASKWORDS=4294967295 -DNBUCKETS=3 --check-prefix=ERR4
# ERR4: Symbol table of .gnu.hash for image:
# ERR4-NEXT: Num Buc: Value Size Type Bind Vis Ndx Name
# ERR4-NEXT: warning: '[[FILE]]': unable to dump the SHT_GNU_HASH section at 0x78: it goes past the end of the file
## Case B: the 'maskwords' field is set so that the table goes past the end of the file.
# RUN: yaml2obj --docnum=8 -D MASKWORDS=2 -D NBUCKETS=4294967295 %s -o %t.err.nbuckets
# RUN: llvm-readelf --hash-symbols %t.err.nbuckets 2>&1 | \
# RUN: FileCheck %s -DFILE=%t.err.nbuckets -DMASKWORDS=2 -DNBUCKETS=4294967295 --check-prefix=ERR4
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .gnu.hash
Type: SHT_GNU_HASH
Flags: [ SHF_ALLOC ]
Header:
SymNdx: 0x1
Shift2: 0x2
## The number of words in the Bloom filter. The value of 2 is no-op.
MaskWords: [[MASKWORDS]]
## The number of hash buckets. The value of 3 is no-op.
NBuckets: [[NBUCKETS]]
BloomFilter: [0x3, 0x4]
HashBuckets: [0x5, 0x6, 0x7]
HashValues: [0x8, 0x9, 0xA, 0xB]
- Name: .dynamic
Type: SHT_DYNAMIC
Flags: [ SHF_ALLOC ]
Link: .dynstr
Entries:
- Tag: DT_GNU_HASH
Value: 0x0
- Tag: DT_NULL
Value: 0x0
DynamicSymbols:
- Name: aaa
Binding: STB_GLOBAL
- Name: bbb
Binding: STB_GLOBAL
- Name: ccc
Binding: STB_GLOBAL
- Name: ddd
Binding: STB_GLOBAL
ProgramHeaders:
- Type: PT_LOAD
Flags: [ PF_R, PF_X ]
Sections:
- Section: .gnu.hash
- Section: .dynamic

View File

@ -4069,27 +4069,35 @@ template <class ELFT> void GNUStyle<ELFT>::printHashSymbols(const ELFO *Obj) {
PrintHashTable(SysVHash);
}
// Try printing .gnu.hash
if (auto 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";
auto 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;
// Print whole chain
while (true) {
printHashedSymbol(Obj, &DynSyms[0], Index++, StringTable, Buc);
// Chain ends at symbol with stopper bit
if ((GnuHash->values(DynSyms.size())[GnuHashable++] & 1) == 1)
break;
}
// Try printing the .gnu.hash table.
const Elf_GnuHash *GnuHash = this->dumper()->getGnuHashTable();
if (!GnuHash)
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));
return;
}
auto 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;
// Print whole chain
while (true) {
printHashedSymbol(Obj, &DynSyms[0], Index++, StringTable, Buc);
// Chain ends at symbol with stopper bit
if ((GnuHash->values(DynSyms.size())[GnuHashable++] & 1) == 1)
break;
}
}
}