Skip to content

[llvm-objdump] Rework .gnu.version_d dumping #128434

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions llvm/include/llvm/Object/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ struct VerdAux {

struct VerDef {
unsigned Offset;
unsigned Version;
unsigned Flags;
unsigned Ndx;
unsigned Cnt;
uint16_t Version;
uint16_t Flags;
uint16_t Ndx;
uint16_t Cnt;
unsigned Hash;
std::string Name;
std::vector<VerdAux> AuxV;
Expand Down Expand Up @@ -1057,8 +1057,8 @@ ELFFile<ELFT>::getVersionDefinitions(const Elf_Shdr &Sec) const {

VerdAux Aux;
Aux.Offset = VerdauxBuf - Start;
if (Verdaux->vda_name <= StrTabOrErr->size())
Aux.Name = std::string(StrTabOrErr->drop_front(Verdaux->vda_name));
if (Verdaux->vda_name < StrTabOrErr->size())
Aux.Name = std::string(StrTabOrErr->drop_front(Verdaux->vda_name).data());
else
Aux.Name = ("<invalid vda_name: " + Twine(Verdaux->vda_name) + ">").str();
return Aux;
Expand Down
1 change: 1 addition & 0 deletions llvm/test/tools/llvm-objdump/ELF/private-headers.test
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Sections:
Value: 0x0
- Name: .gnu.version_d
Type: SHT_GNU_verdef
AddressAlign: 4
Entries:
- Version: 1
Flags: 1
Expand Down
77 changes: 77 additions & 0 deletions llvm/test/tools/llvm-objdump/ELF/verdef-invalid.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
## Adapted from test/llvm-readobj/ELF/verdef-invalid.test
## Check that we report a warning when a SHT_GNU_verdef section contains a version definition
## that refers to an auxiliary entry that goes past the end of the section.

# RUN: yaml2obj %s -o %t
# RUN: llvm-objdump -p %t 2>&1 | FileCheck %s --check-prefix=AUX-PAST-END -DFILE=%t

# AUX-PAST-END: warning: '[[FILE]]': invalid SHT_GNU_verdef section with index 1: version definition 1 refers to an auxiliary entry that goes past the end of the section

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Sections:
- Name: .gnu.version_d
Type: SHT_GNU_verdef
Entries:
- Names:
- FOO
## The correct sh_size is 28.
ShSize: 27
DynamicSymbols:
- Name: foo

## Check we report a warning when a version definition is not correctly aligned in memory.

# RUN: yaml2obj %s --docnum=2 -o %t2
# RUN: llvm-objdump -p %t2 2>&1 | FileCheck %s --check-prefix=MISALIGNED-DEF -DFILE=%t2

# MISALIGNED-DEF: warning: '[[FILE]]': invalid SHT_GNU_verdef section with index 1: found a misaligned version definition entry at offset 0x0

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Sections:
- Type: Fill
Size: 0x1
- Name: .gnu.version_d
Type: SHT_GNU_verdef
Link: .dynstr
Info: 0x1
Entries:
- Names:
- FOO
DynamicSymbols:
- Name: foo

## Check we report "invalid vda_name" when vda_name = size(.dynstr)

# RUN: yaml2obj %s --docnum=3 -o %t3
# RUN: llvm-objdump -p %t3 2>&1 | FileCheck %s --check-prefix=VDANAME-PAST-END --implicit-check-not=warning:

# VDANAME-PAST-END: Version definitions:
# VDANAME-PAST-END-NEXT: 0 0x00 0x00000000 V0
# VDANAME-PAST-END-NEXT: <invalid vda_name: 7>

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Sections:
- Name: .gnu.version_d
Type: SHT_GNU_verdef
Flags: [ SHF_ALLOC ]
Link: .dynstr
Info: 0x1
## The byte offset to the auxiliary entry is 0x13, i.e. it is not correctly aligned in memory.
Content: "010000000000020000000000140000000000000004000000080000000700000000000000"
DynamicSymbols:
- Name: V1
Binding: STB_GLOBAL
- Name: V0
Binding: STB_GLOBAL
28 changes: 19 additions & 9 deletions llvm/test/tools/llvm-objdump/ELF/verdef.test
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# RUN: yaml2obj %s -o %t
# RUN: llvm-objdump -p %t | FileCheck --strict-whitespace %s
# RUN: llvm-objdump -p %t | FileCheck --match-full-lines --strict-whitespace %s

# CHECK: Dynamic Section:
# CHECK-EMPTY:
# CHECK-NEXT: Version definitions:
# CHECK-NEXT: 1 0x01 0x075bcd15 foo
# CHECK-NEXT: 2 0x02 0x3ade68b1 VERSION_1
# CHECK-NEXT: VERSION_2
# CHECK:Dynamic Section:
#CHECK-EMPTY:
# CHECK-NEXT:Version definitions:
# CHECK-NEXT:2 0x01 0x075bcd15 foo
# CHECK-NEXT:3 0x02 0x3ade68b1 VERSION_1
# CHECK-NEXT: VERSION_2
# CHECK-NEXT:4 0x00 0x0000007b VERSION_3
# CHECK-NEXT: VERSION_4 VERSION_5

--- !ELF
FileHeader:
Expand All @@ -24,17 +26,25 @@ Sections:
Entries:
- Version: 1
Flags: 1
VersionNdx: 1
VersionNdx: 2
Hash: 123456789
Names:
- foo
- Version: 1
Flags: 2
VersionNdx: 2
VersionNdx: 3
Hash: 987654321
Names:
- VERSION_1
- VERSION_2
- Version: 1
Flags: 0
VersionNdx: 4
Hash: 123
Names:
- VERSION_3
- VERSION_4
- VERSION_5
DynamicSymbols:
- Name: bar
Binding: STB_GLOBAL
Expand Down
36 changes: 35 additions & 1 deletion llvm/test/tools/llvm-readobj/ELF/verdef-invalid.test
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ Sections:
Entries:
- Names:
- FOO
ShSize: 21
## The correct sh_size is 28.
ShSize: 27
DynamicSymbols:
- Name: foo

Expand Down Expand Up @@ -290,3 +291,36 @@ Sections:
DynamicSymbols:
- Name: foo
Binding: STB_GLOBAL

## Check we report "invalid vda_name" when vda_name = size(.dynstr)

# RUN: yaml2obj %s --docnum=10 -o %t11
# RUN: llvm-readobj -V %t11 2>&1 | FileCheck %s --check-prefix=VDANAME-PAST-END-LLVM -DFILE=%t11 --implicit-check-not=warning:
# RUN: llvm-readelf -V %t11 2>&1 | FileCheck %s --check-prefix=VDANAME-PAST-END-GNU -DFILE=%t11 --implicit-check-not=warning:

# VDANAME-PAST-END-LLVM: Name: V0
# VDANAME-PAST-END-LLVM-NEXT: Predecessors: [<invalid vda_name: 7>]

# VDANAME-PAST-END-GNU: Version definition section '.gnu.version_d' contains 1 entries:
# VDANAME-PAST-END-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 3 (.dynstr)
# VDANAME-PAST-END-GNU-NEXT: 0x0000: Rev: 1 Flags: none Index: 0 Cnt: 2 Name: V0
# VDANAME-PAST-END-GNU-NEXT: 0x001c: Parent 1: <invalid vda_name: 7>

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Sections:
- Name: .gnu.version_d
Type: SHT_GNU_verdef
Flags: [ SHF_ALLOC ]
Link: .dynstr
Info: 0x1
## The byte offset to the auxiliary entry is 0x13, i.e. it is not correctly aligned in memory.
Content: "010000000000020000000000140000000000000004000000080000000700000000000000"
DynamicSymbols:
- Name: V1
Binding: STB_GLOBAL
- Name: V0
Binding: STB_GLOBAL
54 changes: 19 additions & 35 deletions llvm/tools/llvm-objdump/ELFDump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,38 +378,6 @@ void ELFDumper<ELFT>::printSymbolVersionDependency(
}
}

template <class ELFT>
static void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr,
ArrayRef<uint8_t> Contents,
StringRef StrTab) {
outs() << "\nVersion definitions:\n";

const uint8_t *Buf = Contents.data();
uint32_t VerdefIndex = 1;
// sh_info contains the number of entries in the SHT_GNU_verdef section. To
// make the index column have consistent width, we should insert blank spaces
// according to sh_info.
uint16_t VerdefIndexWidth = std::to_string(Shdr.sh_info).size();
while (Buf) {
auto *Verdef = reinterpret_cast<const typename ELFT::Verdef *>(Buf);
outs() << format_decimal(VerdefIndex++, VerdefIndexWidth) << " "
<< format("0x%02" PRIx16 " ", (uint16_t)Verdef->vd_flags)
<< format("0x%08" PRIx32 " ", (uint32_t)Verdef->vd_hash);

const uint8_t *BufAux = Buf + Verdef->vd_aux;
uint16_t VerdauxIndex = 0;
while (BufAux) {
auto *Verdaux = reinterpret_cast<const typename ELFT::Verdaux *>(BufAux);
if (VerdauxIndex)
outs() << std::string(VerdefIndexWidth + 17, ' ');
outs() << StringRef(StrTab.drop_front(Verdaux->vda_name).data()) << '\n';
BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr;
++VerdauxIndex;
}
Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr;
}
}

template <class ELFT> void ELFDumper<ELFT>::printSymbolVersion() {
const ELFFile<ELFT> &Elf = getELFFile();
StringRef FileName = Obj.getFileName();
Expand All @@ -426,10 +394,26 @@ template <class ELFT> void ELFDumper<ELFT>::printSymbolVersion() {
unwrapOrError(Elf.getSection(Shdr.sh_link), FileName);
StringRef StrTab = unwrapOrError(Elf.getStringTable(*StrTabSec), FileName);

if (Shdr.sh_type == ELF::SHT_GNU_verneed)
if (Shdr.sh_type == ELF::SHT_GNU_verneed) {
printSymbolVersionDependency(Shdr);
else
printSymbolVersionDefinition<ELFT>(Shdr, Contents, StrTab);
} else {
OS << "\nVersion definitions:\n";
Expected<std::vector<VerDef>> V =
getELFFile().getVersionDefinitions(Shdr);
if (!V) {
this->reportUniqueWarning(V.takeError());
continue;
}
for (const VerDef &Def : *V) {
OS << Def.Ndx << ' ' << format_hex(Def.Flags, 4) << ' '
<< format_hex(Def.Hash, 10) << ' ' << Def.Name << '\n';
if (!Def.AuxV.empty()) {
for (auto [I, Aux] : enumerate(Def.AuxV))
OS << (I ? ' ' : '\t') << Aux.Name;
OS << '\n';
}
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion llvm/tools/llvm-objdump/llvm-objdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ static StringRef ToolName;

std::unique_ptr<BuildIDFetcher> BIDFetcher;

Dumper::Dumper(const object::ObjectFile &O) : O(O) {
Dumper::Dumper(const object::ObjectFile &O) : O(O), OS(outs()) {
WarningHandler = [this](const Twine &Msg) {
if (Warnings.insert(Msg.str()).second)
reportWarning(Msg, this->O.getFileName());
Expand Down
1 change: 1 addition & 0 deletions llvm/tools/llvm-objdump/llvm-objdump.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class Dumper {
StringSet<> Warnings;

protected:
llvm::raw_ostream &OS;
std::function<Error(const Twine &Msg)> WarningHandler;

public:
Expand Down
2 changes: 1 addition & 1 deletion llvm/tools/llvm-readobj/ELFDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7668,7 +7668,7 @@ void LLVMELFDumper<ELFT>::printVersionDefinitionSection(const Elf_Shdr *Sec) {
W.printFlags("Flags", D.Flags, ArrayRef(SymVersionFlags));
W.printNumber("Index", D.Ndx);
W.printNumber("Hash", D.Hash);
W.printString("Name", D.Name.c_str());
W.printString("Name", D.Name);
W.printList(
"Predecessors", D.AuxV,
[](raw_ostream &OS, const VerdAux &Aux) { OS << Aux.Name.c_str(); });
Expand Down
Loading