[llvm] [llvm-objdump] Rework .gnu.version_d dumping (PR #128434)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 28 09:28:51 PST 2025
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/128434
>From 559f653a3b3a27496c5e683520fffe1caeabfc49 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 23 Feb 2025 12:57:29 -0800
Subject: [PATCH 1/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
=?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.5-bogner
---
llvm/include/llvm/Object/ELF.h | 12 ++---
.../llvm-objdump/ELF/private-headers.test | 1 +
.../llvm-objdump/ELF/verdef-invalid.test | 50 +++++++++++++++++
llvm/test/tools/llvm-objdump/ELF/verdef.test | 28 ++++++----
llvm/tools/llvm-objdump/ELFDump.cpp | 54 +++++++------------
llvm/tools/llvm-objdump/llvm-objdump.cpp | 2 +-
llvm/tools/llvm-objdump/llvm-objdump.h | 1 +
llvm/tools/llvm-readobj/ELFDumper.cpp | 2 +-
8 files changed, 98 insertions(+), 52 deletions(-)
create mode 100644 llvm/test/tools/llvm-objdump/ELF/verdef-invalid.test
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 3aa1d7864fcb7..57a6db6c4e5aa 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -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;
@@ -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;
diff --git a/llvm/test/tools/llvm-objdump/ELF/private-headers.test b/llvm/test/tools/llvm-objdump/ELF/private-headers.test
index eefdc8440385c..15a721895525b 100644
--- a/llvm/test/tools/llvm-objdump/ELF/private-headers.test
+++ b/llvm/test/tools/llvm-objdump/ELF/private-headers.test
@@ -37,6 +37,7 @@ Sections:
Value: 0x0
- Name: .gnu.version_d
Type: SHT_GNU_verdef
+ AddressAlign: 4
Entries:
- Version: 1
Flags: 1
diff --git a/llvm/test/tools/llvm-objdump/ELF/verdef-invalid.test b/llvm/test/tools/llvm-objdump/ELF/verdef-invalid.test
new file mode 100644
index 0000000000000..8d0199244752a
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/ELF/verdef-invalid.test
@@ -0,0 +1,50 @@
+## 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 %t5
+# RUN: llvm-objdump -p %t5 2>&1 | FileCheck %s --check-prefix=AUX-PAST-END -DFILE=%t5
+# RUN: llvm-objdump -p %t5 2>&1 | FileCheck %s --check-prefix=AUX-PAST-END -DFILE=%t5
+
+# 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
+ ShSize: 21
+DynamicSymbols:
+ - Name: foo
+
+## Check we report a warning when a version definition is not correctly aligned in memory.
+
+# RUN: yaml2obj %s --docnum=2 -o %t7
+# RUN: llvm-objdump -p %t7 2>&1 | FileCheck %s --check-prefix=MISALIGNED-DEF -DFILE=%t7
+# RUN: llvm-objdump -p %t7 2>&1 | FileCheck %s --check-prefix=MISALIGNED-DEF -DFILE=%t7
+
+# 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
diff --git a/llvm/test/tools/llvm-objdump/ELF/verdef.test b/llvm/test/tools/llvm-objdump/ELF/verdef.test
index e4ae33853deb4..dbb10bf87cbea 100644
--- a/llvm/test/tools/llvm-objdump/ELF/verdef.test
+++ b/llvm/test/tools/llvm-objdump/ELF/verdef.test
@@ -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:
@@ -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
diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp
index e9e5b059f1786..0c9b1f3479f83 100644
--- a/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -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();
@@ -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';
+ }
+ }
+ }
}
}
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 99e0440dce78d..115f04a4df778 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -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());
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h
index 7253cc3f4d91b..25d9c1e106a6c 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -77,6 +77,7 @@ class Dumper {
StringSet<> Warnings;
protected:
+ llvm::raw_ostream &OS;
std::function<Error(const Twine &Msg)> WarningHandler;
public:
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index fdae09ac767e6..e7825419ef9ec 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -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(); });
>From 6a9c55f4b7ec0b9e2f71df968abbf6f5c41fd018 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Tue, 25 Feb 2025 09:57:13 -0800
Subject: [PATCH 2/3] add "## The correct sh_size is 28."
Created using spr 1.3.5-bogner
---
llvm/test/tools/llvm-objdump/ELF/verdef-invalid.test | 3 ++-
llvm/test/tools/llvm-readobj/ELF/verdef-invalid.test | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/llvm/test/tools/llvm-objdump/ELF/verdef-invalid.test b/llvm/test/tools/llvm-objdump/ELF/verdef-invalid.test
index c3845b8483450..45f2331eadc34 100644
--- a/llvm/test/tools/llvm-objdump/ELF/verdef-invalid.test
+++ b/llvm/test/tools/llvm-objdump/ELF/verdef-invalid.test
@@ -18,7 +18,8 @@ Sections:
Entries:
- Names:
- FOO
- ShSize: 21
+ ## The correct sh_size is 28.
+ ShSize: 27
DynamicSymbols:
- Name: foo
diff --git a/llvm/test/tools/llvm-readobj/ELF/verdef-invalid.test b/llvm/test/tools/llvm-readobj/ELF/verdef-invalid.test
index ca1189b067199..e768e13f4a1ec 100644
--- a/llvm/test/tools/llvm-readobj/ELF/verdef-invalid.test
+++ b/llvm/test/tools/llvm-readobj/ELF/verdef-invalid.test
@@ -128,7 +128,8 @@ Sections:
Entries:
- Names:
- FOO
- ShSize: 21
+ ## The correct sh_size is 28.
+ ShSize: 27
DynamicSymbols:
- Name: foo
>From fb9fcf6786ae0b8c5df3b91cd18ac41d8c60a7ea Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Fri, 28 Feb 2025 09:28:42 -0800
Subject: [PATCH 3/3] drop unintended
llvm/test/tools/obj2yaml/ELF/verdef-section.yaml change
Created using spr 1.3.5-bogner
---
.../tools/obj2yaml/ELF/verdef-section.yaml | 40 ++++++++++++++++++-
1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/llvm/test/tools/obj2yaml/ELF/verdef-section.yaml b/llvm/test/tools/obj2yaml/ELF/verdef-section.yaml
index a77d22d6bf5e2..f082e897a6636 100644
--- a/llvm/test/tools/obj2yaml/ELF/verdef-section.yaml
+++ b/llvm/test/tools/obj2yaml/ELF/verdef-section.yaml
@@ -48,8 +48,44 @@ Sections:
Flags: 0
VersionNdx: 0
Hash: 0
+ VDAux: 20
Names:
- - V0
- - V1
+ - VERSION_0
+## An entry with arbitrary values.
+ - Flags: 2
+ VersionNdx: 2
+ Hash: 108387921
+ VDAux: [[VDAUX=20]]
+ Names:
+ - VERSION_1
+## Another entry with arbitrary values and version predecessors.
+ - Flags: 3
+ VersionNdx: 3
+ Hash: 108387922
+ Names:
+ - VERSION_2
+ - VERSION_3
+ - VERSION_4
## Needed to emit the .dynstr section.
DynamicSymbols: []
+
+## Check we dump the `Info` field when its value is not equal
+## to the number of version definitions.
+
+# RUN: yaml2obj %s -DINFO=0x4 -o %t.info
+# RUN: obj2yaml %t.info | FileCheck %s --check-prefixes=CHECK,INFO
+
+## Document that we are not able to dump a version definition which
+## has a version revision (vd_version) that is not equal to 1.
+
+# RUN: yaml2obj %s -DVERSION=2 -o %t.version
+# RUN: not obj2yaml %t.version 2>&1 | \
+# RUN: FileCheck %s -DFILE=%t.version --check-prefix=VERSION-ERR
+
+# VERSION-ERR: Error reading file: [[FILE]]: invalid SHT_GNU_verdef section version: 2
+
+# RUN: yaml2obj %s -DVDAUX=100 -o %t.vdaux
+# RUN: not obj2yaml %t.vdaux 2>&1 | \
+# RUN: FileCheck %s -DFILE=%t.vdaux --check-prefix=VDAUX-ERR
+
+# VDAUX-ERR: Error reading file: [[FILE]]: corrupted section: vd_aux value 100 in section verdef points past end of the section
More information about the llvm-commits
mailing list