Index: llvm/trunk/test/tools/llvm-readobj/elf-hidden-versym.test =================================================================== --- llvm/trunk/test/tools/llvm-readobj/elf-hidden-versym.test +++ llvm/trunk/test/tools/llvm-readobj/elf-hidden-versym.test @@ -0,0 +1,42 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readelf -V %t | FileCheck %s --check-prefix=HIDDEN + +# HIDDEN: Version symbols section '.gnu.version' contains 2 entries: +# HIDDEN-NEXT: Addr: 0000000000200210 Offset: 0x000240 Link: 6 (.dynsym) +# HIDDEN-NEXT: 000: 0 (*local*) 3h(hiddensym) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x0000000000201000 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Flags: [ SHF_ALLOC ] + Address: 0x0000000000200210 + Link: .dynsym + AddressAlign: 0x0000000000000002 + EntSize: 0x0000000000000002 + Entries: [ 0, 0x8003 ] + - Name: .gnu.version_r + Type: SHT_GNU_verneed + Flags: [ SHF_ALLOC ] + Address: 0x0000000000200250 + Link: .dynstr + AddressAlign: 0x0000000000000004 + Info: 0x0000000000000001 + Dependencies: + - Version: 1 + File: somefile + Entries: + - Name: hiddensym + Hash: 1234 + Flags: 0 + Other: 3 +DynamicSymbols: + Global: + - Name: h +... Index: llvm/trunk/test/tools/llvm-readobj/elf-invalid-versioning.test =================================================================== --- llvm/trunk/test/tools/llvm-readobj/elf-invalid-versioning.test +++ llvm/trunk/test/tools/llvm-readobj/elf-invalid-versioning.test @@ -0,0 +1,42 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readelf -V %t | FileCheck %s --check-prefix=INVALID + +# INVALID: Version symbols section '.gnu.version' contains 2 entries: +# INVALID-NEXT: Addr: 0000000000200210 Offset: 0x000240 Link: 6 (.dynsym) +# INVALID-NEXT: 000: 0 (*local*) 3 (*invalid*) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x0000000000201000 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Flags: [ SHF_ALLOC ] + Address: 0x0000000000200210 + Link: .dynsym + AddressAlign: 0x0000000000000002 + EntSize: 0x0000000000000002 + Entries: [ 0, 3 ] + - Name: .gnu.version_r + Type: SHT_GNU_verneed + Flags: [ SHF_ALLOC ] + Address: 0x0000000000200250 + Link: .dynstr + AddressAlign: 0x0000000000000004 + Info: 0x0000000000000001 + Dependencies: + - Version: 1 + File: somefile + Entries: + - Name: '' # invalid name + Hash: 1937 + Flags: 233 + Other: 3 +DynamicSymbols: + Global: + - Name: f +... Index: llvm/trunk/test/tools/llvm-readobj/elf-versioninfo.test =================================================================== --- llvm/trunk/test/tools/llvm-readobj/elf-versioninfo.test +++ llvm/trunk/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 Index: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp =================================================================== --- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp +++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp @@ -3355,7 +3355,57 @@ return; StringRef SecName = unwrapOrError(Obj->getSectionName(Sec)); - OS << "Dumper for " << SecName << " is not implemented\n"; + uint64_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 (uint64_t VersymRow = 0; VersymRow < Entries; VersymRow += 4) { + OS << " " << format_hex_no_prefix(VersymRow, 3) << ":"; + + for (uint64_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