From cd36e182d2f408fd2949e809b3d20889a5bfa2e9 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Tue, 7 Jun 2016 11:04:49 +0000 Subject: [PATCH] [llvm-readobj] - Teach llvm-readobj to dump .gnu.version_r sections SHT_GNU_verneed (.gnu.version_r) is a version dependency section. It was the last symbol versioning relative section that was not dumped, now it is. Differential revision: http://reviews.llvm.org/D21024 llvm-svn: 271998 --- .../llvm-readobj/Inputs/verneed.elf-x86-64 | Bin 0 -> 13520 bytes .../tools/llvm-readobj/elf-versioninfo.test | 33 +++++++++++ llvm/tools/llvm-readobj/ELFDumper.cpp | 55 ++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 llvm/test/tools/llvm-readobj/Inputs/verneed.elf-x86-64 diff --git a/llvm/test/tools/llvm-readobj/Inputs/verneed.elf-x86-64 b/llvm/test/tools/llvm-readobj/Inputs/verneed.elf-x86-64 new file mode 100644 index 0000000000000000000000000000000000000000..3a9c8d8df8da38631340f7dd361a3dd9c0efb7c8 GIT binary patch literal 13520 zcmeHO%}*0i5T7n6enK^V5KUw+B~3Kz0&2WyYE*)W8t|qUEK(>5w5GcfImywZAO8e@ z21kw_IT{la@MMf<>-^rE*=`%~!bRgu(l_7p-u`xb*m-Z?+$yzq6*!l0UihG1RZ8`KmRJ?uJ~-$eg0c1t^A0@!Hm2PNucC~ecq#-ie5+5A&8=r ztW){44N z-aEaYu6Whe(&qrT9C-JV!)9TOR%@+Btu{XvCCwFzW!r` zs9pNW7+Q|TLYyi)Cca{3qOc$M1SWF3JuXhr^7K+orE z2F}UvbuJzKfxYa5``9U(Uuz_5D-Li;9L0_$_BjlKy?`n`enQ}_-LdLEjueUY*lG+xSO^Jx4z&PNYLb?u|X zVwh$>2=l|F{TbLmCH|=oy7q0>CBFsB4lKt8`H|C^%ZS2R#~@3W5eVeYK2 z7RpLPNe~qngLM5`XNGME$?{`Kh!NfSPQz=ReAS<^pxCJmJeK@-Vm!$lm34l_Z;ox* h+!716Dfwy622oa*S(jPbEB~51okVmYi}XTo{%@DYknI2f literal 0 HcmV?d00001 diff --git a/llvm/test/tools/llvm-readobj/elf-versioninfo.test b/llvm/test/tools/llvm-readobj/elf-versioninfo.test index e43d373e92fc7..c7c97b94344d2 100644 --- a/llvm/test/tools/llvm-readobj/elf-versioninfo.test +++ b/llvm/test/tools/llvm-readobj/elf-versioninfo.test @@ -82,3 +82,36 @@ CHECK-NEXT: Name: VERSION2 CHECK-NEXT: } CHECK-NEXT: ] CHECK-NEXT: } + +RUN: llvm-readobj -V %p/Inputs/verneed.elf-x86-64 | FileCheck %s --check-prefix=VERNEED + +VERNEED: SHT_GNU_verneed { +VERNEED-NEXT: Dependency { +VERNEED-NEXT: Version: 1 +VERNEED-NEXT: Count: 2 +VERNEED-NEXT: FileName: verneed1.so.0 +VERNEED-NEXT: Entry { +VERNEED-NEXT: Hash: 1938 +VERNEED-NEXT: Flags: 0x0 +VERNEED-NEXT: Index: 3 +VERNEED-NEXT: Name: v2 +VERNEED-NEXT: } +VERNEED-NEXT: Entry { +VERNEED-NEXT: Hash: 1939 +VERNEED-NEXT: Flags: 0x0 +VERNEED-NEXT: Index: 2 +VERNEED-NEXT: Name: v3 +VERNEED-NEXT: } +VERNEED-NEXT: } +VERNEED-NEXT: Dependency { +VERNEED-NEXT: Version: 1 +VERNEED-NEXT: Count: 1 +VERNEED-NEXT: FileName: verneed2.so.0 +VERNEED-NEXT: Entry { +VERNEED-NEXT: Hash: 1937 +VERNEED-NEXT: Flags: 0x0 +VERNEED-NEXT: Index: 4 +VERNEED-NEXT: Name: v1 +VERNEED-NEXT: } +VERNEED-NEXT: } +VERNEED-NEXT: } diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index dfdd029a7f9ee..1f45b7986a69b 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -520,6 +520,11 @@ static void printVersionSymbolSection(ELFDumper *Dumper, const ELFO *Obj, } } +static const EnumEntry SymVersionFlags[] = { + {"Base", "BASE", VER_FLG_BASE}, + {"Weak", "WEAK", VER_FLG_WEAK}, + {"Info", "INFO", VER_FLG_INFO}}; + template static void printVersionDefinitionSection(ELFDumper *Dumper, const ELFO *Obj, @@ -568,12 +573,62 @@ static void printVersionDefinitionSection(ELFDumper *Dumper, } } +template +static void printVersionDependencySection(ELFDumper *Dumper, + const ELFO *Obj, + const typename ELFO::Elf_Shdr *Sec, + ScopedPrinter &W) { + typedef typename ELFO::Elf_Verneed VerNeed; + typedef typename ELFO::Elf_Vernaux VernAux; + + DictScope SD(W, "SHT_GNU_verneed"); + if (!Sec) + return; + + unsigned VerNeedNum = 0; + for (const typename ELFO::Elf_Dyn &Dyn : Dumper->dynamic_table()) + if (Dyn.d_tag == DT_VERNEEDNUM) + VerNeedNum = Dyn.d_un.d_val; + + const uint8_t *SecData = (const uint8_t *)Obj->base() + Sec->sh_offset; + const typename ELFO::Elf_Shdr *StrTab = + unwrapOrError(Obj->getSection(Sec->sh_link)); + + const uint8_t *P = SecData; + for (unsigned I = 0; I < VerNeedNum; ++I) { + const VerNeed *Need = reinterpret_cast(P); + DictScope Entry(W, "Dependency"); + W.printNumber("Version", Need->vn_version); + W.printNumber("Count", Need->vn_cnt); + W.printString("FileName", + StringRef((const char *)(Obj->base() + StrTab->sh_offset + + Need->vn_file))); + + const uint8_t *PAux = P + Need->vn_aux; + for (unsigned J = 0; J < Need->vn_cnt; ++J) { + const VernAux *Aux = reinterpret_cast(PAux); + DictScope Entry(W, "Entry"); + W.printNumber("Hash", Aux->vna_hash); + W.printEnum("Flags", Aux->vna_flags, makeArrayRef(SymVersionFlags)); + W.printNumber("Index", Aux->vna_other); + W.printString("Name", + StringRef((const char *)(Obj->base() + StrTab->sh_offset + + Aux->vna_name))); + PAux += Aux->vna_next; + } + P += Need->vn_next; + } +} + template void ELFDumper::printVersionInfo() { // Dump version symbol section. printVersionSymbolSection(this, Obj, dot_gnu_version_sec, W); // Dump version definition section. printVersionDefinitionSection(this, Obj, dot_gnu_version_d_sec, W); + + // Dump version dependency section. + printVersionDependencySection(this, Obj, dot_gnu_version_r_sec, W); } template