477 lines · plain
1## Here we test the --elf-hash-histogram command line option.2 3## This test case checks how we built histograms for hash sections.4 5# RUN: yaml2obj --docnum=1 -D BITS=32 %s -o %t1-32.o6# RUN: llvm-readelf --elf-hash-histogram %t1-32.o | FileCheck %s --check-prefix=HIST7 8## Test --histogram and -I aliases.9# RUN: llvm-readelf --histogram %t1-32.o | FileCheck %s --check-prefix=HIST10# RUN: llvm-readelf -I %t1-32.o | FileCheck %s --check-prefix=HIST11 12# RUN: yaml2obj --docnum=1 -D BITS=64 %s -o %t1-64.o13# RUN: llvm-readelf --elf-hash-histogram %t1-64.o | FileCheck %s --check-prefix=HIST14 15## Check that LLVM output has the expected format.16# RUN: llvm-readobj --elf-hash-histogram %t1-32.o | FileCheck %s --check-prefix=LLVM-HIST17# RUN: llvm-readobj --elf-hash-histogram %t1-64.o | FileCheck %s --check-prefix=LLVM-HIST18 19# HIST: Histogram for bucket list length (total of 3 buckets)20# HIST-NEXT: Length Number % of total Coverage21# HIST-NEXT: 0 2 ( 66.7%) 0.0%22# HIST-NEXT: 1 0 ( 0.0%) 0.0%23# HIST-NEXT: 2 0 ( 0.0%) 0.0%24# HIST-NEXT: 3 1 ( 33.3%) 100.0%25# HIST-NEXT: Histogram for `.gnu.hash' bucket list length (total of 3 buckets)26# HIST-NEXT: Length Number % of total Coverage27# HIST-NEXT: 0 1 ( 33.3%) 0.0%28# HIST-NEXT: 1 1 ( 33.3%) 25.0%29# HIST-NEXT: 2 0 ( 0.0%) 25.0%30# HIST-NEXT: 3 1 ( 33.3%) 100.0%31# HIST-NOT: {{.}}32 33# LLVM-HIST: HashHistogram {34# LLVM-HIST-NEXT: TotalBuckets: 335# LLVM-HIST-NEXT: Chains [36# LLVM-HIST-NEXT: Chain {37# LLVM-HIST-NEXT: Length: 038# LLVM-HIST-NEXT: Count: 239# LLVM-HIST-NEXT: Percentage: 66.740# LLVM-HIST-NEXT: Coverage: 0.041# LLVM-HIST-NEXT: }42# LLVM-HIST-NEXT: Chain {43# LLVM-HIST-NEXT: Length: 144# LLVM-HIST-NEXT: Count: 045# LLVM-HIST-NEXT: Percentage: 0.046# LLVM-HIST-NEXT: Coverage: 0.047# LLVM-HIST-NEXT: }48# LLVM-HIST-NEXT: Chain {49# LLVM-HIST-NEXT: Length: 250# LLVM-HIST-NEXT: Count: 051# LLVM-HIST-NEXT: Percentage: 0.052# LLVM-HIST-NEXT: Coverage: 0.053# LLVM-HIST-NEXT: }54# LLVM-HIST-NEXT: Chain {55# LLVM-HIST-NEXT: Length: 356# LLVM-HIST-NEXT: Count: 157# LLVM-HIST-NEXT: Percentage: 33.358# LLVM-HIST-NEXT: Coverage: 100.059# LLVM-HIST-NEXT: }60# LLVM-HIST-NEXT: ]61# LLVM-HIST-NEXT: }62# LLVM-HIST-NEXT: GnuHashHistogram {63# LLVM-HIST-NEXT: TotalBuckets: 364# LLVM-HIST-NEXT: Buckets [65# LLVM-HIST-NEXT: Bucket {66# LLVM-HIST-NEXT: Length: 067# LLVM-HIST-NEXT: Count: 168# LLVM-HIST-NEXT: Percentage: 33.369# LLVM-HIST-NEXT: Coverage: 0.070# LLVM-HIST-NEXT: }71# LLVM-HIST-NEXT: Bucket {72# LLVM-HIST-NEXT: Length: 173# LLVM-HIST-NEXT: Count: 174# LLVM-HIST-NEXT: Percentage: 33.375# LLVM-HIST-NEXT: Coverage: 25.076# LLVM-HIST-NEXT: }77# LLVM-HIST-NEXT: Bucket {78# LLVM-HIST-NEXT: Length: 279# LLVM-HIST-NEXT: Count: 080# LLVM-HIST-NEXT: Percentage: 0.081# LLVM-HIST-NEXT: Coverage: 25.082# LLVM-HIST-NEXT: }83# LLVM-HIST-NEXT: Bucket {84# LLVM-HIST-NEXT: Length: 385# LLVM-HIST-NEXT: Count: 186# LLVM-HIST-NEXT: Percentage: 33.387# LLVM-HIST-NEXT: Coverage: 100.088# LLVM-HIST-NEXT: }89# LLVM-HIST-NEXT: ]90# LLVM-HIST-NEXT: }91 92--- !ELF93FileHeader:94 Class: ELFCLASS[[BITS]]95 Data: ELFDATA2LSB96 Type: ET_DYN97Sections:98 - Name: .hash99 Type: SHT_HASH100 Flags: [ SHF_ALLOC ]101 Bucket: [ 6, 4, 5 ]102 Chain: [ 0, 0, 1, 0, 2 ]103 - Name: .gnu.hash104 Type: SHT_GNU_HASH105 Flags: [ SHF_ALLOC ]106 Header:107 SymNdx: 0x1108 Shift2: 0x0109 BloomFilter: [ 0x0 ]110 HashBuckets: [ 0x00000001, 0x00000004, 0x00000000 ]111 HashValues: [ 0x0B887388, 0xECD54542, 0x7C92E3BB, 0x1C5871D9 ]112 - Name: .dynamic113 Type: SHT_DYNAMIC114 Flags: [ SHF_WRITE, SHF_ALLOC ]115 Entries:116 - Tag: DT_HASH117 Value: 0x0118 - Tag: DT_GNU_HASH119## sizeof(.hash) == 0x28.120 Value: 0x28121 - Tag: DT_NULL122 Value: 0x0123DynamicSymbols:124 - Name: a125 - Name: b126 - Name: c127 - Name: d128ProgramHeaders:129 - Type: PT_LOAD130 FirstSec: .hash131 LastSec: .dynamic132 133## Show that we report a warning for a hash table which contains an entry of134## the bucket array pointing to a cycle.135 136# RUN: yaml2obj --docnum=2 %s -o %t2.o137# RUN: llvm-readelf --elf-hash-histogram 2>&1 %t2.o | \138# RUN: FileCheck -DFILE=%t2.o %s --check-prefix=BROKEN --implicit-check-not=warning:139 140# BROKEN: warning: '[[FILE]]': .hash section is invalid: bucket 1: a cycle was detected in the linked chain141# BROKEN: Histogram for bucket list length (total of 2 buckets)142# BROKEN-NEXT: Length Number % of total Coverage143# BROKEN-NEXT: 0 0 ( 0.0%) 0.0%144# BROKEN-NEXT: 1 2 (100.0%) 100.0%145 146--- !ELF147FileHeader:148 Class: ELFCLASS32149 Data: ELFDATA2LSB150 Type: ET_REL151Sections:152 - Name: .hash153 Type: SHT_HASH154 Link: .dynsym155 Bucket: [ 1, 1 ]156 Chain: [ 0, 1 ]157 - Name: .dynamic158 Type: SHT_DYNAMIC159 Flags: [ SHF_ALLOC ]160 Entries:161## llvm-readelf will read the hash table from the file offset162## p_offset + (p_vaddr - DT_HASH) = p_offset + (0 - 0) = p_offset,163## which is the start of PT_LOAD, i.e. the file offset of .hash.164 - Tag: DT_HASH165 Value: 0x0166 - Tag: DT_NULL167 Value: 0168DynamicSymbols:169 - Name: foo170ProgramHeaders:171 - Type: PT_LOAD172 FirstSec: .hash173 LastSec: .dynamic174 175## Each SHT_HASH section starts with two 32-bit fields: nbucket and nchain.176## Check we report an error when a DT_HASH value points to data that has size less than 8 bytes.177 178# RUN: yaml2obj --docnum=3 %s -o %t3.o179# RUN: llvm-readelf --elf-hash-histogram %t3.o 2>&1 | FileCheck %s --check-prefix=ERR1 -DFILE=%t3.o180 181# ERR1: warning: '[[FILE]]': the hash table at offset 0x2b1 goes past the end of the file (0x2b8){{$}}182 183--- !ELF184FileHeader:185 Class: ELFCLASS64186 Data: ELFDATA2LSB187 Type: ET_DYN188Sections:189 - Name: .hash190 Type: SHT_HASH191 Flags: [ SHF_ALLOC ]192 Bucket: [ 0 ]193 Chain: [ 0 ]194 - Name: .dynamic195 Type: SHT_DYNAMIC196 Flags: [ SHF_WRITE, SHF_ALLOC ]197 Entries:198 - Tag: DT_HASH199 Value: 0x239200 - Tag: DT_NULL201 Value: 0x0202DynamicSymbols: []203ProgramHeaders:204 - Type: PT_LOAD205 FileSize: 0x23a206 FirstSec: .hash207 LastSec: .dynamic208 209## Check we report a warning when the hash table goes past the end of the file.210 211## Case A.1: the hash table ends right before the EOF. We have a broken nbucket212## field that has a value larger than the number of buckets.213# RUN: yaml2obj --docnum=4 %s -o %t4.1.o -DNBUCKET=0x5d -DNCHAIN=0x1214# RUN: llvm-readelf --elf-hash-histogram %t4.1.o 2>&1 | \215# RUN: FileCheck %s --implicit-check-not={{.}} --allow-empty216 217## Case A.2: the hash table ends 1 byte past the EOF. We have a broken nbucket218## field that has a value larger than the number of buckets.219# RUN: yaml2obj --docnum=4 %s -o %t4.2.o -DNBUCKET=0x5e -DNCHAIN=0x1220# RUN: llvm-readelf --elf-hash-histogram %t4.2.o 2>&1 | \221# RUN: FileCheck %s --check-prefix=ERR2 -DFILE=%t4.2.o --implicit-check-not="warning:"222# ERR2: warning: '[[FILE]]': the hash table at offset 0x54 goes past the end of the file (0x1d4), nbucket = 94, nchain = 1{{$}}223 224## Case B.1: the hash table ends right before the EOF. We have a broken nchain225## field that has a value larger than the number of chains.226# RUN: yaml2obj --docnum=4 %s -o %t4.3.o -DNBUCKET=0x1 -DNCHAIN=0x5d227# RUN: llvm-readelf --elf-hash-histogram %t4.3.o 2>&1 | \228# RUN: FileCheck %s --check-prefix=ERR3 -DFILE=%t4.3.o --implicit-check-not="warning:"229# ERR3: warning: '[[FILE]]': hash table nchain (93) differs from symbol count derived from SHT_DYNSYM section header (1){{$}}230# ERR3: warning: '[[FILE]]': the size (0x5d0) of the dynamic symbol table at 0x78, derived from the hash table, goes past the end of the file (0x1d4) and will be ignored231 232## Case B.2: the hash table ends 1 byte past the EOF. We have a broken nchain233## field that has a value larger than the number of chains.234# RUN: yaml2obj --docnum=4 %s -o %t4.4.o -DNBUCKET=0x1 -DNCHAIN=0x5e235# RUN: llvm-readelf --elf-hash-histogram %t4.4.o 2>&1 | \236# RUN: FileCheck %s --check-prefix=ERR4 -DFILE=%t4.4.o --implicit-check-not="warning:"237# ERR4: warning: '[[FILE]]': hash table nchain (94) differs from symbol count derived from SHT_DYNSYM section header (1){{$}}238# ERR4: warning: '[[FILE]]': the size (0x5e0) of the dynamic symbol table at 0x78, derived from the hash table, goes past the end of the file (0x1d4) and will be ignored239# ERR4: warning: '[[FILE]]': the hash table at offset 0x54 goes past the end of the file (0x1d4), nbucket = 1, nchain = 94{{$}}240 241--- !ELF242FileHeader:243 Class: ELFCLASS32244 Data: ELFDATA2LSB245 Type: ET_DYN246Sections:247 - Name: .hash248 Type: SHT_HASH249 Flags: [ SHF_ALLOC ]250 Bucket: [ 0 ]251 NBucket: [[NBUCKET]]252 Chain: [ 0 ]253 NChain: [[NCHAIN]]254 - Name: .dynamic255 Type: SHT_DYNAMIC256 Flags: [ SHF_WRITE, SHF_ALLOC ]257 Entries:258 - Tag: DT_HASH259 Value: 0x0260 - Tag: DT_NULL261 Value: 0x0262DynamicSymbols: []263ProgramHeaders:264 - Type: PT_LOAD265 FirstSec: .hash266 LastSec: .dynamic267 268## Check we dump a histogram for the .gnu.hash table even when the .hash table is skipped.269 270## Case A: the .hash table has no data to build histogram and it is skipped.271# RUN: yaml2obj --docnum=5 %s -o %t5.o272# RUN: llvm-readelf --elf-hash-histogram %t5.o 2>&1 | \273# RUN: FileCheck %s --check-prefix=GNU-HASH --implicit-check-not="Histogram"274 275## Case B: the .hash table has a broken nbucket field. We report a warning276## and skip dumping of the .hash table.277# RUN: yaml2obj --docnum=5 -DNBUCKET=0xffffffff %s -o %t6.o278# RUN: llvm-readelf --elf-hash-histogram %t6.o 2>&1 | \279# RUN: FileCheck %s -DFILE=%t6.o --check-prefixes=WARN,GNU-HASH280 281# WARN: warning: '[[FILE]]': the hash table at offset 0x78 goes past the end of the file (0x358), nbucket = 4294967295, nchain = 2282# GNU-HASH: Histogram for `.gnu.hash' bucket list length (total of 3 buckets)283 284--- !ELF285FileHeader:286 Class: ELFCLASS64287 Data: ELFDATA2LSB288 Type: ET_DYN289Sections:290 - Name: .hash291 Type: SHT_HASH292 Flags: [ SHF_ALLOC ]293 Bucket: [ 0 ]294## 0x2 is a no-op: it does not change the number of buckets described by the "Bucket" key295 NBucket: [[NBUCKET=0x2]]296 Chain: [ 0, 0 ]297 - Name: .gnu.hash298 Type: SHT_GNU_HASH299 Flags: [ SHF_ALLOC ]300 Header:301 SymNdx: 0x1302 Shift2: 0x0303 BloomFilter: [ 0x0 ]304 HashBuckets: [ 0x00000001, 0x00000004, 0x00000000 ]305 HashValues: [ 0x0B887388 ]306 - Name: .dynamic307 Type: SHT_DYNAMIC308 Flags: [ SHF_WRITE, SHF_ALLOC ]309 Entries:310 - Tag: DT_HASH311 Value: 0x0312 - Tag: DT_GNU_HASH313## sizeof(.hash) == 0x14.314 Value: 0x14315 - Tag: DT_NULL316 Value: 0x0317DynamicSymbols:318 - Name: foo319ProgramHeaders:320 - Type: PT_LOAD321 FirstSec: .hash322 LastSec: .dynamic323 324## Check we report a proper warning when the GNU hash table goes past the end of the file.325 326## Case A: the 'maskwords' field is set so that the GNU hash table goes past the end of the file.327# RUN: yaml2obj --docnum=6 -D MASKWORDS=0x80000000 %s -o %t7328# RUN: llvm-readelf --elf-hash-histogram %t7 2>&1 | \329# RUN: FileCheck %s -DFILE=%t7 --check-prefix=ERR5 --implicit-check-not="Histogram"330 331# ERR5: warning: '[[FILE]]': unable to dump the SHT_GNU_HASH section at 0x78: it goes past the end of the file332 333## Case B: the 'nbuckets' field is set so that the GNU hash table goes past the end of the file.334# RUN: yaml2obj --docnum=6 -D NBUCKETS=0x80000000 %s -o %t8335# RUN: llvm-readelf --elf-hash-histogram %t8 2>&1 | \336# RUN: FileCheck %s -DFILE=%t8 --check-prefix=ERR5 --implicit-check-not="Histogram"337 338--- !ELF339FileHeader:340 Class: ELFCLASS64341 Data: ELFDATA2LSB342 Type: ET_DYN343Sections:344 - Name: .gnu.hash345 Type: SHT_GNU_HASH346 Flags: [ SHF_ALLOC ]347 Header:348 SymNdx: 0x0349 Shift2: 0x0350## The number of words in the Bloom filter. The value of 1 is no-op.351 MaskWords: [[MASKWORDS=1]]352## The number of hash buckets. The value of 1 is no-op.353 NBuckets: [[NBUCKETS=1]]354 BloomFilter: [ 0x0 ]355 HashBuckets: [ 0x0 ]356 HashValues: [ 0x0 ]357 - Name: .dynamic358 Type: SHT_DYNAMIC359 Flags: [ SHF_ALLOC ]360 Link: .dynstr361 Entries:362 - Tag: DT_GNU_HASH363 Value: 0x0364 - Tag: DT_NULL365 Value: 0x0366DynamicSymbols: []367ProgramHeaders:368 - Type: PT_LOAD369 FirstSec: .gnu.hash370 LastSec: .dynamic371 372## Linkers might produce an empty no-op SHT_GNU_HASH section when373## there are no dynamic symbols or when all dynamic symbols are undefined.374## Such sections normally have a single zero entry in the bloom375## filter, a single zero entry in the hash bucket and no values.376##377## The index of the first symbol in the dynamic symbol table378## included in the hash table can be set to the number of dynamic symbols,379## which is one larger than the index of the last dynamic symbol.380## For empty tables however, this value is unimportant and can be ignored.381 382## Check the case when a 'symndx' index of the first symbol in the dynamic symbol383## table is larger than the number of dynamic symbols.384 385## Case A: when the buckets array is not empty and has a non-zero value we report a warning.386# RUN: yaml2obj --docnum=7 -DVAL=0x1 %s -o %t9387# RUN: llvm-readelf --elf-hash-histogram %t9 2>&1 | \388# RUN: FileCheck %s -DFILE=%t9 --check-prefix=ERR6389 390# ERR6: warning: '[[FILE]]': unable to print the GNU hash table histogram: the first hashed symbol index (16) is greater than or equal to the number of dynamic symbols (1)391 392## Case B: we do not report a warning when the buckets array contains only zero values.393# RUN: yaml2obj --docnum=7 -DVAL=0x0 %s -o %t10394# RUN: llvm-readelf --elf-hash-histogram %t10 2>&1 | \395# RUN: FileCheck %s --allow-empty --implicit-check-not="Histogram"396 397## Case C: we do not report a warning when the buckets array is empty.398# RUN: yaml2obj --docnum=7 -DVAL="" %s -o %t11399# RUN: llvm-readelf --elf-hash-histogram %t11 2>&1 | \400# RUN: FileCheck %s --allow-empty --implicit-check-not="Histogram"401 402--- !ELF403FileHeader:404 Class: ELFCLASS64405 Data: ELFDATA2LSB406 Type: ET_DYN407Sections:408 - Name: .gnu.hash409 Type: SHT_GNU_HASH410 Flags: [ SHF_ALLOC ]411 Header:412 SymNdx: 0x10413 Shift2: 0x0414 BloomFilter: [ 0x0 ]415 HashBuckets: [ [[VAL]] ]416 HashValues: [ 0x0 ]417 - Name: .dynamic418 Type: SHT_DYNAMIC419 Flags: [ SHF_ALLOC ]420 Link: .dynstr421 Entries:422 - Tag: DT_GNU_HASH423 Value: 0x0424 - Tag: DT_NULL425 Value: 0x0426DynamicSymbols: []427ProgramHeaders:428 - Type: PT_LOAD429 FirstSec: .gnu.hash430 LastSec: .dynamic431 432## Check we report warnings when the dynamic symbol table is absent or empty.433 434## The code locates the dynamic symbol table by the section type. Use SHT_PROGBITS to hide it.435# RUN: yaml2obj --docnum=8 -DTYPE=SHT_PROGBITS %s -o %t12436# RUN: llvm-readelf --elf-hash-histogram %t12 2>&1 | \437# RUN: FileCheck %s -DFILE=%t12 --check-prefix=ERR7438 439# ERR7: warning: '[[FILE]]': unable to print the GNU hash table histogram: no dynamic symbol table found440 441# RUN: yaml2obj --docnum=8 -DTYPE=SHT_DYNSYM %s -o %t13442# RUN: llvm-readelf --elf-hash-histogram %t13 2>&1 | \443# RUN: FileCheck %s -DFILE=%t13 --check-prefix=ERR8444 445# ERR8: warning: '[[FILE]]': unable to print the GNU hash table histogram: the dynamic symbol table is empty446 447--- !ELF448FileHeader:449 Class: ELFCLASS64450 Data: ELFDATA2LSB451 Type: ET_DYN452Sections:453 - Name: .gnu.hash454 Type: SHT_GNU_HASH455 Flags: [ SHF_ALLOC ]456 Header:457 SymNdx: 0x0458 Shift2: 0x0459 BloomFilter: [ 0x0 ]460 HashBuckets: [ 0x0 ]461 HashValues: [ 0x0 ]462 - Name: .dynamic463 Type: SHT_DYNAMIC464 Flags: [ SHF_ALLOC ]465 Entries:466 - Tag: DT_GNU_HASH467 Value: 0x0468 - Tag: DT_NULL469 Value: 0x0470 - Name: .dynsym471 Type: [[TYPE]]472 Size: 0473ProgramHeaders:474 - Type: PT_LOAD475 FirstSec: .gnu.hash476 LastSec: .gnu.hash477