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:
parent
cd7882baaf
commit
2c089a8181
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user