mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
[llvm-readobj/llvm-readelf] - Reimplement dumping of the SHT_GNU_verneed section.
This is similar to D70495, but for SHT_GNU_verneed section. It solves the same problems: different implementations, lack of error reporting and no test coverage. DIfferential revision: https://reviews.llvm.org/D70826
This commit is contained in:
parent
0f6025a55a
commit
7c3b5b40df
@ -81,16 +81,18 @@ DynamicSymbols:
|
||||
## this situation properly.
|
||||
|
||||
# RUN: yaml2obj --docnum=2 %s -o %t2
|
||||
# RUN: llvm-readelf -V %t2 | FileCheck %s --check-prefix=GNU-NOLINK
|
||||
# RUN: llvm-readobj -V %t2 | FileCheck %s --check-prefix=LLVM-NOLINK
|
||||
# RUN: llvm-readelf -V %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=GNU-NOLINK
|
||||
# RUN: llvm-readobj -V %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=LLVM-NOLINK
|
||||
|
||||
# GNU-NOLINK: Version symbols section '.gnu.version' contains 2 entries:
|
||||
# GNU-NOLINK-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 5 (.dynsym)
|
||||
# GNU-NOLINK-NEXT: 000: 0 (*local*) 2 (bar)
|
||||
# GNU-NOLINK: Version needs section '.gnu.version_r' contains 1 entries:
|
||||
# GNU-NOLINK-NEXT: Addr: 0000000000000000 Offset: 0x000044 Link: 0 ()
|
||||
# GNU-NOLINK-NEXT: 0x0000: Version: 1 File: <invalid> Cnt: 1
|
||||
# GNU-NOLINK-NEXT: 0x0010: Name: <invalid> Flags: none Version: 2
|
||||
# GNU-NOLINK-EMPTY:
|
||||
# GNU-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
|
||||
# GNU-NOLINK-NEXT: 0x0000: Version: 1 File: <corrupt vn_file: 9> Cnt: 1
|
||||
# GNU-NOLINK-NEXT: 0x0010: Name: <corrupt> Flags: none Version: 2
|
||||
|
||||
# LLVM-NOLINK: VersionSymbols [
|
||||
# LLVM-NOLINK: Symbol {
|
||||
@ -104,17 +106,19 @@ DynamicSymbols:
|
||||
# LLVM-NOLINK-NEXT: ]
|
||||
|
||||
# LLVM-NOLINK: VersionRequirements [
|
||||
# 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: Dependency {
|
||||
# LLVM-NOLINK-NEXT: Version: 1
|
||||
# LLVM-NOLINK-NEXT: Count: 1
|
||||
# LLVM-NOLINK-NEXT: FileName: <invalid>
|
||||
# LLVM-NOLINK-NEXT: FileName: <corrupt vn_file: 9>
|
||||
# LLVM-NOLINK-NEXT: Entries [
|
||||
# LLVM-NOLINK-NEXT: Entry {
|
||||
# LLVM-NOLINK-NEXT: Hash: 0
|
||||
# LLVM-NOLINK-NEXT: Flags [ (0x0)
|
||||
# LLVM-NOLINK-NEXT: ]
|
||||
# LLVM-NOLINK-NEXT: Index: 2
|
||||
# LLVM-NOLINK-NEXT: Name: <invalid>
|
||||
# LLVM-NOLINK-NEXT: Name: <corrupt>
|
||||
# LLVM-NOLINK-NEXT: }
|
||||
# LLVM-NOLINK-NEXT: ]
|
||||
# LLVM-NOLINK-NEXT: }
|
||||
@ -212,14 +216,14 @@ DynamicSymbols:
|
||||
# LLVM-OFFSET-EQ-NEXT: Dependency {
|
||||
# LLVM-OFFSET-EQ-NEXT: Version: 1
|
||||
# LLVM-OFFSET-EQ-NEXT: Count: 1
|
||||
# LLVM-OFFSET-EQ-NEXT: FileName: <invalid>
|
||||
# LLVM-OFFSET-EQ-NEXT: FileName: <corrupt vn_file: 1>
|
||||
# LLVM-OFFSET-EQ-NEXT: Entries [
|
||||
# LLVM-OFFSET-EQ-NEXT: Entry {
|
||||
# LLVM-OFFSET-EQ-NEXT: Hash: 0
|
||||
# LLVM-OFFSET-EQ-NEXT: Flags [ (0x0)
|
||||
# LLVM-OFFSET-EQ-NEXT: ]
|
||||
# LLVM-OFFSET-EQ-NEXT: Index: 0
|
||||
# LLVM-OFFSET-EQ-NEXT: Name: <invalid>
|
||||
# LLVM-OFFSET-EQ-NEXT: Name: <corrupt>
|
||||
# LLVM-OFFSET-EQ-NEXT: }
|
||||
# LLVM-OFFSET-EQ-NEXT: ]
|
||||
# LLVM-OFFSET-EQ-NEXT: }
|
||||
@ -227,8 +231,8 @@ DynamicSymbols:
|
||||
|
||||
# GNU-OFFSET-EQ: Version needs section '.gnu.version_r' contains 1 entries:
|
||||
# GNU-OFFSET-EQ-NEXT: Addr: 0000000000000000 Offset: 0x000044 Link: 1 (.mystrtab)
|
||||
# GNU-OFFSET-EQ-NEXT: 0x0000: Version: 1 File: <invalid> Cnt: 1
|
||||
# GNU-OFFSET-EQ-NEXT: 0x0010: Name: <invalid> Flags: none Version: 0
|
||||
# GNU-OFFSET-EQ-NEXT: 0x0000: Version: 1 File: <corrupt vn_file: 1> Cnt: 1
|
||||
# GNU-OFFSET-EQ-NEXT: 0x0010: Name: <corrupt> Flags: none Version: 0
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
@ -268,14 +272,14 @@ DynamicSymbols:
|
||||
# LLVM-OFFSET-GR-NEXT: Dependency {
|
||||
# LLVM-OFFSET-GR-NEXT: Version: 1
|
||||
# LLVM-OFFSET-GR-NEXT: Count: 1
|
||||
# LLVM-OFFSET-GR-NEXT: FileName: <invalid>
|
||||
# LLVM-OFFSET-GR-NEXT: FileName: <corrupt vn_file: 1>
|
||||
# LLVM-OFFSET-GR-NEXT: Entries [
|
||||
# LLVM-OFFSET-GR-NEXT: Entry {
|
||||
# LLVM-OFFSET-GR-NEXT: Hash: 0
|
||||
# LLVM-OFFSET-GR-NEXT: Flags [ (0x0)
|
||||
# LLVM-OFFSET-GR-NEXT: ]
|
||||
# LLVM-OFFSET-GR-NEXT: Index: 0
|
||||
# LLVM-OFFSET-GR-NEXT: Name: <invalid>
|
||||
# LLVM-OFFSET-GR-NEXT: Name: <corrupt>
|
||||
# LLVM-OFFSET-GR-NEXT: }
|
||||
# LLVM-OFFSET-GR-NEXT: ]
|
||||
# LLVM-OFFSET-GR-NEXT: }
|
||||
@ -283,8 +287,8 @@ DynamicSymbols:
|
||||
|
||||
# GNU-OFFSET-GR: Version needs section '.gnu.version_r' contains 1 entries:
|
||||
# GNU-OFFSET-GR-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 1 (.mystrtab)
|
||||
# GNU-OFFSET-GR-NEXT: 0x0000: Version: 1 File: <invalid> Cnt: 1
|
||||
# GNU-OFFSET-GR-NEXT: 0x0010: Name: <invalid> Flags: none Version: 0
|
||||
# GNU-OFFSET-GR-NEXT: 0x0000: Version: 1 File: <corrupt vn_file: 1> Cnt: 1
|
||||
# GNU-OFFSET-GR-NEXT: 0x0010: Name: <corrupt> Flags: none Version: 0
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
@ -312,3 +316,207 @@ Sections:
|
||||
Other: 0
|
||||
DynamicSymbols:
|
||||
- Name: foo
|
||||
|
||||
## Check that we report a warning when sh_link references a non-existent section.
|
||||
|
||||
# RUN: yaml2obj --docnum=6 %s -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
|
||||
|
||||
# INVALID-LINK-LLVM: VersionRequirements [
|
||||
# INVALID-LINK-LLVM-EMPTY:
|
||||
# INVALID-LINK-LLVM-NEXT: warning: '[[FILE]]': invalid section linked to SHT_GNU_verneed section with index 1: invalid section index: 255
|
||||
# INVALID-LINK-LLVM-NEXT: Dependency {
|
||||
# INVALID-LINK-LLVM-NEXT: Version: 1
|
||||
# INVALID-LINK-LLVM-NEXT: Count: 1
|
||||
# INVALID-LINK-LLVM-NEXT: FileName: <corrupt vn_file: 1>
|
||||
# INVALID-LINK-LLVM-NEXT: Entries [
|
||||
# INVALID-LINK-LLVM-NEXT: Entry {
|
||||
# INVALID-LINK-LLVM-NEXT: Hash: 0
|
||||
# INVALID-LINK-LLVM-NEXT: Flags [ (0x0)
|
||||
# INVALID-LINK-LLVM-NEXT: ]
|
||||
# INVALID-LINK-LLVM-NEXT: Index: 0
|
||||
# INVALID-LINK-LLVM-NEXT: Name: <corrupt>
|
||||
# INVALID-LINK-LLVM-NEXT: }
|
||||
# INVALID-LINK-LLVM-NEXT: ]
|
||||
# INVALID-LINK-LLVM-NEXT: }
|
||||
# INVALID-LINK-LLVM-NEXT: ]
|
||||
|
||||
# INVALID-LINK-GNU: Version needs section '.gnu.version_r' contains 1 entries:
|
||||
# INVALID-LINK-GNU-EMPTY:
|
||||
# INVALID-LINK-GNU-NEXT: warning: '[[FILE]]': invalid section linked to SHT_GNU_verneed section with index 1: invalid section index: 255
|
||||
# INVALID-LINK-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 255 (<corrupt>)
|
||||
# INVALID-LINK-GNU-NEXT: 0x0000: Version: 1 File: <corrupt vn_file: 1> Cnt: 1
|
||||
# INVALID-LINK-GNU-NEXT: 0x0010: Name: <corrupt> Flags: none Version: 0
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .gnu.version_r
|
||||
Type: SHT_GNU_verneed
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Info: 1
|
||||
Link: 0xFF
|
||||
Dependencies:
|
||||
- Version: 1
|
||||
File: foo
|
||||
Entries:
|
||||
- Name: 'foo'
|
||||
Hash: 0
|
||||
Flags: 0
|
||||
Other: 0
|
||||
DynamicSymbols:
|
||||
- Name: foo
|
||||
|
||||
## 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
|
||||
# RUN: llvm-readobj --sections -V %t7 2>&1 | FileCheck %s -DFILE=%t7 --check-prefix=INVALID-DATA
|
||||
# RUN: llvm-readelf --sections -V %t7 2>&1 | FileCheck %s -DFILE=%t7 --check-prefix=INVALID-DATA
|
||||
|
||||
# INVALID-DATA: warning: '[[FILE]]': cannot read content of SHT_GNU_verneed section with index 1: section [index 1] has a sh_offset (0xffffffff) + sh_size (0x0) that cannot be represented
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .gnu.version_r
|
||||
Type: SHT_GNU_verneed
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Info: 1
|
||||
Link: .dynstr
|
||||
ShOffset: 0xFFFFFFFF
|
||||
## Triggers creation of the .dynstr.
|
||||
DynamicSymbols:
|
||||
- Name: foo
|
||||
|
||||
## Check that we report a warning when a SHT_GNU_verneed section contains a version dependency
|
||||
## that goes past the end of the section.
|
||||
|
||||
# RUN: yaml2obj --docnum=8 %s -o %t8
|
||||
# RUN: llvm-readobj --sections -V %t8 2>&1 | FileCheck %s -DFILE=%t8 --check-prefix=DEP-PAST-END
|
||||
# RUN: llvm-readelf --sections -V %t8 2>&1 | FileCheck %s -DFILE=%t8 --check-prefix=DEP-PAST-END
|
||||
|
||||
# DEP-PAST-END: warning: '[[FILE]]': invalid SHT_GNU_verneed section with index 1: version dependency 1 goes past the end of the section
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .gnu.version_r
|
||||
Type: SHT_GNU_verneed
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Info: 1
|
||||
Link: .dynstr
|
||||
ShSize: 0x1
|
||||
Dependencies:
|
||||
- Version: 1
|
||||
File: foo
|
||||
Entries:
|
||||
- Name: 'foo'
|
||||
Hash: 0
|
||||
Flags: 0
|
||||
Other: 0
|
||||
DynamicSymbols:
|
||||
- Name: foo
|
||||
|
||||
## Check we report a warning when a version dependency is not correctly aligned in memory.
|
||||
|
||||
# RUN: yaml2obj --docnum=9 %s -o %t9
|
||||
# RUN: llvm-readobj --sections -V %t9 2>&1 | FileCheck %s -DFILE=%t9 --check-prefix=MISALIGNED-DEP
|
||||
# RUN: llvm-readelf --sections -V %t9 2>&1 | FileCheck %s -DFILE=%t9 --check-prefix=MISALIGNED-DEP
|
||||
|
||||
# MISALIGNED-DEP: warning: '[[FILE]]': invalid SHT_GNU_verneed section with index 1: found a misaligned version dependency entry at offset 0x0
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Type: Fill
|
||||
Size: 0x1
|
||||
- Name: .gnu.version_r
|
||||
Type: SHT_GNU_verneed
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Info: 1
|
||||
Link: .dynstr
|
||||
Dependencies:
|
||||
- Version: 1
|
||||
File: foo
|
||||
Entries:
|
||||
- Name: 'foo'
|
||||
Hash: 0
|
||||
Flags: 0
|
||||
Other: 0
|
||||
DynamicSymbols:
|
||||
- Name: foo
|
||||
|
||||
## Check that we report a warning when a SHT_GNU_verneed section contains a dependency definition
|
||||
## that refers to an auxiliary entry that goes past the end of the section.
|
||||
|
||||
# RUN: yaml2obj --docnum=10 %s -o %t10
|
||||
# RUN: llvm-readobj --sections -V %t10 2>&1 | FileCheck %s -DFILE=%t10 --check-prefix=AUX-PAST-END
|
||||
# RUN: llvm-readelf --sections -V %t10 2>&1 | FileCheck %s -DFILE=%t10 --check-prefix=AUX-PAST-END
|
||||
|
||||
# AUX-PAST-END: warning: '[[FILE]]': invalid SHT_GNU_verneed section with index 1: version dependency 1 refers to an auxiliary entry that goes past the end of the section
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .gnu.version_r
|
||||
Type: SHT_GNU_verneed
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Info: 1
|
||||
Link: .dynstr
|
||||
ShSize: 21
|
||||
Dependencies:
|
||||
- Version: 1
|
||||
File: foo
|
||||
Entries:
|
||||
- Name: 'foo'
|
||||
Hash: 0
|
||||
Flags: 0
|
||||
Other: 0
|
||||
DynamicSymbols:
|
||||
- Name: foo
|
||||
|
||||
## Check we report a warning when an auxiliary entry is not correctly aligned in memory.
|
||||
|
||||
# RUN: yaml2obj %s --docnum=11 -o %t11
|
||||
# RUN: llvm-readobj -V %t11 2>&1 | FileCheck %s --check-prefix=MISALIGNED-AUX -DFILE=%t11
|
||||
# RUN: llvm-readelf -V %t11 2>&1 | FileCheck %s --check-prefix=MISALIGNED-AUX -DFILE=%t11
|
||||
|
||||
# MISALIGNED-AUX: warning: '[[FILE]]': invalid SHT_GNU_verneed section with index 1: found a misaligned auxiliary entry at offset 0x11
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .gnu.version_r
|
||||
Type: SHT_GNU_verneed
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Info: 1
|
||||
Link: .dynstr
|
||||
## The byte offset to the auxiliary entry is 0x11, i.e. it is not correctly aligned in memory.
|
||||
Content: "0100010001000000110000000000000000000000"
|
||||
DynamicSymbols:
|
||||
- Name: foo
|
||||
|
@ -167,6 +167,23 @@ struct VerDef {
|
||||
std::string Name;
|
||||
std::vector<VerdAux> AuxV;
|
||||
};
|
||||
|
||||
struct VernAux {
|
||||
unsigned Hash;
|
||||
unsigned Flags;
|
||||
unsigned Other;
|
||||
unsigned Offset;
|
||||
std::string Name;
|
||||
};
|
||||
|
||||
struct VerNeed {
|
||||
unsigned Version;
|
||||
unsigned Cnt;
|
||||
unsigned Offset;
|
||||
std::string File;
|
||||
std::vector<VernAux> AuxV;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
template <typename ELFT> class ELFDumper : public ObjDumper {
|
||||
@ -345,25 +362,50 @@ public:
|
||||
|
||||
Expected<std::vector<VerDef>>
|
||||
getVersionDefinitions(const Elf_Shdr *Sec) const;
|
||||
Expected<std::vector<VerNeed>>
|
||||
getVersionDependencies(const Elf_Shdr *Sec) const;
|
||||
};
|
||||
|
||||
static StringRef getSecTypeName(unsigned Type) {
|
||||
if (Type == ELF::SHT_GNU_versym)
|
||||
return "SHT_GNU_versym";
|
||||
if (Type == ELF::SHT_GNU_verdef)
|
||||
return "SHT_GNU_verdef";
|
||||
if (Type == ELF::SHT_GNU_verneed)
|
||||
return "SHT_GNU_verneed";
|
||||
llvm_unreachable("unexpected section type");
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
static Expected<StringRef> getLinkAsStrtab(const ELFFile<ELFT> *Obj,
|
||||
const typename ELFT::Shdr *Sec,
|
||||
unsigned SecNdx) {
|
||||
Expected<const typename ELFT::Shdr *> StrTabSecOrErr =
|
||||
Obj->getSection(Sec->sh_link);
|
||||
if (!StrTabSecOrErr)
|
||||
return createError("invalid section linked to " +
|
||||
getSecTypeName(Sec->sh_type) + " section with index " +
|
||||
Twine(SecNdx) + ": " +
|
||||
toString(StrTabSecOrErr.takeError()));
|
||||
|
||||
Expected<StringRef> StrTabOrErr = Obj->getStringTable(*StrTabSecOrErr);
|
||||
if (!StrTabOrErr)
|
||||
return createError("invalid string table linked to " +
|
||||
getSecTypeName(Sec->sh_type) + " section with index " +
|
||||
Twine(SecNdx) + ": " +
|
||||
toString(StrTabOrErr.takeError()));
|
||||
return *StrTabOrErr;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Expected<std::vector<VerDef>>
|
||||
ELFDumper<ELFT>::getVersionDefinitions(const Elf_Shdr *Sec) const {
|
||||
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
|
||||
unsigned SecNdx = Sec - &cantFail(Obj->sections()).front();
|
||||
|
||||
Expected<const Elf_Shdr *> StrTabSecOrErr = Obj->getSection(Sec->sh_link);
|
||||
if (!StrTabSecOrErr)
|
||||
return createError(
|
||||
"invalid section linked to SHT_GNU_verdef section with index " +
|
||||
Twine(SecNdx) + ": " + toString(StrTabSecOrErr.takeError()));
|
||||
|
||||
Expected<StringRef> StrTabOrErr = Obj->getStringTable(*StrTabSecOrErr);
|
||||
Expected<StringRef> StrTabOrErr = getLinkAsStrtab(Obj, Sec, SecNdx);
|
||||
if (!StrTabOrErr)
|
||||
return createError(
|
||||
"invalid string table linked to SHT_GNU_verdef section with index " +
|
||||
Twine(SecNdx) + ": " + toString(StrTabOrErr.takeError()));
|
||||
return StrTabOrErr.takeError();
|
||||
|
||||
Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj->getSectionContents(Sec);
|
||||
if (!ContentsOrErr)
|
||||
@ -448,6 +490,90 @@ ELFDumper<ELFT>::getVersionDefinitions(const Elf_Shdr *Sec) const {
|
||||
return Ret;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Expected<std::vector<VerNeed>>
|
||||
ELFDumper<ELFT>::getVersionDependencies(const Elf_Shdr *Sec) const {
|
||||
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
|
||||
unsigned SecNdx = Sec - &cantFail(Obj->sections()).front();
|
||||
|
||||
StringRef StrTab;
|
||||
Expected<StringRef> StrTabOrErr = getLinkAsStrtab(Obj, Sec, SecNdx);
|
||||
if (!StrTabOrErr)
|
||||
ELFDumperStyle->reportUniqueWarning(StrTabOrErr.takeError());
|
||||
else
|
||||
StrTab = *StrTabOrErr;
|
||||
|
||||
Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj->getSectionContents(Sec);
|
||||
if (!ContentsOrErr)
|
||||
return createError(
|
||||
"cannot read content of SHT_GNU_verneed section with index " +
|
||||
Twine(SecNdx) + ": " + toString(ContentsOrErr.takeError()));
|
||||
|
||||
const uint8_t *Start = ContentsOrErr->data();
|
||||
const uint8_t *End = Start + ContentsOrErr->size();
|
||||
const uint8_t *VerneedBuf = Start;
|
||||
|
||||
std::vector<VerNeed> Ret;
|
||||
for (unsigned I = 1; I <= /*VerneedNum=*/Sec->sh_info; ++I) {
|
||||
if (VerneedBuf + sizeof(Elf_Verdef) > End)
|
||||
return createError("invalid SHT_GNU_verneed section with index " +
|
||||
Twine(SecNdx) + ": version dependency " + Twine(I) +
|
||||
" goes past the end of the section");
|
||||
|
||||
if (uintptr_t(VerneedBuf) % sizeof(uint32_t) != 0)
|
||||
return createError(
|
||||
"invalid SHT_GNU_verneed section with index " + Twine(SecNdx) +
|
||||
": found a misaligned version dependency entry at offset 0x" +
|
||||
Twine::utohexstr(VerneedBuf - Start));
|
||||
|
||||
const Elf_Verneed *Verneed =
|
||||
reinterpret_cast<const Elf_Verneed *>(VerneedBuf);
|
||||
|
||||
VerNeed &VN = *Ret.emplace(Ret.end());
|
||||
VN.Version = Verneed->vn_version;
|
||||
VN.Cnt = Verneed->vn_cnt;
|
||||
VN.Offset = VerneedBuf - Start;
|
||||
|
||||
if (Verneed->vn_file < StrTab.size())
|
||||
VN.File = StrTab.drop_front(Verneed->vn_file);
|
||||
else
|
||||
VN.File = "<corrupt vn_file: " + to_string(Verneed->vn_file) + ">";
|
||||
|
||||
const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux;
|
||||
for (unsigned J = 0; J < Verneed->vn_cnt; ++J) {
|
||||
if (uintptr_t(VernauxBuf) % sizeof(uint32_t) != 0)
|
||||
return createError("invalid SHT_GNU_verneed section with index " +
|
||||
Twine(SecNdx) +
|
||||
": found a misaligned auxiliary entry at offset 0x" +
|
||||
Twine::utohexstr(VernauxBuf - Start));
|
||||
|
||||
if (VernauxBuf + sizeof(Elf_Vernaux) > End)
|
||||
return createError(
|
||||
"invalid SHT_GNU_verneed section with index " + Twine(SecNdx) +
|
||||
": version dependency " + Twine(I) +
|
||||
" refers to an auxiliary entry that goes past the end "
|
||||
"of the section");
|
||||
|
||||
const Elf_Vernaux *Vernaux =
|
||||
reinterpret_cast<const Elf_Vernaux *>(VernauxBuf);
|
||||
|
||||
VernAux &Aux = *VN.AuxV.emplace(VN.AuxV.end());
|
||||
Aux.Hash = Vernaux->vna_hash;
|
||||
Aux.Flags = Vernaux->vna_flags;
|
||||
Aux.Other = Vernaux->vna_other;
|
||||
Aux.Offset = VernauxBuf - Start;
|
||||
if (StrTab.size() <= Vernaux->vna_name)
|
||||
Aux.Name = "<corrupt>";
|
||||
else
|
||||
Aux.Name = StrTab.drop_front(Vernaux->vna_name);
|
||||
|
||||
VernauxBuf += Vernaux->vna_next;
|
||||
}
|
||||
VerneedBuf += Verneed->vn_next;
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {
|
||||
StringRef StrTable, SymtabName;
|
||||
@ -3946,9 +4072,10 @@ void GNUStyle<ELFT>::printGNUVersionSectionProlog(
|
||||
SymTabName =
|
||||
unwrapOrError(this->FileName, Obj->getSectionName(*SymTabOrErr));
|
||||
else
|
||||
this->reportUniqueWarning(createError(
|
||||
"invalid section linked to SHT_GNU_verdef section with index " +
|
||||
Twine(SecNdx) + ": " + toString(SymTabOrErr.takeError())));
|
||||
this->reportUniqueWarning(
|
||||
createError("invalid section linked to " +
|
||||
getSecTypeName(Sec->sh_type) + " section with index " +
|
||||
Twine(SecNdx) + ": " + toString(SymTabOrErr.takeError())));
|
||||
|
||||
OS << " Addr: " << format_hex_no_prefix(Sec->sh_addr, 16)
|
||||
<< " Offset: " << format_hex(Sec->sh_offset, 8)
|
||||
@ -4064,45 +4191,20 @@ void GNUStyle<ELFT>::printVersionDependencySection(const ELFFile<ELFT> *Obj,
|
||||
unsigned VerneedNum = Sec->sh_info;
|
||||
printGNUVersionSectionProlog(Obj, Sec, "Version needs", VerneedNum);
|
||||
|
||||
ArrayRef<uint8_t> SecData =
|
||||
unwrapOrError(this->FileName, Obj->getSectionContents(Sec));
|
||||
Expected<std::vector<VerNeed>> V =
|
||||
this->dumper()->getVersionDependencies(Sec);
|
||||
if (!V) {
|
||||
this->reportUniqueWarning(V.takeError());
|
||||
return;
|
||||
}
|
||||
|
||||
const Elf_Shdr *StrTabSec =
|
||||
unwrapOrError(this->FileName, Obj->getSection(Sec->sh_link));
|
||||
StringRef StringTable = {
|
||||
reinterpret_cast<const char *>(Obj->base() + StrTabSec->sh_offset),
|
||||
(size_t)StrTabSec->sh_size};
|
||||
|
||||
const uint8_t *VerneedBuf = SecData.data();
|
||||
for (unsigned I = 0; I < VerneedNum; ++I) {
|
||||
const Elf_Verneed *Verneed =
|
||||
reinterpret_cast<const Elf_Verneed *>(VerneedBuf);
|
||||
|
||||
StringRef File = StringTable.size() > Verneed->vn_file
|
||||
? StringTable.drop_front(Verneed->vn_file)
|
||||
: "<invalid>";
|
||||
|
||||
OS << format(" 0x%04x: Version: %u File: %s Cnt: %u\n",
|
||||
reinterpret_cast<const uint8_t *>(Verneed) - SecData.begin(),
|
||||
(unsigned)Verneed->vn_version, File.data(),
|
||||
(unsigned)Verneed->vn_cnt);
|
||||
|
||||
const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux;
|
||||
for (unsigned J = 0; J < Verneed->vn_cnt; ++J) {
|
||||
const Elf_Vernaux *Vernaux =
|
||||
reinterpret_cast<const Elf_Vernaux *>(VernauxBuf);
|
||||
|
||||
StringRef Name = StringTable.size() > Vernaux->vna_name
|
||||
? StringTable.drop_front(Vernaux->vna_name)
|
||||
: "<invalid>";
|
||||
|
||||
OS << format(" 0x%04x: Name: %s Flags: %s Version: %u\n",
|
||||
reinterpret_cast<const uint8_t *>(Vernaux) - SecData.begin(),
|
||||
Name.data(), versionFlagToString(Vernaux->vna_flags).c_str(),
|
||||
(unsigned)Vernaux->vna_other);
|
||||
VernauxBuf += Vernaux->vna_next;
|
||||
}
|
||||
VerneedBuf += Verneed->vn_next;
|
||||
for (const VerNeed &VN : *V) {
|
||||
OS << format(" 0x%04x: Version: %u File: %s Cnt: %u\n", VN.Offset,
|
||||
VN.Version, VN.File.data(), VN.Cnt);
|
||||
for (const VernAux &Aux : VN.AuxV)
|
||||
OS << format(" 0x%04x: Name: %s Flags: %s Version: %u\n", Aux.Offset,
|
||||
Aux.Name.data(), versionFlagToString(Aux.Flags).c_str(),
|
||||
Aux.Other);
|
||||
}
|
||||
OS << '\n';
|
||||
}
|
||||
@ -5853,45 +5955,27 @@ void LLVMStyle<ELFT>::printVersionDependencySection(const ELFFile<ELFT> *Obj,
|
||||
if (!Sec)
|
||||
return;
|
||||
|
||||
const uint8_t *SecData =
|
||||
reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
|
||||
const Elf_Shdr *StrTabSec =
|
||||
unwrapOrError(this->FileName, Obj->getSection(Sec->sh_link));
|
||||
StringRef StringTable = {
|
||||
reinterpret_cast<const char *>(Obj->base() + StrTabSec->sh_offset),
|
||||
(size_t)StrTabSec->sh_size};
|
||||
Expected<std::vector<VerNeed>> V =
|
||||
this->dumper()->getVersionDependencies(Sec);
|
||||
if (!V) {
|
||||
this->reportUniqueWarning(V.takeError());
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t *VerneedBuf = SecData;
|
||||
unsigned VerneedNum = Sec->sh_info;
|
||||
for (unsigned I = 0; I < VerneedNum; ++I) {
|
||||
const Elf_Verneed *Verneed =
|
||||
reinterpret_cast<const Elf_Verneed *>(VerneedBuf);
|
||||
for (const VerNeed &VN : *V) {
|
||||
DictScope Entry(W, "Dependency");
|
||||
W.printNumber("Version", Verneed->vn_version);
|
||||
W.printNumber("Count", Verneed->vn_cnt);
|
||||
W.printNumber("Version", VN.Version);
|
||||
W.printNumber("Count", VN.Cnt);
|
||||
W.printString("FileName", VN.File.c_str());
|
||||
|
||||
StringRef FileName = StringTable.size() > Verneed->vn_file
|
||||
? StringTable.drop_front(Verneed->vn_file)
|
||||
: "<invalid>";
|
||||
W.printString("FileName", FileName.data());
|
||||
|
||||
const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux;
|
||||
ListScope L(W, "Entries");
|
||||
for (unsigned J = 0; J < Verneed->vn_cnt; ++J) {
|
||||
const Elf_Vernaux *Vernaux =
|
||||
reinterpret_cast<const Elf_Vernaux *>(VernauxBuf);
|
||||
for (const VernAux &Aux : VN.AuxV) {
|
||||
DictScope Entry(W, "Entry");
|
||||
W.printNumber("Hash", Vernaux->vna_hash);
|
||||
W.printFlags("Flags", Vernaux->vna_flags, makeArrayRef(SymVersionFlags));
|
||||
W.printNumber("Index", Vernaux->vna_other);
|
||||
|
||||
StringRef Name = StringTable.size() > Vernaux->vna_name
|
||||
? StringTable.drop_front(Vernaux->vna_name)
|
||||
: "<invalid>";
|
||||
W.printString("Name", Name.data());
|
||||
VernauxBuf += Vernaux->vna_next;
|
||||
W.printNumber("Hash", Aux.Hash);
|
||||
W.printFlags("Flags", Aux.Flags, makeArrayRef(SymVersionFlags));
|
||||
W.printNumber("Index", Aux.Other);
|
||||
W.printString("Name", Aux.Name.c_str());
|
||||
}
|
||||
VerneedBuf += Verneed->vn_next;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user