diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h --- a/llvm/include/llvm/Object/ELF.h +++ b/llvm/include/llvm/Object/ELF.h @@ -1038,7 +1038,7 @@ VN.Offset = VerneedBuf - Start; if (Verneed->vn_file < StrTab.size()) - VN.File = std::string(StrTab.drop_front(Verneed->vn_file)); + VN.File = std::string(StrTab.data() + Verneed->vn_file); else VN.File = ("vn_file) + ">").str(); diff --git a/llvm/test/tools/llvm-objdump/ELF/verneed-invalid.test b/llvm/test/tools/llvm-objdump/ELF/verneed-invalid.test --- a/llvm/test/tools/llvm-objdump/ELF/verneed-invalid.test +++ b/llvm/test/tools/llvm-objdump/ELF/verneed-invalid.test @@ -2,8 +2,8 @@ # RUN: llvm-objdump -p %t 2>&1 | FileCheck %s --check-prefix=BROKEN-AUX -DFILE=%t # BROKEN-AUX: Version References: -# BROKEN-AUX-NEXT: required from : -# BROKEN-AUX-NEXT: 0x00000000 0x00 00 +# BROKEN-AUX-NEXT: warning: '[[FILE]]': invalid SHT_GNU_verneed section with index 2: found a misaligned auxiliary entry at offset 0x11 +# BROKEN-AUX-NOT: {{.}} --- !ELF FileHeader: diff --git a/llvm/test/tools/llvm-objdump/ELF/verneed.test b/llvm/test/tools/llvm-objdump/ELF/verneed.test --- a/llvm/test/tools/llvm-objdump/ELF/verneed.test +++ b/llvm/test/tools/llvm-objdump/ELF/verneed.test @@ -46,3 +46,23 @@ DynamicSymbols: - Name: f1 Binding: STB_GLOBAL + +# RUN: yaml2obj --docnum=2 %s -o %t.empty +# RUN: llvm-objdump -p %t.empty 2>&1 | FileCheck %s --check-prefix=EMPTY --implicit-check-not=warning: + +# EMPTY: Version References: +# EMPTY-NOT: {{.}} + +--- !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 ] +DynamicSymbols: + - Name: f1 + Binding: STB_GLOBAL diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -282,27 +282,28 @@ } template -static void printSymbolVersionDependency(ArrayRef Contents, - StringRef StrTab) { +static void printSymbolVersionDependency(StringRef FileName, + const ELFFile &Obj, + const typename ELFT::Shdr &Sec) { outs() << "\nVersion References:\n"; - const uint8_t *Buf = Contents.data(); - while (Buf) { - auto *Verneed = reinterpret_cast(Buf); - outs() << " required from " - << StringRef(StrTab.drop_front(Verneed->vn_file).data()) << ":\n"; + auto WarningHandler = [&](const Twine &Msg) { + reportWarning(Msg, FileName); + return Error::success(); + }; + Expected> V = + Obj.getVersionDependencies(Sec, WarningHandler); + if (!V) { + reportWarning(toString(V.takeError()), FileName); + return; + } - const uint8_t *BufAux = Buf + Verneed->vn_aux; - while (BufAux) { - auto *Vernaux = reinterpret_cast(BufAux); - outs() << " " - << format("0x%08" PRIx32 " ", (uint32_t)Vernaux->vna_hash) - << format("0x%02" PRIx16 " ", (uint16_t)Vernaux->vna_flags) - << format("%02" PRIu16 " ", (uint16_t)Vernaux->vna_other) - << StringRef(StrTab.drop_front(Vernaux->vna_name).data()) << '\n'; - BufAux = Vernaux->vna_next ? BufAux + Vernaux->vna_next : nullptr; - } - Buf = Verneed->vn_next ? Buf + Verneed->vn_next : nullptr; + raw_fd_ostream &OS = outs(); + for (const VerNeed &VN : *V) { + OS << " required from " << VN.File << ":\n"; + for (const VernAux &Aux : VN.AuxV) + OS << format(" 0x%08x 0x%02x %02u %s\n", Aux.Hash, Aux.Flags, + Aux.Other, Aux.Name.c_str()); } } @@ -355,7 +356,7 @@ StringRef StrTab = unwrapOrError(Elf.getStringTable(*StrTabSec), FileName); if (Shdr.sh_type == ELF::SHT_GNU_verneed) - printSymbolVersionDependency(Contents, StrTab); + printSymbolVersionDependency(FileName, Elf, Shdr); else printSymbolVersionDefinition(Shdr, Contents, StrTab); }