[llvm] r374344 - [llvm-readelf] - Do not enter an infinite loop when printing histogram.
George Rimar via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 10 06:26:26 PDT 2019
Author: grimar
Date: Thu Oct 10 06:26:26 2019
New Revision: 374344
URL: http://llvm.org/viewvc/llvm-project?rev=374344&view=rev
Log:
[llvm-readelf] - Do not enter an infinite loop when printing histogram.
This is similar to D68086.
We are entering an infinite loop when dumping a histogram for a specially crafted
.hash section with a loop in a chain.
Differential revision: https://reviews.llvm.org/D68771
Modified:
llvm/trunk/test/tools/llvm-readobj/elf-hash-histogram.test
llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
Modified: llvm/trunk/test/tools/llvm-readobj/elf-hash-histogram.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/elf-hash-histogram.test?rev=374344&r1=374343&r2=374344&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/elf-hash-histogram.test (original)
+++ llvm/trunk/test/tools/llvm-readobj/elf-hash-histogram.test Thu Oct 10 06:26:26 2019
@@ -1,27 +1,70 @@
-RUN: llvm-readelf --elf-hash-histogram %p/Inputs/gnuhash.so.elf-ppc64 \
-RUN: | FileCheck %s -check-prefix PPC64GNU
-RUN: llvm-readelf --elf-hash-histogram %p/Inputs/gnuhash.so.elf-x86_64 \
-RUN: | FileCheck %s -check-prefix X86GNU
-RUN: llvm-readelf --elf-hash-histogram %p/Inputs/got-plt.exe.elf-mipsel \
-RUN: | FileCheck %s -check-prefix SYSV
-
-PPC64GNU: Histogram for `.gnu.hash' bucket list length (total of 3 buckets)
-PPC64GNU-NEXT: Length Number % of total Coverage
-PPC64GNU-NEXT: 0 1 ( 33.3%) 0.0%
-PPC64GNU-NEXT: 1 1 ( 33.3%) 25.0%
-PPC64GNU-NEXT: 2 0 ( 0.0%) 25.0%
-PPC64GNU-NEXT: 3 1 ( 33.3%) 100.0%
-
-X86GNU: Histogram for `.gnu.hash' bucket list length (total of 3 buckets)
-X86GNU-NEXT: Length Number % of total Coverage
-X86GNU-NEXT: 0 1 ( 33.3%) 0.0%
-X86GNU-NEXT: 1 1 ( 33.3%) 25.0%
-X86GNU-NEXT: 2 0 ( 0.0%) 25.0%
-X86GNU-NEXT: 3 1 ( 33.3%) 100.0%
-
-SYSV: Histogram for bucket list length (total of 3 buckets)
-SYSV-NEXT: Length Number % of total Coverage
-SYSV-NEXT: 0 0 ( 0.0%) 0.0%
-SYSV-NEXT: 1 0 ( 0.0%) 0.0%
-SYSV-NEXT: 2 2 ( 66.7%) 57.1%
-SYSV-NEXT: 3 1 ( 33.3%) 100.0%
+# RUN: llvm-readelf --elf-hash-histogram %p/Inputs/gnuhash.so.elf-ppc64 \
+# RUN: | FileCheck %s -check-prefix PPC64GNU
+# RUN: llvm-readelf --elf-hash-histogram %p/Inputs/gnuhash.so.elf-x86_64 \
+# RUN: | FileCheck %s -check-prefix X86GNU
+# RUN: llvm-readelf --elf-hash-histogram %p/Inputs/got-plt.exe.elf-mipsel \
+# RUN: | FileCheck %s -check-prefix SYSV
+
+# PPC64GNU: Histogram for `.gnu.hash' bucket list length (total of 3 buckets)
+# PPC64GNU-NEXT: Length Number % of total Coverage
+# PPC64GNU-NEXT: 0 1 ( 33.3%) 0.0%
+# PPC64GNU-NEXT: 1 1 ( 33.3%) 25.0%
+# PPC64GNU-NEXT: 2 0 ( 0.0%) 25.0%
+# PPC64GNU-NEXT: 3 1 ( 33.3%) 100.0%
+
+# X86GNU: Histogram for `.gnu.hash' bucket list length (total of 3 buckets)
+# X86GNU-NEXT: Length Number % of total Coverage
+# X86GNU-NEXT: 0 1 ( 33.3%) 0.0%
+# X86GNU-NEXT: 1 1 ( 33.3%) 25.0%
+# X86GNU-NEXT: 2 0 ( 0.0%) 25.0%
+# X86GNU-NEXT: 3 1 ( 33.3%) 100.0%
+
+# SYSV: Histogram for bucket list length (total of 3 buckets)
+# SYSV-NEXT: Length Number % of total Coverage
+# SYSV-NEXT: 0 0 ( 0.0%) 0.0%
+# SYSV-NEXT: 1 0 ( 0.0%) 0.0%
+# SYSV-NEXT: 2 2 ( 66.7%) 57.1%
+# SYSV-NEXT: 3 1 ( 33.3%) 100.0%
+
+## Show that we report a warning for a hash table which contains an entry of
+## the bucket array pointing to a cycle.
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: llvm-readelf --elf-hash-histogram 2>&1 %t.o | FileCheck -DFILE=%t.o %s --check-prefix BROKEN
+
+# BROKEN: warning: '[[FILE]]': .hash section is invalid: bucket 1: a cycle was detected in the linked chain
+# BROKEN: Histogram for bucket list length (total of 1 buckets)
+# BROKEN-NEXT: Length Number % of total Coverage
+# BROKEN-NEXT: 0 0 ( 0.0%) 0.0%
+# BROKEN-NEXT: 1 1 (100.0%) 100.0%
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_386
+Sections:
+ - Name: .hash
+ Type: SHT_HASH
+ Link: .dynsym
+ Bucket: [ 1 ]
+ Chain: [ 0, 1 ]
+ - Name: .dynamic
+ Type: SHT_DYNAMIC
+ Flags: [ SHF_ALLOC ]
+ Entries:
+## llvm-readelf will read the hash table from the file offset
+## p_offset + (p_vaddr - DT_HASH) = p_offset + (0 - 0) = p_offset,
+## which is the start of PT_LOAD, i.e. the file offset of .hash.
+ - Tag: DT_HASH
+ Value: 0x0
+ - Tag: DT_NULL
+ Value: 0
+DynamicSymbols:
+ - Name: foo
+ProgramHeaders:
+ - Type: PT_LOAD
+ Sections:
+ - Section: .hash
+ - Section: .dynamic
Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFDumper.cpp?rev=374344&r1=374343&r2=374344&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Thu Oct 10 06:26:26 2019
@@ -3968,9 +3968,21 @@ void GNUStyle<ELFT>::printHashHistogram(
// Go over all buckets and and note chain lengths of each bucket (total
// unique chain lengths).
for (size_t B = 0; B < NBucket; B++) {
- for (size_t C = Buckets[B]; C > 0 && C < NChain; C = Chains[C])
+ std::vector<bool> Visited(NChain);
+ for (size_t C = Buckets[B]; C < NChain; C = Chains[C]) {
+ if (C == ELF::STN_UNDEF)
+ break;
+ if (Visited[C]) {
+ reportWarning(
+ createError(".hash section is invalid: bucket " + Twine(C) +
+ ": a cycle was detected in the linked chain"),
+ this->FileName);
+ break;
+ }
+ Visited[C] = true;
if (MaxChain <= ++ChainLen[B])
MaxChain++;
+ }
TotalSyms += ChainLen[B];
}
More information about the llvm-commits
mailing list