diff --git a/llvm/test/tools/llvm-readobj/elf-versioninfo.test b/llvm/test/tools/llvm-readobj/elf-versioninfo.test --- a/llvm/test/tools/llvm-readobj/elf-versioninfo.test +++ b/llvm/test/tools/llvm-readobj/elf-versioninfo.test @@ -77,7 +77,11 @@ GNU-VERDEF: 0x000000006ffffffc VERDEF 0x25c GNU-VERDEF: 0x000000006ffffffd VERDEFNUM 3 -GNU-VERDEF: Dumper for .gnu.version is not implemented +GNU-VERDEF: Version symbols section '.gnu.version' contains 8 entries: +GNU-VERDEF-NEXT: Addr: 000000000000024c Offset: 0x00024c Link: 1 (.dynsym) +GNU-VERDEF-NEXT: 000: 0 (*local*) 1 (*global*) 1 (*global*) 3 (VERSION2) +GNU-VERDEF-NEXT: 004: 1 (*global*) 2 (VERSION1) 2 (VERSION1) 3 (VERSION2) + GNU-VERDEF: Dumper for .gnu.version_d is not implemented RUN: llvm-readobj -V %p/Inputs/verneed.elf-x86-64 | FileCheck %s --check-prefix=LLVM-VERNEED @@ -114,6 +118,9 @@ LLVM-VERNEED-NEXT: } LLVM-VERNEED-NEXT: } -GNU-VERNEED: Dumper for .gnu.version is not implemented +GNU-VERNEED: Version symbols section '.gnu.version' contains 4 entries: +GNU-VERNEED-NEXT: Addr: 0000000000010228 Offset: 0x000228 Link: 1 (.dynsym) +GNU-VERNEED-NEXT: 000: 0 (*local*) 2 (v3) 3 (v2) 4 (v1) + GNU-VERNEED: Dumper for .gnu.version_r is not implemented diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -3367,7 +3367,56 @@ return; StringRef SecName = unwrapOrError(Obj->getSectionName(Sec)); - OS << "Dumper for " << SecName << " is not implemented\n"; + uint32_t Entries = Sec->sh_size / sizeof(Elf_Versym); + OS << "Version symbols section '" << SecName << "' " + << "contains " << Entries << " entries:\n"; + + const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec->sh_link)); + StringRef SymTabName = unwrapOrError(Obj->getSectionName(SymTab)); + OS << " Addr: " << format_hex_no_prefix(Sec->sh_addr, 16) + << " Offset: " << format_hex(Sec->sh_offset, 8) + << " Link: " << Sec->sh_link << " (" << SymTabName << ")\n"; + + const uint8_t *VersymBuf = + reinterpret_cast(Obj->base() + Sec->sh_offset); + const ELFDumper *Dumper = this->dumper(); + StringRef StrTable = Dumper->getDynamicStringTable(); + + // readelf prints 4 entries per line. + for (uint32_t VersymRow = 0; VersymRow < Entries; VersymRow += 4) { + OS << " " << format_hex_no_prefix(VersymRow, 3) << ":"; + + for (uint32_t VersymIndex = 0; + (VersymIndex < 4) && (VersymIndex + VersymRow) < Entries; + ++VersymIndex) { + const Elf_Versym *Versym = + reinterpret_cast(VersymBuf); + switch (Versym->vs_index) { + case 0: + OS << " 0 (*local*) "; + break; + case 1: + OS << " 1 (*global*) "; + break; + default: + OS << format("%4x%c", Versym->vs_index & VERSYM_VERSION, + Versym->vs_index & VERSYM_HIDDEN ? 'h' : ' '); + + bool IsDefault = true; + std::string VersionName = Dumper->getSymbolVersionByIndex( + StrTable, Versym->vs_index, IsDefault); + + if (!VersionName.empty()) + VersionName = "(" + VersionName + ")"; + else + VersionName = "(*invalid*)"; + OS << left_justify(VersionName, 13); + } + VersymBuf += sizeof(Elf_Versym); + } + OS << '\n'; + } + OS << '\n'; } template