mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-29 22:30:33 +00:00
[llvm-readobj][llvm-readelf] - Refactor parsing of the SHT_GNU_versym section.
This introduce a new helper which is used to parse the SHT_GNU_versym section. LLVM/GNU styles implementations now use it to share the logic. Differential revision: https://reviews.llvm.org/D71054
This commit is contained in:
parent
66a3737c3f
commit
ac568692e9
@ -637,13 +637,13 @@ Sections:
|
|||||||
Symbols:
|
Symbols:
|
||||||
- Name: foo
|
- Name: foo
|
||||||
|
|
||||||
## Check that we report an error if SHT_GNU_versym has invalid
|
## Check that we report a warning if SHT_GNU_versym has invalid
|
||||||
## sh_entsize value (3 instead of 2) when trying to access the entries.
|
## sh_entsize value (3 instead of 2) when trying to access the entries.
|
||||||
|
|
||||||
# RUN: yaml2obj %s --docnum=30 -o %t30
|
# RUN: yaml2obj %s --docnum=30 -o %t30
|
||||||
# RUN: not llvm-readobj -V %t30 2>&1 | FileCheck -DFILE=%t30 --check-prefix=INVALID-VER-SHENTSIZE %s
|
# RUN: llvm-readobj -V %t30 2>&1 | FileCheck -DFILE=%t30 --check-prefix=INVALID-VER-SHENTSIZE %s
|
||||||
|
|
||||||
# INVALID-VER-SHENTSIZE: error: '[[FILE]]': section [index 1] has invalid sh_entsize: expected 2, but got 3
|
# INVALID-VER-SHENTSIZE: warning: '[[FILE]]': cannot read content of SHT_GNU_versym section with index 1: section [index 1] has an invalid sh_entsize: 3
|
||||||
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader:
|
FileHeader:
|
||||||
@ -657,6 +657,7 @@ Sections:
|
|||||||
Type: SHT_GNU_versym
|
Type: SHT_GNU_versym
|
||||||
EntSize: 0x0000000000000003
|
EntSize: 0x0000000000000003
|
||||||
Entries: [ ]
|
Entries: [ ]
|
||||||
|
Link: .dynsym
|
||||||
## Needed to trigger creation of .dynsym.
|
## Needed to trigger creation of .dynsym.
|
||||||
DynamicSymbols:
|
DynamicSymbols:
|
||||||
- Name: foo
|
- Name: foo
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
# Test that multiple sections with the same type does not trigger an error.
|
# Test that multiple sections with the same type does not trigger an error.
|
||||||
|
|
||||||
# CHECK: ElfHeader {
|
# CHECK: ElfHeader {
|
||||||
|
# CHECK: VersionSymbols [
|
||||||
# CHECK: VersionDefinitions [
|
# CHECK: VersionDefinitions [
|
||||||
# CHECK: VersionRequirements [
|
# CHECK: VersionRequirements [
|
||||||
# CHECK: CGProfile [
|
# CHECK: CGProfile [
|
||||||
@ -23,10 +24,12 @@ Sections:
|
|||||||
EntSize: 24
|
EntSize: 24
|
||||||
- Name: .versym
|
- Name: .versym
|
||||||
Type: SHT_GNU_versym
|
Type: SHT_GNU_versym
|
||||||
Entries: [ ]
|
Entries: [ 0 ]
|
||||||
|
Link: .dynsym
|
||||||
- Name: .versym2
|
- Name: .versym2
|
||||||
Type: SHT_GNU_versym
|
Type: SHT_GNU_versym
|
||||||
Entries: [ ]
|
Entries: [ 0 ]
|
||||||
|
Link: .dynsym
|
||||||
- Name: .verdef
|
- Name: .verdef
|
||||||
Type: SHT_GNU_verdef
|
Type: SHT_GNU_verdef
|
||||||
Info: 0x0000000000000000
|
Info: 0x0000000000000000
|
||||||
@ -59,4 +62,5 @@ Sections:
|
|||||||
Content: ''
|
Content: ''
|
||||||
Symbols:
|
Symbols:
|
||||||
- Name: f
|
- Name: f
|
||||||
|
DynamicSymbols: []
|
||||||
...
|
...
|
||||||
|
@ -53,6 +53,7 @@ Sections:
|
|||||||
- Name: .gnu.version
|
- Name: .gnu.version
|
||||||
Type: SHT_GNU_versym
|
Type: SHT_GNU_versym
|
||||||
Entries: [ 0 ]
|
Entries: [ 0 ]
|
||||||
|
Link: .dynsym
|
||||||
- Name: .gnu.version_d
|
- Name: .gnu.version_d
|
||||||
Type: SHT_GNU_verdef
|
Type: SHT_GNU_verdef
|
||||||
Info: 0x0
|
Info: 0x0
|
||||||
@ -111,3 +112,4 @@ ProgramHeaders:
|
|||||||
Sections:
|
Sections:
|
||||||
- Section: .note.gnu.build-id
|
- Section: .note.gnu.build-id
|
||||||
Symbols: []
|
Symbols: []
|
||||||
|
DynamicSymbols: []
|
||||||
|
@ -275,6 +275,7 @@ DynamicSymbols:
|
|||||||
# INVALID-VERDEF-LLVM-NEXT: Name:
|
# INVALID-VERDEF-LLVM-NEXT: Name:
|
||||||
# INVALID-VERDEF-LLVM-NEXT: }
|
# INVALID-VERDEF-LLVM-NEXT: }
|
||||||
# INVALID-VERDEF-LLVM-NEXT: Symbol {
|
# INVALID-VERDEF-LLVM-NEXT: Symbol {
|
||||||
|
# INVALID-VERDEF-LLVM-NEXT: Version: 2
|
||||||
# INVALID-VERDEF-LLVM-EMPTY:
|
# INVALID-VERDEF-LLVM-EMPTY:
|
||||||
# INVALID-VERDEF-LLVM-NEXT: error: '[[FILE]]': invalid SHT_GNU_verdef section with index 2: version definition 1 goes past the end of the section
|
# INVALID-VERDEF-LLVM-NEXT: error: '[[FILE]]': invalid SHT_GNU_verdef section with index 2: version definition 1 goes past the end of the section
|
||||||
|
|
||||||
|
@ -101,9 +101,9 @@ DynamicSymbols:
|
|||||||
# LLVM-NOLINK-NEXT: Name:
|
# LLVM-NOLINK-NEXT: Name:
|
||||||
# LLVM-NOLINK-NEXT: }
|
# LLVM-NOLINK-NEXT: }
|
||||||
# LLVM-NOLINK-NEXT: Symbol {
|
# LLVM-NOLINK-NEXT: Symbol {
|
||||||
|
# LLVM-NOLINK-NEXT: Version: 2
|
||||||
# LLVM-NOLINK-EMPTY:
|
# LLVM-NOLINK-EMPTY:
|
||||||
# LLVM-NOLINK-NEXT: warning: '[[FILE]]': invalid string table linked to SHT_GNU_verneed section with index 2: invalid sh_type for string table section [index 0]: expected SHT_STRTAB, but got SHT_NULL
|
# LLVM-NOLINK-NEXT: warning: '[[FILE]]': invalid string table linked to SHT_GNU_verneed section with index 2: invalid sh_type for string table section [index 0]: expected SHT_STRTAB, but got SHT_NULL
|
||||||
# LLVM-NOLINK-NEXT: Version: 2
|
|
||||||
# LLVM-NOLINK-NEXT: Name: foo@<corrupt>
|
# LLVM-NOLINK-NEXT: Name: foo@<corrupt>
|
||||||
# LLVM-NOLINK-NEXT: }
|
# LLVM-NOLINK-NEXT: }
|
||||||
# LLVM-NOLINK-NEXT: ]
|
# LLVM-NOLINK-NEXT: ]
|
||||||
@ -183,8 +183,7 @@ Sections:
|
|||||||
AddressAlign: 4
|
AddressAlign: 4
|
||||||
## The byte offset to the auxiliary entry is 0x11, i.e. it is not correctly aligned in memory.
|
## The byte offset to the auxiliary entry is 0x11, i.e. it is not correctly aligned in memory.
|
||||||
Content: "0100010001000000110000000000000000000000"
|
Content: "0100010001000000110000000000000000000000"
|
||||||
DynamicSymbols:
|
DynamicSymbols: []
|
||||||
- Name: foo
|
|
||||||
|
|
||||||
## Here we check that we can properly dump the case when a dependency file name
|
## Here we check that we can properly dump the case when a dependency file name
|
||||||
## and/or a dependency name string offset is equal to the string table size.
|
## and/or a dependency name string offset is equal to the string table size.
|
||||||
|
220
test/tools/llvm-readobj/elf-versym-invalid.test
Normal file
220
test/tools/llvm-readobj/elf-versym-invalid.test
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
## Test how llvm-readobj/llvm-readelf tools handle invalid SHT_GNU_versym sections.
|
||||||
|
|
||||||
|
## Check that we report a warning when sh_link references a non-existent section.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=1 %s -o %t1
|
||||||
|
# RUN: llvm-readelf -V %t1 2>&1 | FileCheck -DFILE=%t1 %s --check-prefix=GNU-INVALID-LINK
|
||||||
|
# RUN: llvm-readobj -V %t1 2>&1 | FileCheck -DFILE=%t1 %s --check-prefix=LLVM-INVALID-LINK
|
||||||
|
|
||||||
|
# GNU-INVALID-LINK: Version symbols section '.gnu.version' contains 0 entries:
|
||||||
|
# GNU-INVALID-LINK-EMPTY:
|
||||||
|
# GNU-INVALID-LINK-NEXT: warning: '[[FILE]]': invalid section linked to SHT_GNU_versym section with index 1: invalid section index: 255
|
||||||
|
# GNU-INVALID-LINK-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 255 (<corrupt>)
|
||||||
|
|
||||||
|
# LLVM-INVALID-LINK: VersionSymbols [
|
||||||
|
# LLVM-INVALID-LINK-EMPTY:
|
||||||
|
# LLVM-INVALID-LINK-NEXT: warning: '[[FILE]]': invalid section linked to SHT_GNU_versym section with index 1: invalid section index: 255
|
||||||
|
# LLVM-INVALID-LINK-NEXT: ]
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_EXEC
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .gnu.version
|
||||||
|
Type: SHT_GNU_versym
|
||||||
|
Link: 0xFF
|
||||||
|
Entries: [ ]
|
||||||
|
|
||||||
|
## Check that we report a warning when the sh_link field of a SHT_GNU_versym section does not reference
|
||||||
|
## a dynamic symbol table section.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=2 %s -o %t2
|
||||||
|
# RUN: llvm-readelf -V %t2 2>&1 | FileCheck -DFILE=%t2 %s --check-prefix=INVALID-SYMBOL-TABLE-GNU
|
||||||
|
# RUN: llvm-readobj -V %t2 2>&1 | FileCheck -DFILE=%t2 %s --check-prefix=INVALID-SYMBOL-TABLE-LLVM
|
||||||
|
|
||||||
|
# INVALID-SYMBOL-TABLE-GNU: Version symbols section '.gnu.version' contains 1 entries:
|
||||||
|
# INVALID-SYMBOL-TABLE-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 0 ()
|
||||||
|
# INVALID-SYMBOL-TABLE-GNU-EMPTY:
|
||||||
|
# INVALID-SYMBOL-TABLE-GNU-NEXT: warning: '[[FILE]]': invalid section linked to SHT_GNU_versym section with index 1: expected SHT_DYNSYM, but got SHT_NULL
|
||||||
|
# INVALID-SYMBOL-TABLE-GNU-NEXT: 000: 0 (*local*)
|
||||||
|
|
||||||
|
# INVALID-SYMBOL-TABLE-LLVM: VersionSymbols [
|
||||||
|
# INVALID-SYMBOL-TABLE-LLVM-EMPTY:
|
||||||
|
# INVALID-SYMBOL-TABLE-LLVM-NEXT: warning: '[[FILE]]': invalid section linked to SHT_GNU_versym section with index 1: expected SHT_DYNSYM, but got SHT_NULL
|
||||||
|
# INVALID-SYMBOL-TABLE-LLVM-NEXT: ]
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_EXEC
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .gnu.version
|
||||||
|
Type: SHT_GNU_versym
|
||||||
|
Link: 0x0
|
||||||
|
Entries: [ 0 ]
|
||||||
|
|
||||||
|
## Check we report a warning when something is wrong with a string table linked to a symbol table that
|
||||||
|
## is linked with SHT_GNU_versym. In this case we are unable to produce LLVM style output,
|
||||||
|
## but GNU style is fine because it does not need that string table.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=3 %s -o %t3
|
||||||
|
# RUN: llvm-readelf -V %t3 2>&1 | FileCheck -DFILE=%t3 %s --check-prefix=INVALID-STRING-TABLE-GNU
|
||||||
|
# RUN: llvm-readobj -V %t3 2>&1 | FileCheck -DFILE=%t3 %s --check-prefix=INVALID-STRING-TABLE-LLVM
|
||||||
|
|
||||||
|
# INVALID-STRING-TABLE-GNU: Version symbols section '.gnu.version' contains 1 entries:
|
||||||
|
# INVALID-STRING-TABLE-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 5 (.dynsym)
|
||||||
|
# INVALID-STRING-TABLE-GNU-EMPTY:
|
||||||
|
# INVALID-STRING-TABLE-GNU-NEXT: warning: '[[FILE]]': can't get a string table for the symbol table linked to SHT_GNU_versym section with index 1: invalid string table linked to SHT_DYNSYM section with index 5: invalid sh_type for string table section [index 2]: expected SHT_STRTAB, but got SHT_NULL
|
||||||
|
# INVALID-STRING-TABLE-GNU-NEXT: 000: 0 (*local*)
|
||||||
|
|
||||||
|
# INVALID-STRING-TABLE-LLVM: VersionSymbols [
|
||||||
|
# INVALID-STRING-TABLE-LLVM-EMPTY:
|
||||||
|
# INVALID-STRING-TABLE-LLVM-NEXT: warning: '[[FILE]]': can't get a string table for the symbol table linked to SHT_GNU_versym section with index 1: invalid string table linked to SHT_DYNSYM section with index 5: invalid sh_type for string table section [index 2]: expected SHT_STRTAB, but got SHT_NULL
|
||||||
|
# INVALID-STRING-TABLE-LLVM-NEXT: ]
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_EXEC
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .gnu.version
|
||||||
|
Type: SHT_GNU_versym
|
||||||
|
Link: .dynsym
|
||||||
|
Entries: [ 0 ]
|
||||||
|
- Name: .dynstr
|
||||||
|
Type: SHT_NULL
|
||||||
|
DynamicSymbols: []
|
||||||
|
|
||||||
|
## Check we report a warning when a SHT_GNU_versym section is not correctly aligned in memory.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=4 %s -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-EMPTY:
|
||||||
|
# MISALIGNED-GNU-NEXT: warning: '[[FILE]]': the SHT_GNU_versym section with index 1 is misaligned
|
||||||
|
|
||||||
|
# MISALIGNED-LLVM: VersionSymbols [
|
||||||
|
# MISALIGNED-LLVM-EMPTY:
|
||||||
|
# MISALIGNED-LLVM-NEXT: warning: '[[FILE]]': the SHT_GNU_versym section with index 1 is misaligned
|
||||||
|
# MISALIGNED-LLVM-NEXT: ]
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_EXEC
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .gnu.version
|
||||||
|
Type: SHT_GNU_versym
|
||||||
|
Entries: [ ]
|
||||||
|
ShOffset: 0xffff
|
||||||
|
|
||||||
|
## Check we report a warning when a SHT_GNU_versym section has an invalid entry size.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=5 %s -o %t5
|
||||||
|
# RUN: llvm-readelf -V %t5 2>&1 | FileCheck -DFILE=%t5 %s --check-prefix=INVALID-ENT-SIZE-GNU
|
||||||
|
# RUN: llvm-readobj -V %t5 2>&1 | FileCheck -DFILE=%t5 %s --check-prefix=INVALID-ENT-SIZE-LLVM
|
||||||
|
|
||||||
|
# INVALID-ENT-SIZE-GNU: Version symbols section '.gnu.version' contains 1 entries:
|
||||||
|
# INVALID-ENT-SIZE-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 0 ()
|
||||||
|
# INVALID-ENT-SIZE-GNU-EMPTY:
|
||||||
|
# INVALID-ENT-SIZE-GNU-NEXT: warning: '[[FILE]]': cannot read content of SHT_GNU_versym section with index 1: section [index 1] has an invalid sh_entsize: 3
|
||||||
|
|
||||||
|
# INVALID-ENT-SIZE-LLVM: VersionSymbols [
|
||||||
|
# INVALID-ENT-SIZE-LLVM-EMPTY:
|
||||||
|
# INVALID-ENT-SIZE-LLVM-NEXT: warning: '[[FILE]]': cannot read content of SHT_GNU_versym section with index 1: section [index 1] has an invalid sh_entsize: 3
|
||||||
|
# INVALID-ENT-SIZE-LLVM-NEXT: ]
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_EXEC
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .gnu.version
|
||||||
|
Type: SHT_GNU_versym
|
||||||
|
Entries: [ 0 ]
|
||||||
|
EntSize: 3
|
||||||
|
|
||||||
|
## Check we report a warning when the number of version entries does not match the number of symbols in the associated symbol table.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=6 %s -o %t6
|
||||||
|
# RUN: llvm-readelf -V %t6 2>&1 | FileCheck -DFILE=%t6 %s --check-prefix=SYMBOLS-NUM-MISMATCH-GNU
|
||||||
|
# RUN: llvm-readobj -V %t6 2>&1 | FileCheck -DFILE=%t6 %s --check-prefix=SYMBOLS-NUM-MISMATCH-LLVM
|
||||||
|
|
||||||
|
# SYMBOLS-NUM-MISMATCH-GNU: Version symbols section '.gnu.version' contains 2 entries:
|
||||||
|
# SYMBOLS-NUM-MISMATCH-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 4 (.dynsym)
|
||||||
|
# SYMBOLS-NUM-MISMATCH-GNU-EMPTY:
|
||||||
|
# SYMBOLS-NUM-MISMATCH-GNU-NEXT: warning: '[[FILE]]': SHT_GNU_versym section with index 1: the number of entries (2) does not match the number of symbols (3) in the symbol table with index 4
|
||||||
|
# SYMBOLS-NUM-MISMATCH-GNU-NEXT: 000: 0 (*local*) 1 (*global*)
|
||||||
|
|
||||||
|
# SYMBOLS-NUM-MISMATCH-LLVM: VersionSymbols [
|
||||||
|
# SYMBOLS-NUM-MISMATCH-LLVM-EMPTY:
|
||||||
|
# SYMBOLS-NUM-MISMATCH-LLVM-NEXT: warning: '[[FILE]]': SHT_GNU_versym section with index 1: the number of entries (2) does not match the number of symbols (3) in the symbol table with index 4
|
||||||
|
# SYMBOLS-NUM-MISMATCH-LLVM-NEXT: ]
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_EXEC
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .gnu.version
|
||||||
|
Type: SHT_GNU_versym
|
||||||
|
Entries: [ 0, 1 ]
|
||||||
|
Link: .dynsym
|
||||||
|
DynamicSymbols:
|
||||||
|
- Name: foo
|
||||||
|
- Name: bar
|
||||||
|
|
||||||
|
## Check we can dump a SHT_GNU_versym section when it is linked to a custom dynamic symbol
|
||||||
|
## table that is not called ".dynsym".
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=7 %s -o %t7
|
||||||
|
# RUN: llvm-readelf -V %t7 2>&1 | FileCheck -DFILE=%t7 %s --check-prefix=CUSTOM-SYMTAB-GNU
|
||||||
|
# RUN: llvm-readobj -V %t7 2>&1 | FileCheck -DFILE=%t7 %s --check-prefix=CUSTOM-SYMTAB-LLVM
|
||||||
|
|
||||||
|
# CUSTOM-SYMTAB-GNU: Version symbols section '.gnu.version' contains 1 entries:
|
||||||
|
# CUSTOM-SYMTAB-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 2 (.foo.dynsym)
|
||||||
|
# CUSTOM-SYMTAB-GNU-NEXT: 000: 0 (*local*)
|
||||||
|
|
||||||
|
# CUSTOM-SYMTAB-LLVM: VersionSymbols [
|
||||||
|
# CUSTOM-SYMTAB-LLVM-NEXT: Symbol {
|
||||||
|
# CUSTOM-SYMTAB-LLVM-NEXT: Version: 0
|
||||||
|
# CUSTOM-SYMTAB-LLVM-NEXT: Name:
|
||||||
|
# CUSTOM-SYMTAB-LLVM-NEXT: }
|
||||||
|
# CUSTOM-SYMTAB-LLVM-NEXT: ]
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_EXEC
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .gnu.version
|
||||||
|
Type: SHT_GNU_versym
|
||||||
|
Link: .foo.dynsym
|
||||||
|
Entries: [ 0 ]
|
||||||
|
## A custom empty dynamic symbol table with a null entry.
|
||||||
|
- Name: .foo.dynsym
|
||||||
|
Type: SHT_DYNSYM
|
||||||
|
Link: .dynstr
|
||||||
|
EntSize: 24
|
||||||
|
Size: 24
|
||||||
|
DynamicSymbols:
|
||||||
|
- Name: foo
|
||||||
|
- Name: bar
|
@ -339,6 +339,9 @@ public:
|
|||||||
const Elf_Hash *getHashTable() const { return HashTable; }
|
const Elf_Hash *getHashTable() const { return HashTable; }
|
||||||
const Elf_GnuHash *getGnuHashTable() const { return GnuHashTable; }
|
const Elf_GnuHash *getGnuHashTable() const { return GnuHashTable; }
|
||||||
|
|
||||||
|
Expected<ArrayRef<Elf_Versym>> getVersionTable(const Elf_Shdr *Sec,
|
||||||
|
ArrayRef<Elf_Sym> *SymTab,
|
||||||
|
StringRef *StrTab) const;
|
||||||
Expected<std::vector<VerDef>>
|
Expected<std::vector<VerDef>>
|
||||||
getVersionDefinitions(const Elf_Shdr *Sec) const;
|
getVersionDefinitions(const Elf_Shdr *Sec) const;
|
||||||
Expected<std::vector<VerNeed>>
|
Expected<std::vector<VerNeed>>
|
||||||
@ -368,6 +371,90 @@ static Expected<StringRef> getLinkAsStrtab(const ELFFile<ELFT> *Obj,
|
|||||||
return *StrTabOrErr;
|
return *StrTabOrErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the linked symbol table and associated string table for a given section.
|
||||||
|
template <class ELFT>
|
||||||
|
static Expected<std::pair<typename ELFT::SymRange, StringRef>>
|
||||||
|
getLinkAsSymtab(const ELFFile<ELFT> *Obj, const typename ELFT::Shdr *Sec,
|
||||||
|
unsigned SecNdx, unsigned ExpectedType) {
|
||||||
|
Expected<const typename ELFT::Shdr *> SymtabOrErr =
|
||||||
|
Obj->getSection(Sec->sh_link);
|
||||||
|
if (!SymtabOrErr)
|
||||||
|
return createError("invalid section linked to " +
|
||||||
|
object::getELFSectionTypeName(
|
||||||
|
Obj->getHeader()->e_machine, Sec->sh_type) +
|
||||||
|
" section with index " + Twine(SecNdx) + ": " +
|
||||||
|
toString(SymtabOrErr.takeError()));
|
||||||
|
|
||||||
|
if ((*SymtabOrErr)->sh_type != ExpectedType)
|
||||||
|
return createError(
|
||||||
|
"invalid section linked to " +
|
||||||
|
object::getELFSectionTypeName(Obj->getHeader()->e_machine,
|
||||||
|
Sec->sh_type) +
|
||||||
|
" section with index " + Twine(SecNdx) + ": expected " +
|
||||||
|
object::getELFSectionTypeName(Obj->getHeader()->e_machine,
|
||||||
|
ExpectedType) +
|
||||||
|
", but got " +
|
||||||
|
object::getELFSectionTypeName(Obj->getHeader()->e_machine,
|
||||||
|
(*SymtabOrErr)->sh_type));
|
||||||
|
|
||||||
|
Expected<StringRef> StrTabOrErr =
|
||||||
|
getLinkAsStrtab(Obj, *SymtabOrErr, Sec->sh_link);
|
||||||
|
if (!StrTabOrErr)
|
||||||
|
return createError(
|
||||||
|
"can't get a string table for the symbol table linked to " +
|
||||||
|
object::getELFSectionTypeName(Obj->getHeader()->e_machine,
|
||||||
|
Sec->sh_type) +
|
||||||
|
" section with index " + Twine(SecNdx) + ": " +
|
||||||
|
toString(StrTabOrErr.takeError()));
|
||||||
|
|
||||||
|
Expected<typename ELFT::SymRange> SymsOrErr = Obj->symbols(*SymtabOrErr);
|
||||||
|
if (!SymsOrErr)
|
||||||
|
return createError(
|
||||||
|
"unable to read symbols from the symbol table with index " +
|
||||||
|
Twine(Sec->sh_link) + ": " + toString(SymsOrErr.takeError()));
|
||||||
|
|
||||||
|
return std::make_pair(*SymsOrErr, *StrTabOrErr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
Expected<ArrayRef<typename ELFT::Versym>>
|
||||||
|
ELFDumper<ELFT>::getVersionTable(const Elf_Shdr *Sec, ArrayRef<Elf_Sym> *SymTab,
|
||||||
|
StringRef *StrTab) const {
|
||||||
|
assert((!SymTab && !StrTab) || (SymTab && StrTab));
|
||||||
|
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
|
||||||
|
unsigned SecNdx = Sec - &cantFail(Obj->sections()).front();
|
||||||
|
|
||||||
|
if (uintptr_t(Obj->base() + Sec->sh_offset) % sizeof(uint16_t) != 0)
|
||||||
|
return createError("the SHT_GNU_versym section with index " +
|
||||||
|
Twine(SecNdx) + " is misaligned");
|
||||||
|
|
||||||
|
Expected<ArrayRef<Elf_Versym>> VersionsOrErr =
|
||||||
|
Obj->template getSectionContentsAsArray<Elf_Versym>(Sec);
|
||||||
|
if (!VersionsOrErr)
|
||||||
|
return createError(
|
||||||
|
"cannot read content of SHT_GNU_versym section with index " +
|
||||||
|
Twine(SecNdx) + ": " + toString(VersionsOrErr.takeError()));
|
||||||
|
|
||||||
|
Expected<std::pair<ArrayRef<Elf_Sym>, StringRef>> SymTabOrErr =
|
||||||
|
getLinkAsSymtab(Obj, Sec, SecNdx, SHT_DYNSYM);
|
||||||
|
if (!SymTabOrErr) {
|
||||||
|
ELFDumperStyle->reportUniqueWarning(SymTabOrErr.takeError());
|
||||||
|
return *VersionsOrErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SymTabOrErr->first.size() != VersionsOrErr->size())
|
||||||
|
ELFDumperStyle->reportUniqueWarning(
|
||||||
|
createError("SHT_GNU_versym section with index " + Twine(SecNdx) +
|
||||||
|
": the number of entries (" + Twine(VersionsOrErr->size()) +
|
||||||
|
") does not match the number of symbols (" +
|
||||||
|
Twine(SymTabOrErr->first.size()) +
|
||||||
|
") in the symbol table with index " + Twine(Sec->sh_link)));
|
||||||
|
|
||||||
|
if (SymTab)
|
||||||
|
std::tie(*SymTab, *StrTab) = *SymTabOrErr;
|
||||||
|
return *VersionsOrErr;
|
||||||
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
Expected<std::vector<VerDef>>
|
Expected<std::vector<VerDef>>
|
||||||
ELFDumper<ELFT>::getVersionDefinitions(const Elf_Shdr *Sec) const {
|
ELFDumper<ELFT>::getVersionDefinitions(const Elf_Shdr *Sec) const {
|
||||||
@ -4013,23 +4100,24 @@ void GNUStyle<ELFT>::printVersionSymbolSection(const ELFFile<ELFT> *Obj,
|
|||||||
if (!Sec)
|
if (!Sec)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned Entries = Sec->sh_size / sizeof(Elf_Versym);
|
printGNUVersionSectionProlog(Obj, Sec, "Version symbols",
|
||||||
printGNUVersionSectionProlog(Obj, Sec, "Version symbols", Entries);
|
Sec->sh_size / sizeof(Elf_Versym));
|
||||||
|
Expected<ArrayRef<Elf_Versym>> VerTableOrErr =
|
||||||
const uint8_t *VersymBuf =
|
this->dumper()->getVersionTable(Sec, /*SymTab=*/nullptr,
|
||||||
reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
|
/*StrTab=*/nullptr);
|
||||||
const ELFDumper<ELFT> *Dumper = this->dumper();
|
if (!VerTableOrErr) {
|
||||||
|
this->reportUniqueWarning(VerTableOrErr.takeError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// readelf prints 4 entries per line.
|
// readelf prints 4 entries per line.
|
||||||
|
uint64_t Entries = VerTableOrErr->size();
|
||||||
for (uint64_t VersymRow = 0; VersymRow < Entries; VersymRow += 4) {
|
for (uint64_t VersymRow = 0; VersymRow < Entries; VersymRow += 4) {
|
||||||
OS << " " << format_hex_no_prefix(VersymRow, 3) << ":";
|
OS << " " << format_hex_no_prefix(VersymRow, 3) << ":";
|
||||||
|
|
||||||
for (uint64_t VersymIndex = 0;
|
for (uint64_t I = 0; (I < 4) && (I + VersymRow) < Entries; ++I) {
|
||||||
(VersymIndex < 4) && (VersymIndex + VersymRow) < Entries;
|
unsigned Version = (*VerTableOrErr)[VersymRow + I].vs_index;
|
||||||
++VersymIndex) {
|
switch (Version) {
|
||||||
const Elf_Versym *Versym =
|
|
||||||
reinterpret_cast<const Elf_Versym *>(VersymBuf);
|
|
||||||
switch (Versym->vs_index) {
|
|
||||||
case 0:
|
case 0:
|
||||||
OS << " 0 (*local*) ";
|
OS << " 0 (*local*) ";
|
||||||
break;
|
break;
|
||||||
@ -4039,18 +4127,17 @@ void GNUStyle<ELFT>::printVersionSymbolSection(const ELFFile<ELFT> *Obj,
|
|||||||
default:
|
default:
|
||||||
bool IsDefault = true;
|
bool IsDefault = true;
|
||||||
std::string VersionName =
|
std::string VersionName =
|
||||||
Dumper->getSymbolVersionByIndex(Versym->vs_index, IsDefault);
|
this->dumper()->getSymbolVersionByIndex(Version, IsDefault);
|
||||||
|
|
||||||
if (!VersionName.empty())
|
if (!VersionName.empty())
|
||||||
VersionName = "(" + VersionName + ")";
|
VersionName = "(" + VersionName + ")";
|
||||||
else
|
else
|
||||||
VersionName = "(*invalid*)";
|
VersionName = "(*invalid*)";
|
||||||
|
|
||||||
OS << format("%4x%c", Versym->vs_index & VERSYM_VERSION,
|
OS << format("%4x%c", Version & VERSYM_VERSION,
|
||||||
Versym->vs_index & VERSYM_HIDDEN ? 'h' : ' ');
|
Version & VERSYM_HIDDEN ? 'h' : ' ');
|
||||||
OS << left_justify(VersionName, 13);
|
OS << left_justify(VersionName, 13);
|
||||||
}
|
}
|
||||||
VersymBuf += sizeof(Elf_Versym);
|
|
||||||
}
|
}
|
||||||
OS << '\n';
|
OS << '\n';
|
||||||
}
|
}
|
||||||
@ -5834,20 +5921,23 @@ void LLVMStyle<ELFT>::printVersionSymbolSection(const ELFFile<ELFT> *Obj,
|
|||||||
if (!Sec)
|
if (!Sec)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const uint8_t *VersymBuf =
|
StringRef StrTable;
|
||||||
reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
|
ArrayRef<Elf_Sym> Syms;
|
||||||
const ELFDumper<ELFT> *Dumper = this->dumper();
|
Expected<ArrayRef<Elf_Versym>> VerTableOrErr =
|
||||||
StringRef StrTable = Dumper->getDynamicStringTable();
|
this->dumper()->getVersionTable(Sec, &Syms, &StrTable);
|
||||||
|
if (!VerTableOrErr) {
|
||||||
|
this->reportUniqueWarning(VerTableOrErr.takeError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Same number of entries in the dynamic symbol table (DT_SYMTAB).
|
if (StrTable.empty() || Syms.empty() || Syms.size() != VerTableOrErr->size())
|
||||||
for (const Elf_Sym &Sym : Dumper->dynamic_symbols()) {
|
return;
|
||||||
|
|
||||||
|
for (size_t I = 0, E = Syms.size(); I < E; ++I) {
|
||||||
DictScope S(W, "Symbol");
|
DictScope S(W, "Symbol");
|
||||||
const Elf_Versym *Versym = reinterpret_cast<const Elf_Versym *>(VersymBuf);
|
W.printNumber("Version", (*VerTableOrErr)[I].vs_index & VERSYM_VERSION);
|
||||||
std::string FullSymbolName =
|
W.printString("Name", this->dumper()->getFullSymbolName(
|
||||||
Dumper->getFullSymbolName(&Sym, StrTable, true /* IsDynamic */);
|
&Syms[I], StrTable, /*IsDynamic=*/true));
|
||||||
W.printNumber("Version", Versym->vs_index & VERSYM_VERSION);
|
|
||||||
W.printString("Name", FullSymbolName);
|
|
||||||
VersymBuf += sizeof(Elf_Versym);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user