From 2930dab31533feb3f4a4e14f8bcd9457a2388338 Mon Sep 17 00:00:00 2001 From: Georgii Rymar Date: Thu, 23 Jan 2020 18:56:24 +0300 Subject: [PATCH] [llvm-readobj] - Improve error message reported by DynRegionInfo. DynRegionInfo is a helper class used to create memory ranges. It is used for many things and can report errors. Errors reported currently do not provide a good diagnostic. This patch fixes it and adds a test for each possible case. Differential revision: https://reviews.llvm.org/D73484 --- llvm/test/Object/invalid.test | 6 +- .../ELF/broken-dynamic-reloc-name.test | 49 --- .../llvm-readobj/ELF/broken-dynamic-reloc.test | 375 +++++++++++++++++++++ llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test | 52 +++ .../tools/llvm-readobj/ELF/dynamic-malformed.test | 8 +- .../ELF/dynamic-not-in-pt-dynamic.test | 4 +- .../ELF/non-dynamic-in-pt-dynamic.test | 4 +- llvm/tools/llvm-readobj/ELFDumper.cpp | 59 +++- 8 files changed, 487 insertions(+), 70 deletions(-) delete mode 100644 llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc-name.test create mode 100644 llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test diff --git a/llvm/test/Object/invalid.test b/llvm/test/Object/invalid.test index b47ba6f..c923937 100644 --- a/llvm/test/Object/invalid.test +++ b/llvm/test/Object/invalid.test @@ -137,7 +137,7 @@ Symbols: # RUN: yaml2obj %s --docnum=7 -o %t7 # RUN: llvm-readobj --dyn-symbols %t7 2>&1 | FileCheck -DFILE=%t7 --check-prefix=INVALID-DYNSYM-SIZE %s -# INVALID-DYNSYM-SIZE: warning: '[[FILE]]': invalid section size (48) or entity size (32) +# INVALID-DYNSYM-SIZE: warning: '[[FILE]]': section with index 1 has invalid size (0x30) or entry size (0x20) --- !ELF FileHeader: @@ -474,7 +474,7 @@ ProgramHeaders: # RUN: %p/Inputs/corrupt-invalid-relocation-size.elf.x86-64 2>&1 \ # RUN: | FileCheck -DFILE=%p/Inputs/corrupt-invalid-relocation-size.elf.x86-64 --check-prefix=RELOC-BROKEN-ENTSIZE %s -# RELOC-BROKEN-ENTSIZE: warning: '[[FILE]]': invalid section size (24) or entity size (25) +# RELOC-BROKEN-ENTSIZE: warning: '[[FILE]]': invalid DT_RELASZ value (0x18) or DT_RELAENT value (0x19) ## Check that llvm-readobj reports a warning when .dynamic section has an invalid ## size, which isn't a multiple of the dynamic entry size. @@ -482,7 +482,7 @@ ProgramHeaders: # RUN: yaml2obj %s --docnum=22 -o %t22 # RUN: llvm-readobj --dyn-relocations %t22 2>&1 | FileCheck -DFILE=%t22 --check-prefix=DYN-TABLE-SIZE %s -# DYN-TABLE-SIZE: warning: '[[FILE]]': invalid section size (1) or entity size (16) +# DYN-TABLE-SIZE: warning: '[[FILE]]': section with index 1 has invalid size (0x1){{$}} --- !ELF FileHeader: diff --git a/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc-name.test b/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc-name.test deleted file mode 100644 index cdbafd7..0000000 --- a/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc-name.test +++ /dev/null @@ -1,49 +0,0 @@ -## Check that llvm-readobj/llvm-readelf reports an error when dumping relocations if a dynamic -## symbol name offset is broken (goes past the end of the dynamic symbol string table). - -# RUN: yaml2obj %s -o %t -# RUN: llvm-readobj --dyn-relocations %t 2>&1 | FileCheck %s -DFILE=%t --check-prefix=LLVM -# RUN: llvm-readelf --dyn-relocations %t 2>&1 | FileCheck %s -DFILE=%t --check-prefix=GNU - -# LLVM: Dynamic Relocations { -# LLVM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 1: st_name (0x1234) is past the end of the string table of size 0x1 -# LLVM-NEXT: 0x0 R_X86_64_NONE 0x0 -# LLVM-NEXT: } - -# GNU: 'RELA' relocation section at offset {{.+}} contains 24 bytes: -# GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend -# GNU-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 1: st_name (0x1234) is past the end of the string table of size 0x1 -# GNU-NEXT: 0000000000000000 0000000100000000 R_X86_64_NONE 0000000000000000 + 0 - ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_DYN - Machine: EM_X86_64 -Sections: - - Name: .rela.dyn - Type: SHT_RELA - Link: .dynsym - Relocations: - - Offset: 0x0 - Symbol: 1 ## Index of a dynamic symbol with a broken st_name. - Type: R_X86_64_NONE - - Name: .dynamic - Type: SHT_DYNAMIC - Entries: - - Tag: DT_RELA - Value: 0x0000000000000000 - - Tag: DT_RELASZ - Value: 0x0000000000000018 - - Tag: DT_RELAENT - Value: 0x0000000000000018 - - Tag: DT_NULL - Value: 0x0000000000000000 -DynamicSymbols: - - NameIndex: 0x1234 -ProgramHeaders: - - Type: PT_LOAD - Sections: - - Section: .rela.dyn - - Section: .dynamic diff --git a/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test b/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test new file mode 100644 index 0000000..5f3e4d4 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test @@ -0,0 +1,375 @@ +## Test how we handle cases when dynamic relocations or corresponding dynamic tags are broken. + +## Check that llvm-readobj/llvm-readelf reports an error when dumping relocations if a dynamic +## symbol name offset is broken (goes past the end of the dynamic symbol string table). + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: llvm-readobj --dyn-relocations %t1 2>&1 | FileCheck %s -DFILE=%t1 --check-prefix=LLVM +# RUN: llvm-readelf --dyn-relocations %t1 2>&1 | FileCheck %s -DFILE=%t1 --check-prefix=GNU + +# LLVM: Dynamic Relocations { +# LLVM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 1: st_name (0x1234) is past the end of the string table of size 0x1 +# LLVM-NEXT: 0x0 R_X86_64_NONE 0x0 +# LLVM-NEXT: } + +# GNU: 'RELA' relocation section at offset {{.+}} contains 24 bytes: +# GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +# GNU-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 1: st_name (0x1234) is past the end of the string table of size 0x1 +# GNU-NEXT: 0000000000000000 0000000100000000 R_X86_64_NONE 0000000000000000 + 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .rela.dyn + Type: SHT_RELA + Link: .dynsym + Relocations: + - Offset: 0x0 + Symbol: 1 ## Index of a dynamic symbol with a broken st_name. + Type: R_X86_64_NONE + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_RELA + Value: 0x0000000000000000 + - Tag: DT_RELASZ + Value: 0x0000000000000018 + - Tag: DT_RELAENT + Value: 0x0000000000000018 + - Tag: DT_NULL + Value: 0x0000000000000000 +DynamicSymbols: + - NameIndex: 0x1234 +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .rela.dyn + - Section: .dynamic + +## Show we print a warning for an invalid relocation table size stored in a DT_RELASZ entry. +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: llvm-readobj --dyn-relocations %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=INVALID-DT-RELASZ +# RUN: llvm-readelf --dyn-relocations %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=INVALID-DT-RELASZ + +# INVALID-DT-RELASZ: warning: '[[FILE]]': invalid DT_RELASZ value (0xff) or DT_RELAENT value (0x18) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .rela.dyn + Type: SHT_RELA + Relocations: + - Offset: 0x0 + Type: R_X86_64_NONE + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_RELA + Value: 0x0 + - Tag: DT_RELASZ + Value: 0xFF + - Tag: DT_RELAENT + Value: 0x18 + - Tag: DT_NULL + Value: 0x0 +DynamicSymbols: [] +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .rela.dyn + - Section: .dynamic + +## Show we print a warning for an invalid relocation table entry size stored in a DT_RELAENT entry. +# RUN: yaml2obj --docnum=3 %s -o %t3 +# RUN: llvm-readobj --dyn-relocations %t3 2>&1 | FileCheck %s -DFILE=%t3 --check-prefix=INVALID-DT-RELAENT +# RUN: llvm-readelf --dyn-relocations %t3 2>&1 | FileCheck %s -DFILE=%t3 --check-prefix=INVALID-DT-RELAENT + +## INVALID-DT-RELAENT: warning: '[[FILE]]': invalid DT_RELASZ value (0x18) or DT_RELAENT value (0xff) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .rela.dyn + Type: SHT_RELA + Relocations: + - Offset: 0x0 + Type: R_X86_64_NONE + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_RELA + Value: 0x0 + - Tag: DT_RELASZ + Value: 0x18 + - Tag: DT_RELAENT + Value: 0xFF + - Tag: DT_NULL + Value: 0x0 +DynamicSymbols: [] +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .rela.dyn + - Section: .dynamic + +## Show we print a warning for an invalid relocation table size stored in a DT_RELSZ entry. +# RUN: yaml2obj --docnum=4 %s -o %t4 +# RUN: llvm-readobj --dyn-relocations %t4 2>&1 | FileCheck %s -DFILE=%t4 --check-prefix=INVALID-DT-RELSZ +# RUN: llvm-readelf --dyn-relocations %t4 2>&1 | FileCheck %s -DFILE=%t4 --check-prefix=INVALID-DT-RELSZ + +## INVALID-DT-RELSZ: warning: '[[FILE]]': invalid DT_RELSZ value (0xff) or DT_RELENT value (0x18) + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: + - Name: .rela.dyn + Type: SHT_REL + Relocations: + - Offset: 0x0 + Type: R_386_NONE + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_REL + Value: 0x0 + - Tag: DT_RELSZ + Value: 0xFF + - Tag: DT_RELENT + Value: 0x18 + - Tag: DT_NULL + Value: 0x0 +DynamicSymbols: [] +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .rela.dyn + - Section: .dynamic + +## Show we print a warning for an invalid relocation table entry size stored in a DT_RELENT entry. +# RUN: yaml2obj --docnum=5 %s -o %t5 +# RUN: llvm-readobj --dyn-relocations %t5 2>&1 | FileCheck %s -DFILE=%t5 --check-prefix=INVALID-DT-RELENT +# RUN: llvm-readelf --dyn-relocations %t5 2>&1 | FileCheck %s -DFILE=%t5 --check-prefix=INVALID-DT-RELENT + +## INVALID-DT-RELENT: warning: '[[FILE]]': invalid DT_RELSZ value (0x18) or DT_RELENT value (0xff) + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: + - Name: .rela.dyn + Type: SHT_REL + Relocations: + - Offset: 0x0 + Type: R_386_NONE + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_REL + Value: 0x0 + - Tag: DT_RELSZ + Value: 0x18 + - Tag: DT_RELENT + Value: 0xFF + - Tag: DT_NULL + Value: 0x0 +DynamicSymbols: [] +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .rela.dyn + - Section: .dynamic + +## Show we print a warning for an invalid relocation table size stored in a DT_RELRSZ/DT_ANDROID_RELRSZ entry. +# RUN: yaml2obj --docnum=6 %s -o %t6 +# RUN: llvm-readobj --dyn-relocations %t6 2>&1 | FileCheck %s -DFILE=%t6 --check-prefix=INVALID-DT-RELRSZ +# RUN: llvm-readelf --dyn-relocations %t6 2>&1 | FileCheck %s -DFILE=%t6 --check-prefix=INVALID-DT-RELRSZ +# RUN: yaml2obj --docnum=7 %s -o %t7 +# RUN: llvm-readobj --dyn-relocations %t7 2>&1 | FileCheck %s -DFILE=%t7 --check-prefix=INVALID-DT-ANDROID-RELRSZ +# RUN: llvm-readelf --dyn-relocations %t7 2>&1 | FileCheck %s -DFILE=%t7 --check-prefix=INVALID-DT-ANDROID-RELRSZ + +## INVALID-DT-RELRSZ: warning: '[[FILE]]': invalid DT_RELRSZ value (0xff) or DT_RELRENT value (0x18) +## INVALID-DT-ANDROID-RELRSZ: warning: '[[FILE]]': invalid DT_ANDROID_RELRSZ value (0xff) or DT_ANDROID_RELRENT value (0x18) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .relr.dyn + Type: SHT_RELR + Flags: [ SHF_ALLOC ] + Content: "" + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_RELR + Value: 0x0 + - Tag: DT_RELRSZ + Value: 0xFF + - Tag: DT_RELRENT + Value: 0x18 + - Tag: DT_NULL + Value: 0x0 +DynamicSymbols: [] +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .relr.dyn + - Section: .dynamic + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .relr.dyn + Type: SHT_RELR + Flags: [ SHF_ALLOC ] + Content: "" + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_RELR + Value: 0x0 + - Tag: DT_ANDROID_RELRSZ + Value: 0xFF + - Tag: DT_ANDROID_RELRENT + Value: 0x18 + - Tag: DT_NULL + Value: 0x0 +DynamicSymbols: [] +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .relr.dyn + - Section: .dynamic + +## Show we print a warning for an invalid relocation table entry size stored in a DT_RELRENT/DT_ANDROID_RELRENT entry. +# RUN: yaml2obj --docnum=8 %s -o %t8 +# RUN: llvm-readobj --dyn-relocations %t8 2>&1 | FileCheck %s -DFILE=%t8 --check-prefix=INVALID-DT-RELRENT +# RUN: llvm-readelf --dyn-relocations %t8 2>&1 | FileCheck %s -DFILE=%t8 --check-prefix=INVALID-DT-RELRENT +# RUN: yaml2obj --docnum=9 %s -o %t9 +# RUN: llvm-readobj --dyn-relocations %t9 2>&1 | FileCheck %s -DFILE=%t9 --check-prefix=INVALID-DT-ANDROID-RELRENT +# RUN: llvm-readelf --dyn-relocations %t9 2>&1 | FileCheck %s -DFILE=%t9 --check-prefix=INVALID-DT-ANDROID-RELRENT + +## INVALID-DT-RELRENT: invalid DT_RELRSZ value (0x18) or DT_RELRENT value (0xff) +## INVALID-DT-ANDROID-RELRENT: invalid DT_ANDROID_RELRSZ value (0x18) or DT_ANDROID_RELRENT value (0xff) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .relr.dyn + Type: SHT_RELR + Flags: [ SHF_ALLOC ] + Content: "" + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_RELR + Value: 0x0 + - Tag: DT_RELRSZ + Value: 0x18 + - Tag: DT_RELRENT + Value: 0xFF + - Tag: DT_NULL + Value: 0x0 +DynamicSymbols: [] +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .relr.dyn + - Section: .dynamic + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .relr.dyn + Type: SHT_RELR + Flags: [ SHF_ALLOC ] + Content: "" + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_RELR + Value: 0x0 + - Tag: DT_ANDROID_RELRSZ + Value: 0x18 + - Tag: DT_ANDROID_RELRENT + Value: 0xFF + - Tag: DT_NULL + Value: 0x0 +DynamicSymbols: [] +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .relr.dyn + - Section: .dynamic + +## Show we print a warning for an invalid value of DT_PLTRELSZ, which describes the total size +## of the relocation entries associated with the procedure linkage table. +# RUN: yaml2obj --docnum=10 %s -o %t10 +# RUN: llvm-readobj --dyn-relocations %t10 2>&1 | FileCheck %s -DFILE=%t10 --check-prefix=INVALID-DT-PLTRELSZ +# RUN: llvm-readelf --dyn-relocations %t10 2>&1 | FileCheck %s -DFILE=%t10 --check-prefix=INVALID-DT-PLTRELSZ + +# INVALID-DT-PLTRELSZ: warning: '[[FILE]]': invalid DT_PLTRELSZ value (0xff){{$}} + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .rela.plt + Type: SHT_RELA + Relocations: + - Offset: 0x0 + Type: R_X86_64_NONE + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_JMPREL + Value: 0x0 + - Tag: DT_PLTRELSZ + Value: 0xFF ## The valid value would be 0x18. + - Tag: DT_PLTREL + Value: 0x7 ## DT_RELA + - Tag: DT_NULL + Value: 0x0 +DynamicSymbols: [] +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .rela.plt + - Section: .dynamic diff --git a/llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test b/llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test index 30020cc..32cccdd 100644 --- a/llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test +++ b/llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test @@ -349,3 +349,55 @@ FileHeader: Type: ET_DYN Machine: EM_386 DynamicSymbols: [] + +## Case 9: Check what we print when: +## a) The size of the dynamic symbol table is not a multiple of its entry size. +# RUN: yaml2obj %s --docnum=10 -o %t10 +# RUN: llvm-readobj --dyn-symbols %t10 2>&1 | FileCheck %s -DFILE=%t10 --check-prefix=DYNSYM-SIZE-INVALID1 +# RUN: llvm-readelf --dyn-symbols %t10 2>&1 | FileCheck %s -DFILE=%t10 --check-prefix=DYNSYM-SIZE-INVALID1 +## b) The same, but the DT_SYMTAB tag is present. In this case the dynamic tag has priority over the +## information about a location and an entity size of the dynamic symbol table from the section header. +## The code uses sizeof(Elf_Sym) for an entity size, so it can't be incorrect and +## the message printed is a bit shorter. +# RUN: yaml2obj %s --docnum=11 -o %t11 +# RUN: llvm-readobj --dyn-symbols %t11 2>&1 | FileCheck %s -DFILE=%t11 --check-prefix=DYNSYM-SIZE-INVALID2 +# RUN: llvm-readelf --dyn-symbols %t11 2>&1 | FileCheck %s -DFILE=%t11 --check-prefix=DYNSYM-SIZE-INVALID2 + +# DYNSYM-SIZE-INVALID1: warning: '[[FILE]]': section with index 1 has invalid size (0x1) or entry size (0x10) + +# DYNSYM-SIZE-INVALID2: warning: '[[FILE]]': section with index 2 has invalid size (0x1){{$}} + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: + - Name: .dynsym + Type: SHT_DYNSYM + Size: 0x1 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_SYMTAB + Value: 0x100 + - Tag: DT_NULL + Value: 0 + - Name: .dynsym + Type: SHT_DYNSYM + Address: 0x100 + Size: 0x1 +ProgramHeaders: + - Type: PT_LOAD + VAddr: 0x100 + Sections: + - Section: .dynsym diff --git a/llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test b/llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test index 1a31fa3..9852240 100644 --- a/llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test +++ b/llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test @@ -7,8 +7,8 @@ # RUN: llvm-readelf --all %t.bad-size 2>&1 \ # RUN: | FileCheck %s -DFILE=%t.bad-size --implicit-check-not=warning --check-prefix WARN-GNU -# WARN: warning: '[[FILE]]': invalid section size (4) or entity size (16) -# WARN: warning: '[[FILE]]': invalid section size (4) or entity size (16) +# WARN: warning: '[[FILE]]': invalid PT_DYNAMIC size (0x4){{$}} +# WARN: warning: '[[FILE]]': section with index 1 has invalid size (0x4){{$}} # WARN: warning: '[[FILE]]': no valid dynamic table was found # WARN-EMPTY: # WARN: File: @@ -16,8 +16,8 @@ # WARN: ] # WARN: ProgramHeaders [ -# WARN-GNU: warning: '[[FILE]]': invalid section size (4) or entity size (16) -# WARN-GNU: warning: '[[FILE]]': invalid section size (4) or entity size (16) +# WARN-GNU: warning: '[[FILE]]': invalid PT_DYNAMIC size (0x4){{$}} +# WARN-GNU: warning: '[[FILE]]': section with index 1 has invalid size (0x4){{$}} # WARN-GNU: warning: '[[FILE]]': no valid dynamic table was found # WARN-GNU-NEXT: ELF Header: # WARN-GNU: Symbol table '.symtab' contains 1 entries: diff --git a/llvm/test/tools/llvm-readobj/ELF/dynamic-not-in-pt-dynamic.test b/llvm/test/tools/llvm-readobj/ELF/dynamic-not-in-pt-dynamic.test index cb8da63..7922ed0 100644 --- a/llvm/test/tools/llvm-readobj/ELF/dynamic-not-in-pt-dynamic.test +++ b/llvm/test/tools/llvm-readobj/ELF/dynamic-not-in-pt-dynamic.test @@ -12,7 +12,7 @@ # RUN: | FileCheck -DFILE=%t1.o --check-prefixes=WARNING1,GNU1 %s # WARNING1: warning: '[[FILE]]': The SHT_DYNAMIC section '.dynamic' is not contained within the PT_DYNAMIC segment -# WARNING1: warning: '[[FILE]]': invalid section size (1) or entity size (16) +# WARNING1: warning: '[[FILE]]': invalid PT_DYNAMIC size (0x1){{$}} # WARNING1: warning: '[[FILE]]': SHT_DYNAMIC section header and PT_DYNAMIC program header disagree about the location of the dynamic table # WARNING1: warning: '[[FILE]]': PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used @@ -124,7 +124,7 @@ ProgramHeaders: # RUN: llvm-readelf --dynamic-table %t3.o 2>&1 \ # RUN: | FileCheck -DFILE=%t3.o --check-prefix=WARNING3 --implicit-check-not="Dynamic" %s -# WARNING3: warning: '[[FILE]]': invalid section size (1) or entity size (16) +# WARNING3: warning: '[[FILE]]': invalid PT_DYNAMIC size (0x1){{$}} # WARNING3: warning: '[[FILE]]': SHT_DYNAMIC section header and PT_DYNAMIC program header disagree about the location of the dynamic table # WARNING3: warning: '[[FILE]]': no valid dynamic table was found diff --git a/llvm/test/tools/llvm-readobj/ELF/non-dynamic-in-pt-dynamic.test b/llvm/test/tools/llvm-readobj/ELF/non-dynamic-in-pt-dynamic.test index 77dea95..fad72ae 100644 --- a/llvm/test/tools/llvm-readobj/ELF/non-dynamic-in-pt-dynamic.test +++ b/llvm/test/tools/llvm-readobj/ELF/non-dynamic-in-pt-dynamic.test @@ -11,7 +11,7 @@ # RUN: | FileCheck %s --DFILE=%t1.o --check-prefixes=WARNING,GNU # WARNING: warning: '[[FILE]]': The SHT_DYNAMIC section '.dynamic' is not at the start of PT_DYNAMIC segment -# WARNING: warning: '[[FILE]]': invalid section size (33) or entity size (16) +# WARNING: warning: '[[FILE]]': invalid PT_DYNAMIC size (0x21){{$}} # WARNING: warning: '[[FILE]]': SHT_DYNAMIC section header and PT_DYNAMIC program header disagree about the location of the dynamic table # WARNING: warning: '[[FILE]]': PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used @@ -122,7 +122,7 @@ ProgramHeaders: # RUN: llvm-readobj --dynamic-table %t3.o 2>&1 | FileCheck %s --DFILE=%t3.o --check-prefixes=WARNING2,LLVM3 # RUN: llvm-readelf --dynamic-table %t3.o 2>&1 | FileCheck %s --DFILE=%t3.o --check-prefixes=WARNING2,GNU3 -# WARNING2: warning: '[[FILE]]': invalid section size (257) or entity size (16) +# WARNING2: warning: '[[FILE]]': invalid PT_DYNAMIC size (0x101){{$}} # WARNING2: warning: '[[FILE]]': PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used # LLVM3: DynamicSection [ (2 entries) diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index cd6600b..5671b6c 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -135,19 +135,34 @@ struct DynRegionInfo { /// Name of the file. Used for error reporting. StringRef FileName; + /// Error prefix. Used for error reporting to provide more information. + std::string Context; + /// Region size name. Used for error reporting. + StringRef SizePrintName = "size"; + /// Entry size name. Used for error reporting. If this field is empty, errors + /// will not mention the entry size. + StringRef EntSizePrintName = "entry size"; template ArrayRef getAsArrayRef() const { const Type *Start = reinterpret_cast(Addr); if (!Start) return {Start, Start}; - if (EntSize != sizeof(Type) || Size % EntSize) { - // TODO: Add a section index to this warning. - reportWarning(createError("invalid section size (" + Twine(Size) + - ") or entity size (" + Twine(EntSize) + ")"), - FileName); - return {Start, Start}; - } - return {Start, Start + (Size / EntSize)}; + if (EntSize == sizeof(Type) && (Size % EntSize == 0)) + return {Start, Start + (Size / EntSize)}; + + std::string Msg; + if (!Context.empty()) + Msg += Context + " has "; + + Msg += ("invalid " + SizePrintName + " (0x" + Twine::utohexstr(Size) + ")") + .str(); + if (!EntSizePrintName.empty()) + Msg += + (" or " + EntSizePrintName + " (0x" + Twine::utohexstr(EntSize) + ")") + .str(); + + reportWarning(createError(Msg.c_str()), FileName); + return {Start, Start}; } }; @@ -1847,6 +1862,9 @@ void ELFDumper::loadDynamicTable(const ELFFile *Obj) { bool IsPhdrTableValid = false; if (DynamicPhdr) { FromPhdr = createDRIFrom(DynamicPhdr, sizeof(Elf_Dyn)); + FromPhdr.SizePrintName = "PT_DYNAMIC size"; + FromPhdr.EntSizePrintName = ""; + IsPhdrTableValid = !FromPhdr.getAsArrayRef().empty(); } @@ -1860,6 +1878,11 @@ void ELFDumper::loadDynamicTable(const ELFFile *Obj) { FromSec = checkDRI({ObjF->getELFFile()->base() + DynamicSec->sh_offset, DynamicSec->sh_size, sizeof(Elf_Dyn), ObjF->getFileName()}); + FromSec.Context = ("section with index " + + Twine(DynamicSec - &cantFail(Obj->sections()).front())) + .str(); + FromSec.EntSizePrintName = ""; + IsSecTableValid = !FromSec.getAsArrayRef().empty(); } @@ -1920,8 +1943,9 @@ ELFDumper::ELFDumper(const object::ELFObjectFile *ObjF, DynPLTRelRegion(ObjF->getFileName()), DynSymRegion(ObjF->getFileName()), DynamicTable(ObjF->getFileName()) { const ELFFile *Obj = ObjF->getELFFile(); - for (const Elf_Shdr &Sec : - unwrapOrError(ObjF->getFileName(), Obj->sections())) { + typename ELFT::ShdrRange Sections = + unwrapOrError(ObjF->getFileName(), Obj->sections()); + for (const Elf_Shdr &Sec : Sections) { switch (Sec.sh_type) { case ELF::SHT_SYMTAB: if (!DotSymtabSec) @@ -1930,6 +1954,8 @@ ELFDumper::ELFDumper(const object::ELFObjectFile *ObjF, case ELF::SHT_DYNSYM: if (!DynSymRegion.Size) { DynSymRegion = createDRIFrom(&Sec); + DynSymRegion.Context = + ("section with index " + Twine(&Sec - &Sections.front())).str(); // This is only used (if Elf_Shdr present)for naming section in GNU // style DynSymtabName = @@ -2030,6 +2056,7 @@ void ELFDumper::parseDynamicTable(const ELFFile *Obj) { DynSymRegion.Addr = VA; DynSymRegion.EntSize = sizeof(Elf_Sym); + DynSymRegion.EntSizePrintName = ""; } break; } @@ -2038,9 +2065,11 @@ void ELFDumper::parseDynamicTable(const ELFFile *Obj) { break; case ELF::DT_RELASZ: DynRelaRegion.Size = Dyn.getVal(); + DynRelaRegion.SizePrintName = "DT_RELASZ value"; break; case ELF::DT_RELAENT: DynRelaRegion.EntSize = Dyn.getVal(); + DynRelaRegion.EntSizePrintName = "DT_RELAENT value"; break; case ELF::DT_SONAME: SONameOffset = Dyn.getVal(); @@ -2050,9 +2079,11 @@ void ELFDumper::parseDynamicTable(const ELFFile *Obj) { break; case ELF::DT_RELSZ: DynRelRegion.Size = Dyn.getVal(); + DynRelRegion.SizePrintName = "DT_RELSZ value"; break; case ELF::DT_RELENT: DynRelRegion.EntSize = Dyn.getVal(); + DynRelRegion.EntSizePrintName = "DT_RELENT value"; break; case ELF::DT_RELR: case ELF::DT_ANDROID_RELR: @@ -2061,10 +2092,16 @@ void ELFDumper::parseDynamicTable(const ELFFile *Obj) { case ELF::DT_RELRSZ: case ELF::DT_ANDROID_RELRSZ: DynRelrRegion.Size = Dyn.getVal(); + DynRelrRegion.SizePrintName = Dyn.d_tag == ELF::DT_RELRSZ + ? "DT_RELRSZ value" + : "DT_ANDROID_RELRSZ value"; break; case ELF::DT_RELRENT: case ELF::DT_ANDROID_RELRENT: DynRelrRegion.EntSize = Dyn.getVal(); + DynRelrRegion.EntSizePrintName = Dyn.d_tag == ELF::DT_RELRENT + ? "DT_RELRENT value" + : "DT_ANDROID_RELRENT value"; break; case ELF::DT_PLTREL: if (Dyn.getVal() == DT_REL) @@ -2075,12 +2112,14 @@ void ELFDumper::parseDynamicTable(const ELFFile *Obj) { reportError(createError(Twine("unknown DT_PLTREL value of ") + Twine((uint64_t)Dyn.getVal())), ObjF->getFileName()); + DynPLTRelRegion.EntSizePrintName = ""; break; case ELF::DT_JMPREL: DynPLTRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); break; case ELF::DT_PLTRELSZ: DynPLTRelRegion.Size = Dyn.getVal(); + DynPLTRelRegion.SizePrintName = "DT_PLTRELSZ value"; break; } } -- 2.7.4