Index: test/tools/llvm-readobj/elf-hash-symbols.test =================================================================== --- test/tools/llvm-readobj/elf-hash-symbols.test +++ test/tools/llvm-readobj/elf-hash-symbols.test @@ -361,3 +361,42 @@ PAddr: 0x1000 Sections: - Section: .dynamic + +## Show that we report a warning when .hash section contains a chain with a cycle. + +# RUN: yaml2obj --docnum=6 %s -o %t6.so +# RUN: llvm-readelf --hash-symbols %t6.so 2>&1 | FileCheck %s -DFILE=%t6.so --check-prefix=BROKEN + +# BROKEN: Symbol table of .hash for image: +# BROKEN-NEXT: Num Buc: Value Size Type Bind Vis Ndx Name +# BROKEN-NEXT: 1 0: 00000000 0 NOTYPE LOCAL DEFAULT UND aaa +# BROKEN: warning: '[[FILE]]': .hash section is invalid + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: + - Name: .hash + Type: SHT_HASH + Link: .dynsym + Bucket: [ 1 ] + Chain: [ 1, 1 ] + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: +## PT_LOAD's p_vaddr is 0x0. PT_LOAD's p_offset = 0x1bc. DT_HASH value is 0x0. +## llvm-readelf will read .hash content from p_offset + (p_vaddr - DT_HASH value) = 0x1bc. +## This matches the file offset of the .hash section. + - Tag: DT_HASH + Value: 0x0 +DynamicSymbols: + - Name: aaa + - Name: bbb +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .hash + - Section: .dynamic Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -3437,10 +3437,18 @@ for (uint32_t Buc = 0; Buc < SysVHash->nbucket; Buc++) { if (Buckets[Buc] == ELF::STN_UNDEF) continue; + std::vector Visited(SysVHash->nchain); for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash->nchain; Ch = Chains[Ch]) { if (Ch == ELF::STN_UNDEF) break; + + if (Visited[Ch]) { + reportWarning(createError(".hash section is invalid"), FileName); + break; + } + printHashedSymbol(Obj, &DynSyms[0], Ch, StringTable, Buc); + Visited[Ch] = true; } } }