Index: test/tools/llvm-objdump/verdef-elf.test =================================================================== --- /dev/null +++ test/tools/llvm-objdump/verdef-elf.test @@ -0,0 +1,41 @@ +# RUN: yaml2obj %s > %t +# RUN: llvm-objdump -p %t | FileCheck %s + +# CHECK: Version definitions: +# CHECK-NEXT: 1 0x01 0x075bcd15 foo +# CHECK-NEXT: 2 0x02 0x3ade68b1 VERSION_1 +# CHECK-NEXT: VERSION_2 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 + Entry: 0x0000000000001000 +Sections: + - Name: .gnu.version_d + Type: SHT_GNU_verdef + Flags: [ SHF_ALLOC ] + Address: 0x0000000000000230 + Link: .dynstr + AddressAlign: 0x0000000000000004 + Info: 0x0000000000000003 + Entries: + - Version: 1 + Flags: 1 + VersionNdx: 1 + Hash: 123456789 + Names: + - foo + - Version: 1 + Flags: 2 + VersionNdx: 2 + Hash: 987654321 + Names: + - VERSION_1 + - VERSION_2 +DynamicSymbols: + Global: + - Name: bar +... Index: test/tools/llvm-objdump/verdef-many-entries-elf.test =================================================================== --- /dev/null +++ test/tools/llvm-objdump/verdef-many-entries-elf.test @@ -0,0 +1,120 @@ +# RUN: yaml2obj %s > %t +# RUN: llvm-objdump -p %t | FileCheck %s + +# CHECK: Version definitions: +# CHECK-NEXT: 1 0x01 0x075bcd15 VERSION_1 +# CHECK-NEXT: 2 0x02 0x3ade68b1 VERSION_2 +# CHECK-NEXT: VERSION_2_1 +# CHECK-NEXT: 3 0x02 0x05e30a09 VERSION_3 +# CHECK-NEXT: 4 0x02 0x05e15871 VERSION_4 +# CHECK-NEXT: 5 0x02 0x05e30a6d VERSION_5 +# CHECK-NEXT: 6 0x02 0x3afced31 VERSION_6 +# CHECK-NEXT: 7 0x02 0x3b76ff31 VERSION_7 +# CHECK-NEXT: 8 0x02 0x3b76ff31 VERSION_8 +# CHECK-NEXT: 9 0x02 0x3b76ff31 VERSION_9 +# CHECK-NEXT: 10 0x02 0x3b76ff31 VERSION_10 +# CHECK-NEXT: 11 0x02 0x3b76ff31 VERSION_11 +# CHECK-NEXT: VERSION_11_1 +# CHECK-NEXT: 12 0x02 0x3b76ff31 VERSION_12 +# CHECK-NEXT: 13 0x02 0x3b76ff31 VERSION_13 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 + Entry: 0x0000000000001000 +Sections: + - Name: .gnu.version_d + Type: SHT_GNU_verdef + Flags: [ SHF_ALLOC ] + Address: 0x0000000000000230 + Link: .dynstr + AddressAlign: 0x0000000000000004 + Info: 0x0000000000000010 + Entries: + - Version: 1 + Flags: 1 + VersionNdx: 1 + Hash: 123456789 + Names: + - VERSION_1 + - Version: 1 + Flags: 2 + VersionNdx: 2 + Hash: 987654321 + Names: + - VERSION_2 + - VERSION_2_1 + - Version: 1 + Flags: 2 + VersionNdx: 3 + Hash: 98765321 + Names: + - VERSION_3 + - Version: 1 + Flags: 2 + VersionNdx: 4 + Hash: 98654321 + Names: + - VERSION_4 + - Version: 1 + Flags: 2 + VersionNdx: 5 + Hash: 98765421 + Names: + - VERSION_5 + - Version: 1 + Flags: 2 + VersionNdx: 6 + Hash: 989654321 + Names: + - VERSION_6 + - Version: 1 + Flags: 2 + VersionNdx: 7 + Hash: 997654321 + Names: + - VERSION_7 + - Version: 1 + Flags: 2 + VersionNdx: 8 + Hash: 997654321 + Names: + - VERSION_8 + - Version: 1 + Flags: 2 + VersionNdx: 9 + Hash: 997654321 + Names: + - VERSION_9 + - Version: 1 + Flags: 2 + VersionNdx: 10 + Hash: 997654321 + Names: + - VERSION_10 + - Version: 1 + Flags: 2 + VersionNdx: 11 + Hash: 997654321 + Names: + - VERSION_11 + - VERSION_11_1 + - Version: 1 + Flags: 2 + VersionNdx: 12 + Hash: 997654321 + Names: + - VERSION_12 + - Version: 1 + Flags: 2 + VersionNdx: 13 + Hash: 997654321 + Names: + - VERSION_13 +DynamicSymbols: + Global: + - Name: bar +... Index: tools/llvm-objdump/ELFDump.cpp =================================================================== --- tools/llvm-objdump/ELFDump.cpp +++ tools/llvm-objdump/ELFDump.cpp @@ -298,6 +298,45 @@ } template +void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr, + ArrayRef Contents, + StringRef StrTab) { + typedef ELFFile ELFO; + typedef typename ELFO::Elf_Verdef Elf_Verdef; + typedef typename ELFO::Elf_Verdaux Elf_Verdaux; + + outs() << "Version definitions:\n"; + + const uint8_t *Buf = Contents.data(); + uint32_t VerdefIndex = 1; + // sh_info contains the number of entries of verdef section. + // To make the index column have consistent width, we should + // increase the column width when entries is greater than 9. + // We assume the entries of verdef is no greater than 99. + uint16_t VerdefIndexWidth = (Shdr.sh_info > 9) ? 2 : 1; + while (Buf) { + const Elf_Verdef *Verdef = reinterpret_cast(Buf); + outs() << format_decimal(VerdefIndex++, VerdefIndexWidth) << " " + << format("0x%02" PRIx16 " ", (uint16_t)Verdef->vd_flags) + << format("0x%08" PRIx32 " ", (uint32_t)Verdef->vd_hash); + + const uint8_t *BufAux = Buf + Verdef->vd_aux; + uint16_t VerdauxIndex = 0; + while (BufAux) { + const Elf_Verdaux *Verdaux = + reinterpret_cast(BufAux); + if (VerdauxIndex) + outs() << ((Shdr.sh_info > 9) ? " " + : " "); + outs() << StringRef(StrTab.drop_front(Verdaux->vda_name).data()) << '\n'; + BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr; + ++VerdauxIndex; + } + Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr; + } +} + +template void printSymbolVersionInfo(const ELFFile *Elf, StringRef FileName) { typedef typename ELFT::Shdr Elf_Shdr; @@ -306,7 +345,8 @@ report_error(FileName, SectionsOrError.takeError()); for (const Elf_Shdr &Shdr : *SectionsOrError) { - if (Shdr.sh_type != ELF::SHT_GNU_verneed) + if (Shdr.sh_type != ELF::SHT_GNU_verneed && + Shdr.sh_type != ELF::SHT_GNU_verdef) continue; auto ContentsOrError = Elf->getSectionContents(&Shdr); @@ -321,8 +361,11 @@ if (!StrTabOrError) report_error(FileName, StrTabOrError.takeError()); - printSymbolVersionDependency(*ContentsOrError, *StrTabOrError); - // TODO: Implement symbol version definitions dumper. + if (Shdr.sh_type == ELF::SHT_GNU_verneed) + printSymbolVersionDependency(*ContentsOrError, *StrTabOrError); + else + printSymbolVersionDefinition(Shdr, *ContentsOrError, + *StrTabOrError); } }