Skip to content

Commit 29d395a

Browse files
MaskRaytru
authored andcommitted
[llvm-objdump] Change printSymbolVersionDependency to use ELFFile API
When .gnu.version_r is empty (allowed by readelf but warned by objdump), llvm-objdump -p may decode the next section as .gnu.version_r and may crash due to out-of-bounds C string reference. ELFFile<ELFT>::getVersionDependencies handles 0-entry .gnu.version_r gracefully. Just use it. Fix #57707 Differential Revision: https://reviews.llvm.org/D133751 (cherry picked from commit 25394c9)
1 parent 4936d7c commit 29d395a

File tree

4 files changed

+43
-22
lines changed

4 files changed

+43
-22
lines changed

llvm/include/llvm/Object/ELF.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1028,7 +1028,7 @@ ELFFile<ELFT>::getVersionDependencies(const Elf_Shdr &Sec,
10281028
VN.Offset = VerneedBuf - Start;
10291029

10301030
if (Verneed->vn_file < StrTab.size())
1031-
VN.File = std::string(StrTab.drop_front(Verneed->vn_file));
1031+
VN.File = std::string(StrTab.data() + Verneed->vn_file);
10321032
else
10331033
VN.File = ("<corrupt vn_file: " + Twine(Verneed->vn_file) + ">").str();
10341034

llvm/test/tools/llvm-objdump/ELF/verneed-invalid.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
# RUN: llvm-objdump -p %t 2>&1 | FileCheck %s --check-prefix=BROKEN-AUX -DFILE=%t
33

44
# BROKEN-AUX: Version References:
5-
# BROKEN-AUX-NEXT: required from :
6-
# BROKEN-AUX-NEXT: 0x00000000 0x00 00
5+
# BROKEN-AUX-NEXT: warning: '[[FILE]]': invalid SHT_GNU_verneed section with index 2: found a misaligned auxiliary entry at offset 0x11
6+
# BROKEN-AUX-NOT: {{.}}
77

88
--- !ELF
99
FileHeader:

llvm/test/tools/llvm-objdump/ELF/verneed.test

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,23 @@ Sections:
4646
DynamicSymbols:
4747
- Name: f1
4848
Binding: STB_GLOBAL
49+
50+
# RUN: yaml2obj --docnum=2 %s -o %t.empty
51+
# RUN: llvm-objdump -p %t.empty 2>&1 | FileCheck %s --check-prefix=EMPTY --implicit-check-not=warning:
52+
53+
# EMPTY: Version References:
54+
# EMPTY-NOT: {{.}}
55+
56+
--- !ELF
57+
FileHeader:
58+
Class: ELFCLASS64
59+
Data: ELFDATA2LSB
60+
Type: ET_EXEC
61+
Machine: EM_X86_64
62+
Sections:
63+
- Name: .gnu.version_r
64+
Type: SHT_GNU_verneed
65+
Flags: [ SHF_ALLOC ]
66+
DynamicSymbols:
67+
- Name: f1
68+
Binding: STB_GLOBAL

llvm/tools/llvm-objdump/ELFDump.cpp

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -282,27 +282,28 @@ static void printProgramHeaders(const ELFFile<ELFT> &Obj, StringRef FileName) {
282282
}
283283

284284
template <class ELFT>
285-
static void printSymbolVersionDependency(ArrayRef<uint8_t> Contents,
286-
StringRef StrTab) {
285+
static void printSymbolVersionDependency(StringRef FileName,
286+
const ELFFile<ELFT> &Obj,
287+
const typename ELFT::Shdr &Sec) {
287288
outs() << "\nVersion References:\n";
288289

289-
const uint8_t *Buf = Contents.data();
290-
while (Buf) {
291-
auto *Verneed = reinterpret_cast<const typename ELFT::Verneed *>(Buf);
292-
outs() << " required from "
293-
<< StringRef(StrTab.drop_front(Verneed->vn_file).data()) << ":\n";
290+
auto WarningHandler = [&](const Twine &Msg) {
291+
reportWarning(Msg, FileName);
292+
return Error::success();
293+
};
294+
Expected<std::vector<VerNeed>> V =
295+
Obj.getVersionDependencies(Sec, WarningHandler);
296+
if (!V) {
297+
reportWarning(toString(V.takeError()), FileName);
298+
return;
299+
}
294300

295-
const uint8_t *BufAux = Buf + Verneed->vn_aux;
296-
while (BufAux) {
297-
auto *Vernaux = reinterpret_cast<const typename ELFT::Vernaux *>(BufAux);
298-
outs() << " "
299-
<< format("0x%08" PRIx32 " ", (uint32_t)Vernaux->vna_hash)
300-
<< format("0x%02" PRIx16 " ", (uint16_t)Vernaux->vna_flags)
301-
<< format("%02" PRIu16 " ", (uint16_t)Vernaux->vna_other)
302-
<< StringRef(StrTab.drop_front(Vernaux->vna_name).data()) << '\n';
303-
BufAux = Vernaux->vna_next ? BufAux + Vernaux->vna_next : nullptr;
304-
}
305-
Buf = Verneed->vn_next ? Buf + Verneed->vn_next : nullptr;
301+
raw_fd_ostream &OS = outs();
302+
for (const VerNeed &VN : *V) {
303+
OS << " required from " << VN.File << ":\n";
304+
for (const VernAux &Aux : VN.AuxV)
305+
OS << format(" 0x%08x 0x%02x %02u %s\n", Aux.Hash, Aux.Flags,
306+
Aux.Other, Aux.Name.c_str());
306307
}
307308
}
308309

@@ -355,7 +356,7 @@ static void printSymbolVersionInfo(const ELFFile<ELFT> &Elf,
355356
StringRef StrTab = unwrapOrError(Elf.getStringTable(*StrTabSec), FileName);
356357

357358
if (Shdr.sh_type == ELF::SHT_GNU_verneed)
358-
printSymbolVersionDependency<ELFT>(Contents, StrTab);
359+
printSymbolVersionDependency<ELFT>(FileName, Elf, Shdr);
359360
else
360361
printSymbolVersionDefinition<ELFT>(Shdr, Contents, StrTab);
361362
}

0 commit comments

Comments
 (0)