diff --git a/llvm/test/tools/llvm-readobj/ELF/verdef-invalid.test b/llvm/test/tools/llvm-readobj/ELF/verdef-invalid.test --- a/llvm/test/tools/llvm-readobj/ELF/verdef-invalid.test +++ b/llvm/test/tools/llvm-readobj/ELF/verdef-invalid.test @@ -34,11 +34,11 @@ ## Check that we report a warning when we can't read the content of the SHT_GNU_verdef section. -# RUN: yaml2obj %s --docnum=2 -o %t3 +# RUN: yaml2obj %s --docnum=2 -DSHOFFSET=0xFFFFFFFF -o %t3 # RUN: llvm-readobj -V %t3 2>&1 | FileCheck %s --check-prefix=INVALID-DATA -DFILE=%t3 # RUN: llvm-readelf -V %t3 2>&1 | FileCheck %s --check-prefix=INVALID-DATA -DFILE=%t3 -# INVALID-DATA: warning: '[[FILE]]': cannot read content of SHT_GNU_verdef section with index 1: section [index 1] has a sh_offset (0xffffffff) + sh_size (0x0) that is greater than the file size (0x228) +# INVALID-DATA: warning: '[[FILE]]': cannot read content of SHT_GNU_verdef section with index 1: section [index 1] has a sh_offset (0xffffffff) + sh_size (0x0) that is greater than the file size (0x230) --- !ELF FileHeader: @@ -51,10 +51,42 @@ Link: .dynstr Info: 0x0 Entries: [] - ShOffset: 0xFFFFFFFF + ShOffset: [[SHOFFSET=]] + ShName: [[SHNAME=]] + - Name: .dynstr + Type: SHT_STRTAB + ShName: [[DYNSTRNAME=]] DynamicSymbols: - Name: foo +## Check that llvm-readelf reports a warning when the name of the SHT_GNU_verdef section can't be read. + +# RUN: yaml2obj %s --docnum=2 -DSHNAME=0xFF -o %t.invalid.name +# RUN: llvm-readobj -V %t.invalid.name 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-NAME-LLVM -DFILE=%t.invalid.name --implicit-check-not=warning: +# RUN: llvm-readelf -V %t.invalid.name 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-NAME-GNU -DFILE=%t.invalid.name --implicit-check-not=warning: + +# INVALID-NAME-LLVM: VersionDefinitions [ +# INVALID-NAME-LLVM-NEXT: ] + +# INVALID-NAME-GNU: warning: '[[FILE]]': unable to get the name of SHT_GNU_verdef section with index 1: a section [index 1] has an invalid sh_name (0xff) offset which goes past the end of the section name string table +# INVALID-NAME-GNU-NEXT: Version definition section '' contains 0 entries: +# INVALID-NAME-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 2 (.dynstr) + +## Check that llvm-readelf reports a warning when we are unable to read the name of +## the section linked with the SHT_GNU_verdef section (usually ".dynstr"). + +# RUN: yaml2obj %s --docnum=2 -DDYNSTRNAME=0xFF -o %t.invalid.name2 +# RUN: llvm-readobj -V %t.invalid.name2 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-NAME-LLVM -DFILE=%t.invalid.name2 --implicit-check-not=warning: +# RUN: llvm-readelf -V %t.invalid.name2 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-NAME2-GNU -DFILE=%t.invalid.name2 --implicit-check-not=warning: + +# INVALID-NAME2-GNU: Version definition section '.gnu.version_d' contains 0 entries: +# INVALID-NAME2-GNU-NEXT: warning: '[[FILE]]': unable to get the name of SHT_STRTAB section with index 2: a section [index 2] has an invalid sh_name (0xff) offset which goes past the end of the section name string table +# INVALID-NAME2-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 2 () + ## Check that we report a warning when a SHT_GNU_verdef section contains a version definition ## that goes past the end of the section. diff --git a/llvm/test/tools/llvm-readobj/ELF/verneed-invalid.test b/llvm/test/tools/llvm-readobj/ELF/verneed-invalid.test --- a/llvm/test/tools/llvm-readobj/ELF/verneed-invalid.test +++ b/llvm/test/tools/llvm-readobj/ELF/verneed-invalid.test @@ -315,7 +315,7 @@ ## Check that we report a warning when sh_link references a non-existent section. -# RUN: yaml2obj --docnum=6 %s -o %t6 +# RUN: yaml2obj --docnum=6 %s -DLINK=0xFF -o %t6 # RUN: llvm-readobj --sections -V %t6 2>&1 | FileCheck %s -DFILE=%t6 --implicit-check-not="warning:" --check-prefix=INVALID-LINK-LLVM # RUN: llvm-readelf --sections -V %t6 2>&1 | FileCheck %s -DFILE=%t6 --implicit-check-not="warning:" --check-prefix=INVALID-LINK-GNU @@ -349,11 +349,12 @@ Data: ELFDATA2LSB Type: ET_EXEC Sections: - - Name: .gnu.version_r - Type: SHT_GNU_verneed - Flags: [ SHF_ALLOC ] - Info: 1 - Link: 0xFF + - Name: .gnu.version_r + Type: SHT_GNU_verneed + Flags: [ SHF_ALLOC ] + Info: 1 + Link: [[LINK=.dynstr]] + ShName: [[SHNAME=]] Dependencies: - Version: 1 File: foo @@ -362,9 +363,58 @@ Hash: 0 Flags: 0 Other: 0 + - Name: .dynstr + Type: SHT_STRTAB + ShName: [[DYNSTRNAME=]] DynamicSymbols: - Name: foo +## Check that llvm-readelf reports a warning when the name of the SHT_GNU_verneed section can't be read. + +# RUN: yaml2obj --docnum=6 %s -DSHNAME=0xFFFFFFFF -o %t.invalid.name +# RUN: llvm-readobj -V %t.invalid.name 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.invalid.name --check-prefix=INVALID-NAME-LLVM --implicit-check-not=warning: +# RUN: llvm-readelf -V %t.invalid.name 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.invalid.name --check-prefix=INVALID-NAME-GNU --implicit-check-not=warning: + +# INVALID-NAME-LLVM: VersionRequirements [ +# INVALID-NAME-LLVM-NEXT: Dependency { +# INVALID-NAME-LLVM-NEXT: Version: 1 +# INVALID-NAME-LLVM-NEXT: Count: 1 +# INVALID-NAME-LLVM-NEXT: FileName: foo +# INVALID-NAME-LLVM-NEXT: Entries [ +# INVALID-NAME-LLVM-NEXT: Entry { +# INVALID-NAME-LLVM-NEXT: Hash: 0 +# INVALID-NAME-LLVM-NEXT: Flags [ (0x0) +# INVALID-NAME-LLVM-NEXT: ] +# INVALID-NAME-LLVM-NEXT: Index: 0 +# INVALID-NAME-LLVM-NEXT: Name: foo +# INVALID-NAME-LLVM-NEXT: } +# INVALID-NAME-LLVM-NEXT: ] +# INVALID-NAME-LLVM-NEXT: } +# INVALID-NAME-LLVM-NEXT: ] + +# INVALID-NAME-GNU: warning: '[[FILE]]': unable to get the name of SHT_GNU_verneed section with index 1: a section [index 1] has an invalid sh_name (0xffffffff) offset which goes past the end of the section name string table +# INVALID-NAME-GNU-NEXT: Version needs section '' contains 1 entries: +# INVALID-NAME-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 2 (.dynstr) +# INVALID-NAME-GNU-NEXT: 0x0000: Version: 1 File: foo Cnt: 1 +# INVALID-NAME-GNU-NEXT: 0x0010: Name: foo Flags: none Version: 0 + +## Check that llvm-readelf reports a warning when we are unable to read the name of +## the section linked with the SHT_GNU_verneed section (usually ".dynstr"). + +# RUN: yaml2obj --docnum=6 %s -DDYNSTRNAME=0xFFFFFFFF -o %t.invalid.name2 +# RUN: llvm-readobj -V %t.invalid.name2 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.invalid.name2 --check-prefix=INVALID-NAME-LLVM --implicit-check-not=warning: +# RUN: llvm-readelf -V %t.invalid.name2 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.invalid.name2 --check-prefix=INVALID-NAME2-GNU --implicit-check-not=warning: + +# INVALID-NAME2-GNU: Version needs section '.gnu.version_r' contains 1 entries: +# INVALID-NAME2-GNU-NEXT: warning: '[[FILE]]': unable to get the name of SHT_STRTAB section with index 2: a section [index 2] has an invalid sh_name (0xffffffff) offset which goes past the end of the section name string table +# INVALID-NAME2-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 2 () +# INVALID-NAME2-GNU-NEXT: 0x0000: Version: 1 File: foo Cnt: 1 +# INVALID-NAME2-GNU-NEXT: 0x0010: Name: foo Flags: none Version: 0 + ## Check that we report a warning when we can't read the content of the SHT_GNU_verneed section. # RUN: yaml2obj --docnum=7 %s -o %t7 diff --git a/llvm/test/tools/llvm-readobj/ELF/versym-invalid.test b/llvm/test/tools/llvm-readobj/ELF/versym-invalid.test --- a/llvm/test/tools/llvm-readobj/ELF/versym-invalid.test +++ b/llvm/test/tools/llvm-readobj/ELF/versym-invalid.test @@ -74,12 +74,12 @@ ## Check we report a warning when a SHT_GNU_versym section is not correctly aligned in memory. -# RUN: yaml2obj --docnum=3 %s -o %t4 +# RUN: yaml2obj --docnum=3 %s -DSHOFFSET=0xffff -o %t4 # RUN: llvm-readelf -V %t4 2>&1 | FileCheck -DFILE=%t4 %s --check-prefix=MISALIGNED-GNU # RUN: llvm-readobj -V %t4 2>&1 | FileCheck -DFILE=%t4 %s --check-prefix=MISALIGNED-LLVM -# MISALIGNED-GNU: Version symbols section '.gnu.version' contains 0 entries: -# MISALIGNED-GNU-NEXT: Addr: 0000000000000000 Offset: 0x00ffff Link: 0 () +# MISALIGNED-GNU: Version symbols section '.gnu.version' contains 1 entries: +# MISALIGNED-GNU-NEXT: Addr: 0000000000000000 Offset: 0x00ffff Link: 2 (.dynsym) # MISALIGNED-GNU-NEXT: warning: '[[FILE]]': the SHT_GNU_versym section with index 1 is misaligned # MISALIGNED-LLVM: VersionSymbols [ @@ -92,10 +92,50 @@ Data: ELFDATA2LSB Type: ET_EXEC Sections: - - Name: .gnu.version - Type: SHT_GNU_versym - Entries: [ ] - ShOffset: 0xffff + - Name: .gnu.version + Type: SHT_GNU_versym + Entries: [ 0 ] + Link: .dynsym + ShOffset: [[SHOFFSET=]] + ShName: [[SHNAME=]] + - Name: .dynsym + Type: SHT_DYNSYM + ShName: [[DYNSYMNAME=]] +DynamicSymbols: [] + +## Check that llvm-readelf reports a warning when the name of the SHT_GNU_versym section can't be read. + +# RUN: yaml2obj %s --docnum=3 -DSHNAME=0xFF -o %t.invalid.name +# RUN: llvm-readobj -V %t.invalid.name 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-NAME-LLVM -DFILE=%t.invalid.name --implicit-check-not=warning: +# RUN: llvm-readelf -V %t.invalid.name 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-NAME-GNU -DFILE=%t.invalid.name --implicit-check-not=warning: + +# INVALID-NAME-LLVM: VersionSymbols [ +# INVALID-NAME-LLVM-NEXT: Symbol { +# INVALID-NAME-LLVM-NEXT: Version: 0 +# INVALID-NAME-LLVM-NEXT: Name: +# INVALID-NAME-LLVM-NEXT: } +# INVALID-NAME-LLVM-NEXT: ] + +# INVALID-NAME-GNU: warning: '[[FILE]]': unable to get the name of SHT_GNU_versym section with index 1: a section [index 1] has an invalid sh_name (0xff) offset which goes past the end of the section name string table +# INVALID-NAME-GNU-NEXT: Version symbols section '' contains 1 entries: +# INVALID-NAME-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 2 (.dynsym) +# INVALID-NAME-GNU-NEXT: 000: 0 (*local*) + +## Check that llvm-readelf reports a warning when we are unable to read the name of +## the section linked with the SHT_GNU_verneed section (usually ".dynsym"). + +# RUN: yaml2obj %s --docnum=3 -DDYNSYMNAME=0xFF -o %t.invalid.name2 +# RUN: llvm-readobj -V %t.invalid.name2 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-NAME-LLVM -DFILE=%t.invalid.name2 --implicit-check-not=warning: +# RUN: llvm-readelf -V %t.invalid.name2 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-NAME2-GNU -DFILE=%t.invalid.name2 --implicit-check-not=warning: + +# INVALID-NAME2-GNU: Version symbols section '.gnu.version' contains 1 entries: +# INVALID-NAME2-GNU-NEXT: warning: '[[FILE]]': unable to get the name of SHT_DYNSYM section with index 2: a section [index 2] has an invalid sh_name (0xff) offset which goes past the end of the section name string table +# INVALID-NAME2-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 2 () +# INVALID-NAME2-GNU-NEXT: 000: 0 (*local*) ## Check we report a warning when a SHT_GNU_versym section has an invalid entry size. diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -952,7 +952,7 @@ std::string getSymbolSectionNdx(const Elf_Sym &Symbol, unsigned SymIndex); void printProgramHeaders(); void printSectionMapping(); - void printGNUVersionSectionProlog(const typename ELFT::Shdr *Sec, + void printGNUVersionSectionProlog(const typename ELFT::Shdr &Sec, const Twine &Label, unsigned EntriesNum); }; @@ -4718,26 +4718,25 @@ template void GNUStyle::printGNUVersionSectionProlog( - const typename ELFT::Shdr *Sec, const Twine &Label, unsigned EntriesNum) { - StringRef SecName = - unwrapOrError(this->FileName, this->Obj.getSectionName(*Sec)); + const typename ELFT::Shdr &Sec, const Twine &Label, unsigned EntriesNum) { + // Don't inline the SecName, because it might report a warning to stderr and + // corrupt the output. + StringRef SecName = this->getPrintableSectionName(Sec); OS << Label << " section '" << SecName << "' " << "contains " << EntriesNum << " entries:\n"; - StringRef SymTabName = ""; - Expected SymTabOrErr = - this->Obj.getSection(Sec->sh_link); - if (SymTabOrErr) - SymTabName = - unwrapOrError(this->FileName, this->Obj.getSectionName(**SymTabOrErr)); + StringRef LinkedSecName = ""; + if (Expected LinkedSecOrErr = + this->Obj.getSection(Sec.sh_link)) + LinkedSecName = this->getPrintableSectionName(**LinkedSecOrErr); else - this->reportUniqueWarning(createError("invalid section linked to " + - describe(this->Obj, *Sec) + ": " + - toString(SymTabOrErr.takeError()))); + this->reportUniqueWarning( + createError("invalid section linked to " + describe(this->Obj, Sec) + + ": " + toString(LinkedSecOrErr.takeError()))); - OS << " Addr: " << format_hex_no_prefix(Sec->sh_addr, 16) - << " Offset: " << format_hex(Sec->sh_offset, 8) - << " Link: " << Sec->sh_link << " (" << SymTabName << ")\n"; + OS << " Addr: " << format_hex_no_prefix(Sec.sh_addr, 16) + << " Offset: " << format_hex(Sec.sh_offset, 8) + << " Link: " << Sec.sh_link << " (" << LinkedSecName << ")\n"; } template @@ -4745,7 +4744,7 @@ if (!Sec) return; - printGNUVersionSectionProlog(Sec, "Version symbols", + printGNUVersionSectionProlog(*Sec, "Version symbols", Sec->sh_size / sizeof(Elf_Versym)); Expected> VerTableOrErr = this->dumper().getVersionTable(*Sec, /*SymTab=*/nullptr, @@ -4818,7 +4817,7 @@ if (!Sec) return; - printGNUVersionSectionProlog(Sec, "Version definition", Sec->sh_info); + printGNUVersionSectionProlog(*Sec, "Version definition", Sec->sh_info); Expected> V = this->dumper().getVersionDefinitions(*Sec); if (!V) { @@ -4846,7 +4845,7 @@ return; unsigned VerneedNum = Sec->sh_info; - printGNUVersionSectionProlog(Sec, "Version needs", VerneedNum); + printGNUVersionSectionProlog(*Sec, "Version needs", VerneedNum); Expected> V = this->dumper().getVersionDependencies(*Sec);