[llvm] 3249bfd - [llvm-readobj] - Don't crash when a broken GNU hash table is dumped with --hash-symbols.
Georgii Rymar via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 24 05:56:22 PDT 2020
Author: Georgii Rymar
Date: 2020-06-24T15:55:43+03:00
New Revision: 3249bfda9678724207803ce675505ffbfa65a372
URL: https://github.com/llvm/llvm-project/commit/3249bfda9678724207803ce675505ffbfa65a372
DIFF: https://github.com/llvm/llvm-project/commit/3249bfda9678724207803ce675505ffbfa65a372.diff
LOG: [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
Added:
Modified:
llvm/test/tools/llvm-readobj/ELF/hash-symbols.test
llvm/tools/llvm-readobj/ELFDumper.cpp
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-readobj/ELF/hash-symbols.test b/llvm/test/tools/llvm-readobj/ELF/hash-symbols.test
index dd0d9e398174..edd3c1e9b84c 100644
--- a/llvm/test/tools/llvm-readobj/ELF/hash-symbols.test
+++ b/llvm/test/tools/llvm-readobj/ELF/hash-symbols.test
@@ -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
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index e38ae9d56fb3..b424918a8d4b 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -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;
}
}
}
More information about the llvm-commits
mailing list