--- /dev/null
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objdump -p %t | FileCheck --strict-whitespace %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
+...
}
}
+template <class ELFT>
+void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr,
+ ArrayRef<uint8_t> Contents,
+ StringRef StrTab) {
+ typedef ELFFile<ELFT> 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 in the SHT_GNU_verdef section. To
+ // make the index column have consistent width, we should insert blank spaces
+ // according to sh_info.
+ uint16_t VerdefIndexWidth = std::to_string(Shdr.sh_info).size();
+ while (Buf) {
+ const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(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<const Elf_Verdaux *>(BufAux);
+ if (VerdauxIndex)
+ outs() << std::string(VerdefIndexWidth + 17, ' ');
+ 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 <class ELFT>
void printSymbolVersionInfo(const ELFFile<ELFT> *Elf, StringRef FileName) {
typedef typename ELFT::Shdr Elf_Shdr;
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);
if (!StrTabOrError)
report_error(FileName, StrTabOrError.takeError());
- printSymbolVersionDependency<ELFT>(*ContentsOrError, *StrTabOrError);
- // TODO: Implement symbol version definitions dumper.
+ if (Shdr.sh_type == ELF::SHT_GNU_verneed)
+ printSymbolVersionDependency<ELFT>(*ContentsOrError, *StrTabOrError);
+ else
+ printSymbolVersionDefinition<ELFT>(Shdr, *ContentsOrError,
+ *StrTabOrError);
}
}