From c15d5b41a3810afe86d2fbe7eba6746bdeb592d4 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Wed, 22 Jun 2016 13:43:38 +0000 Subject: [PATCH] [llvm-readobj] - Teach llvm-readobj to print dependencies of SHT_GNU_verdef and refactor dumping method. This patch changes single method of llvm-readobj. It teaches SHT_GNU_verdef dumper to print version dependencies, also it removes few fields from output that can be dumped with other keys and slightly refactors code. Testcase was also modified to match the changes. Change is required for testcases of upcoming lld patches. Differential revision: http://reviews.llvm.org/D21552 llvm-svn: 273417 --- test/tools/llvm-readobj/elf-versioninfo.test | 57 ++++++++------------ tools/llvm-readobj/ELFDumper.cpp | 44 ++++++++------- 2 files changed, 49 insertions(+), 52 deletions(-) diff --git a/test/tools/llvm-readobj/elf-versioninfo.test b/test/tools/llvm-readobj/elf-versioninfo.test index c7c97b94344..919120e2caa 100644 --- a/test/tools/llvm-readobj/elf-versioninfo.test +++ b/test/tools/llvm-readobj/elf-versioninfo.test @@ -47,40 +47,29 @@ CHECK-NEXT: } CHECK-NEXT: ] CHECK-NEXT: } -CHECK: Version definition { -CHECK-NEXT: Section Name: .gnu.version_d (70) -CHECK-NEXT: Address: 0x25C -CHECK-NEXT: Offset: 0x25C -CHECK-NEXT: Link: 2 -CHECK-NEXT: Entries [ -CHECK-NEXT: Entry { -CHECK-NEXT: Offset: 0x0 -CHECK-NEXT: Rev: 1 -CHECK-NEXT: Flags: 1 -CHECK-NEXT: Index: 1 -CHECK-NEXT: Cnt: 1 -CHECK-NEXT: Hash: 430712 -CHECK-NEXT: Name: blah -CHECK-NEXT: } -CHECK-NEXT: Entry { -CHECK-NEXT: Offset: 0x1C -CHECK-NEXT: Rev: 1 -CHECK-NEXT: Flags: 0 -CHECK-NEXT: Index: 2 -CHECK-NEXT: Cnt: 1 -CHECK-NEXT: Hash: 175630257 -CHECK-NEXT: Name: VERSION1 -CHECK-NEXT: } -CHECK-NEXT: Entry { -CHECK-NEXT: Offset: 0x38 -CHECK-NEXT: Rev: 1 -CHECK-NEXT: Flags: 0 -CHECK-NEXT: Index: 3 -CHECK-NEXT: Cnt: 2 -CHECK-NEXT: Hash: 175630258 -CHECK-NEXT: Name: VERSION2 -CHECK-NEXT: } -CHECK-NEXT: ] +CHECK: SHT_GNU_verdef { +CHECK-NEXT: Definition { +CHECK-NEXT: Version: 1 +CHECK-NEXT: Flags: Base (0x1) +CHECK-NEXT: Index: 1 +CHECK-NEXT: Hash: 430712 +CHECK-NEXT: Name: blah +CHECK-NEXT: } +CHECK-NEXT: Definition { +CHECK-NEXT: Version: 1 +CHECK-NEXT: Flags: 0x0 +CHECK-NEXT: Index: 2 +CHECK-NEXT: Hash: 175630257 +CHECK-NEXT: Name: VERSION1 +CHECK-NEXT: } +CHECK-NEXT: Definition { +CHECK-NEXT: Version: 1 +CHECK-NEXT: Flags: 0x0 +CHECK-NEXT: Index: 3 +CHECK-NEXT: Hash: 175630258 +CHECK-NEXT: Name: VERSION2 +CHECK-NEXT: Predecessor: VERSION1 +CHECK-NEXT: } CHECK-NEXT: } RUN: llvm-readobj -V %p/Inputs/verneed.elf-x86-64 | FileCheck %s --check-prefix=VERNEED diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 1f45b7986a6..84e368e7aa3 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -530,21 +530,19 @@ static void printVersionDefinitionSection(ELFDumper *Dumper, const ELFO *Obj, const typename ELFO::Elf_Shdr *Sec, ScopedPrinter &W) { - DictScope SD(W, "Version definition"); + typedef typename ELFO::Elf_Verdef VerDef; + typedef typename ELFO::Elf_Verdaux VerdAux; + + DictScope SD(W, "SHT_GNU_verdef"); if (!Sec) return; - StringRef Name = unwrapOrError(Obj->getSectionName(Sec)); - W.printNumber("Section Name", Name, Sec->sh_name); - W.printHex("Address", Sec->sh_addr); - W.printHex("Offset", Sec->sh_offset); - W.printNumber("Link", Sec->sh_link); - unsigned verdef_entries = 0; // The number of entries in the section SHT_GNU_verdef // is determined by DT_VERDEFNUM tag. + unsigned VerDefsNum = 0; for (const typename ELFO::Elf_Dyn &Dyn : Dumper->dynamic_table()) { if (Dyn.d_tag == DT_VERDEFNUM) - verdef_entries = Dyn.d_un.d_val; + VerDefsNum = Dyn.d_un.d_val; } const uint8_t *SecStartAddress = (const uint8_t *)Obj->base() + Sec->sh_offset; @@ -553,22 +551,32 @@ static void printVersionDefinitionSection(ELFDumper *Dumper, const typename ELFO::Elf_Shdr *StrTab = unwrapOrError(Obj->getSection(Sec->sh_link)); - ListScope Entries(W, "Entries"); - for (unsigned i = 0; i < verdef_entries; ++i) { - if (P + sizeof(typename ELFO::Elf_Verdef) > SecEndAddress) + while (VerDefsNum--) { + if (P + sizeof(VerDef) > SecEndAddress) report_fatal_error("invalid offset in the section"); - auto *VD = reinterpret_cast(P); - DictScope Entry(W, "Entry"); - W.printHex("Offset", (uintptr_t)P - (uintptr_t)SecStartAddress); - W.printNumber("Rev", VD->vd_version); - // FIXME: print something more readable. - W.printNumber("Flags", VD->vd_flags); + + auto *VD = reinterpret_cast(P); + DictScope Def(W, "Definition"); + W.printNumber("Version", VD->vd_version); + W.printEnum("Flags", VD->vd_flags, makeArrayRef(SymVersionFlags)); W.printNumber("Index", VD->vd_ndx); - W.printNumber("Cnt", VD->vd_cnt); W.printNumber("Hash", VD->vd_hash); W.printString("Name", StringRef((const char *)(Obj->base() + StrTab->sh_offset + VD->getAux()->vda_name))); + if (!VD->vd_cnt) + report_fatal_error("at least one definition string must exist"); + if (VD->vd_cnt > 2) + report_fatal_error("more than one predecessor is not expected"); + + if (VD->vd_cnt == 2) { + const uint8_t *PAux = P + VD->vd_aux + VD->getAux()->vda_next; + const VerdAux *Aux = reinterpret_cast(PAux); + W.printString("Predecessor", + StringRef((const char *)(Obj->base() + StrTab->sh_offset + + Aux->vda_name))); + } + P += VD->vd_next; } }