diff --git a/llvm/test/Object/invalid.test b/llvm/test/Object/invalid.test --- a/llvm/test/Object/invalid.test +++ b/llvm/test/Object/invalid.test @@ -637,13 +637,13 @@ Symbols: - Name: foo -## Check that we report an error if SHT_GNU_versym has invalid +## Check that we report a warning if SHT_GNU_versym has invalid ## sh_entsize value (3 instead of 2) when trying to access the entries. # RUN: yaml2obj %s --docnum=30 -o %t30 -# RUN: not llvm-readobj -V %t30 2>&1 | FileCheck -DFILE=%t30 --check-prefix=INVALID-VER-SHENTSIZE %s +# RUN: llvm-readobj -V %t30 2>&1 | FileCheck -DFILE=%t30 --check-prefix=INVALID-VER-SHENTSIZE %s -# INVALID-VER-SHENTSIZE: error: '[[FILE]]': section [index 1] has invalid sh_entsize: expected 2, but got 3 +# INVALID-VER-SHENTSIZE: warning: '[[FILE]]': cannot read content of SHT_GNU_versym section with index 1: section [index 1] has an invalid sh_entsize: 3 --- !ELF FileHeader: @@ -657,6 +657,7 @@ Type: SHT_GNU_versym EntSize: 0x0000000000000003 Entries: [ ] + Link: .dynsym ## Needed to trigger creation of .dynsym. DynamicSymbols: - Name: foo diff --git a/llvm/test/Object/multiple-sections.yaml b/llvm/test/Object/multiple-sections.yaml --- a/llvm/test/Object/multiple-sections.yaml +++ b/llvm/test/Object/multiple-sections.yaml @@ -4,6 +4,7 @@ # Test that multiple sections with the same type does not trigger an error. # CHECK: ElfHeader { +# CHECK: VersionSymbols [ # CHECK: VersionDefinitions [ # CHECK: VersionRequirements [ # CHECK: CGProfile [ @@ -23,10 +24,12 @@ EntSize: 24 - Name: .versym Type: SHT_GNU_versym - Entries: [ ] + Entries: [ 0 ] + Link: .dynsym - Name: .versym2 Type: SHT_GNU_versym - Entries: [ ] + Entries: [ 0 ] + Link: .dynsym - Name: .verdef Type: SHT_GNU_verdef Info: 0x0000000000000000 @@ -59,4 +62,5 @@ Content: '' Symbols: - Name: f +DynamicSymbols: [] ... diff --git a/llvm/test/tools/llvm-readobj/all.test b/llvm/test/tools/llvm-readobj/all.test --- a/llvm/test/tools/llvm-readobj/all.test +++ b/llvm/test/tools/llvm-readobj/all.test @@ -53,6 +53,7 @@ - Name: .gnu.version Type: SHT_GNU_versym Entries: [ 0 ] + Link: .dynsym - Name: .gnu.version_d Type: SHT_GNU_verdef Info: 0x0 @@ -111,3 +112,4 @@ Sections: - Section: .note.gnu.build-id Symbols: [] +DynamicSymbols: [] diff --git a/llvm/test/tools/llvm-readobj/elf-verdef-invalid.test b/llvm/test/tools/llvm-readobj/elf-verdef-invalid.test --- a/llvm/test/tools/llvm-readobj/elf-verdef-invalid.test +++ b/llvm/test/tools/llvm-readobj/elf-verdef-invalid.test @@ -275,6 +275,7 @@ # INVALID-VERDEF-LLVM-NEXT: Name: # INVALID-VERDEF-LLVM-NEXT: } # INVALID-VERDEF-LLVM-NEXT: Symbol { +# INVALID-VERDEF-LLVM-NEXT: Version: 2 # INVALID-VERDEF-LLVM-EMPTY: # INVALID-VERDEF-LLVM-NEXT: error: '[[FILE]]': invalid SHT_GNU_verdef section with index 2: version definition 1 goes past the end of the section diff --git a/llvm/test/tools/llvm-readobj/elf-verneed-invalid.test b/llvm/test/tools/llvm-readobj/elf-verneed-invalid.test --- a/llvm/test/tools/llvm-readobj/elf-verneed-invalid.test +++ b/llvm/test/tools/llvm-readobj/elf-verneed-invalid.test @@ -101,9 +101,9 @@ # LLVM-NOLINK-NEXT: Name: # LLVM-NOLINK-NEXT: } # LLVM-NOLINK-NEXT: Symbol { +# LLVM-NOLINK-NEXT: Version: 2 # LLVM-NOLINK-EMPTY: # LLVM-NOLINK-NEXT: warning: '[[FILE]]': invalid string table linked to SHT_GNU_verneed section with index 2: invalid sh_type for string table section [index 0]: expected SHT_STRTAB, but got SHT_NULL -# LLVM-NOLINK-NEXT: Version: 2 # LLVM-NOLINK-NEXT: Name: foo@ # LLVM-NOLINK-NEXT: } # LLVM-NOLINK-NEXT: ] @@ -183,8 +183,7 @@ AddressAlign: 4 ## The byte offset to the auxiliary entry is 0x11, i.e. it is not correctly aligned in memory. Content: "0100010001000000110000000000000000000000" -DynamicSymbols: - - Name: foo +DynamicSymbols: [] ## Here we check that we can properly dump the case when a dependency file name ## and/or a dependency name string offset is equal to the string table size. diff --git a/llvm/test/tools/llvm-readobj/elf-versym-invalid.test b/llvm/test/tools/llvm-readobj/elf-versym-invalid.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/elf-versym-invalid.test @@ -0,0 +1,220 @@ +## Test how llvm-readobj/llvm-readelf tools handle invalid SHT_GNU_versym sections. + +## Check that we report a warning when sh_link references a non-existent section. + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: llvm-readelf -V %t1 2>&1 | FileCheck -DFILE=%t1 %s --check-prefix=GNU-INVALID-LINK +# RUN: llvm-readobj -V %t1 2>&1 | FileCheck -DFILE=%t1 %s --check-prefix=LLVM-INVALID-LINK + +# GNU-INVALID-LINK: Version symbols section '.gnu.version' contains 0 entries: +# GNU-INVALID-LINK-EMPTY: +# GNU-INVALID-LINK-NEXT: warning: '[[FILE]]': invalid section linked to SHT_GNU_versym section with index 1: invalid section index: 255 +# GNU-INVALID-LINK-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 255 () + +# LLVM-INVALID-LINK: VersionSymbols [ +# LLVM-INVALID-LINK-EMPTY: +# LLVM-INVALID-LINK-NEXT: warning: '[[FILE]]': invalid section linked to SHT_GNU_versym section with index 1: invalid section index: 255 +# LLVM-INVALID-LINK-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Link: 0xFF + Entries: [ ] + +## Check that we report a warning when the sh_link field of a SHT_GNU_versym section does not reference +## a dynamic symbol table section. + +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: llvm-readelf -V %t2 2>&1 | FileCheck -DFILE=%t2 %s --check-prefix=INVALID-SYMBOL-TABLE-GNU +# RUN: llvm-readobj -V %t2 2>&1 | FileCheck -DFILE=%t2 %s --check-prefix=INVALID-SYMBOL-TABLE-LLVM + +# INVALID-SYMBOL-TABLE-GNU: Version symbols section '.gnu.version' contains 1 entries: +# INVALID-SYMBOL-TABLE-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 0 () +# INVALID-SYMBOL-TABLE-GNU-EMPTY: +# INVALID-SYMBOL-TABLE-GNU-NEXT: warning: '[[FILE]]': invalid section linked to SHT_GNU_versym section with index 1: expected SHT_DYNSYM, but got SHT_NULL +# INVALID-SYMBOL-TABLE-GNU-NEXT: 000: 0 (*local*) + +# INVALID-SYMBOL-TABLE-LLVM: VersionSymbols [ +# INVALID-SYMBOL-TABLE-LLVM-EMPTY: +# INVALID-SYMBOL-TABLE-LLVM-NEXT: warning: '[[FILE]]': invalid section linked to SHT_GNU_versym section with index 1: expected SHT_DYNSYM, but got SHT_NULL +# INVALID-SYMBOL-TABLE-LLVM-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Link: 0x0 + Entries: [ 0 ] + +## Check we report a warning when something is wrong with a string table linked to a symbol table that +## is linked with SHT_GNU_versym. In this case we are unable to produce LLVM style output, +## but GNU style is fine because it does not need that string table. + +# RUN: yaml2obj --docnum=3 %s -o %t3 +# RUN: llvm-readelf -V %t3 2>&1 | FileCheck -DFILE=%t3 %s --check-prefix=INVALID-STRING-TABLE-GNU +# RUN: llvm-readobj -V %t3 2>&1 | FileCheck -DFILE=%t3 %s --check-prefix=INVALID-STRING-TABLE-LLVM + +# INVALID-STRING-TABLE-GNU: Version symbols section '.gnu.version' contains 1 entries: +# INVALID-STRING-TABLE-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 5 (.dynsym) +# INVALID-STRING-TABLE-GNU-EMPTY: +# INVALID-STRING-TABLE-GNU-NEXT: warning: '[[FILE]]': can't get a string table for the symbol table linked to SHT_GNU_versym section with index 1: invalid string table linked to SHT_DYNSYM section with index 5: invalid sh_type for string table section [index 2]: expected SHT_STRTAB, but got SHT_NULL +# INVALID-STRING-TABLE-GNU-NEXT: 000: 0 (*local*) + +# INVALID-STRING-TABLE-LLVM: VersionSymbols [ +# INVALID-STRING-TABLE-LLVM-EMPTY: +# INVALID-STRING-TABLE-LLVM-NEXT: warning: '[[FILE]]': can't get a string table for the symbol table linked to SHT_GNU_versym section with index 1: invalid string table linked to SHT_DYNSYM section with index 5: invalid sh_type for string table section [index 2]: expected SHT_STRTAB, but got SHT_NULL +# INVALID-STRING-TABLE-LLVM-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Link: .dynsym + Entries: [ 0 ] + - Name: .dynstr + Type: SHT_NULL +DynamicSymbols: [] + +## Check we report a warning when a SHT_GNU_versym section is not correctly aligned in memory. + +# RUN: yaml2obj --docnum=4 %s -o %t4 +# RUN: llvm-readelf -V %t4 2>&1 | FileCheck -DFILE=%t4 %s --check-prefix=MISALIGNED-GNU +# RUN: llvm-readobj -V %t4 2>&1 | FileCheck -DFILE=%t4 %s --check-prefix=MISALIGNED-LLVM + +# MISALIGNED-GNU: Version symbols section '.gnu.version' contains 0 entries: +# MISALIGNED-GNU-NEXT: Addr: 0000000000000000 Offset: 0x00ffff Link: 0 () +# MISALIGNED-GNU-EMPTY: +# MISALIGNED-GNU-NEXT: warning: '[[FILE]]': the SHT_GNU_versym section with index 1 is misaligned + +# MISALIGNED-LLVM: VersionSymbols [ +# MISALIGNED-LLVM-EMPTY: +# MISALIGNED-LLVM-NEXT: warning: '[[FILE]]': the SHT_GNU_versym section with index 1 is misaligned +# MISALIGNED-LLVM-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Entries: [ ] + ShOffset: 0xffff + +## Check we report a warning when a SHT_GNU_versym section has an invalid entry size. + +# RUN: yaml2obj --docnum=5 %s -o %t5 +# RUN: llvm-readelf -V %t5 2>&1 | FileCheck -DFILE=%t5 %s --check-prefix=INVALID-ENT-SIZE-GNU +# RUN: llvm-readobj -V %t5 2>&1 | FileCheck -DFILE=%t5 %s --check-prefix=INVALID-ENT-SIZE-LLVM + +# INVALID-ENT-SIZE-GNU: Version symbols section '.gnu.version' contains 1 entries: +# INVALID-ENT-SIZE-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 0 () +# INVALID-ENT-SIZE-GNU-EMPTY: +# INVALID-ENT-SIZE-GNU-NEXT: warning: '[[FILE]]': cannot read content of SHT_GNU_versym section with index 1: section [index 1] has an invalid sh_entsize: 3 + +# INVALID-ENT-SIZE-LLVM: VersionSymbols [ +# INVALID-ENT-SIZE-LLVM-EMPTY: +# INVALID-ENT-SIZE-LLVM-NEXT: warning: '[[FILE]]': cannot read content of SHT_GNU_versym section with index 1: section [index 1] has an invalid sh_entsize: 3 +# INVALID-ENT-SIZE-LLVM-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Entries: [ 0 ] + EntSize: 3 + +## Check we report a warning when the number of version entries does not match the number of symbols in the associated symbol table. + +# RUN: yaml2obj --docnum=6 %s -o %t6 +# RUN: llvm-readelf -V %t6 2>&1 | FileCheck -DFILE=%t6 %s --check-prefix=SYMBOLS-NUM-MISMATCH-GNU +# RUN: llvm-readobj -V %t6 2>&1 | FileCheck -DFILE=%t6 %s --check-prefix=SYMBOLS-NUM-MISMATCH-LLVM + +# SYMBOLS-NUM-MISMATCH-GNU: Version symbols section '.gnu.version' contains 2 entries: +# SYMBOLS-NUM-MISMATCH-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 4 (.dynsym) +# SYMBOLS-NUM-MISMATCH-GNU-EMPTY: +# SYMBOLS-NUM-MISMATCH-GNU-NEXT: warning: '[[FILE]]': SHT_GNU_versym section with index 1: the number of entries (2) does not match the number of symbols (3) in the symbol table with index 4 +# SYMBOLS-NUM-MISMATCH-GNU-NEXT: 000: 0 (*local*) 1 (*global*) + +# SYMBOLS-NUM-MISMATCH-LLVM: VersionSymbols [ +# SYMBOLS-NUM-MISMATCH-LLVM-EMPTY: +# SYMBOLS-NUM-MISMATCH-LLVM-NEXT: warning: '[[FILE]]': SHT_GNU_versym section with index 1: the number of entries (2) does not match the number of symbols (3) in the symbol table with index 4 +# SYMBOLS-NUM-MISMATCH-LLVM-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Entries: [ 0, 1 ] + Link: .dynsym +DynamicSymbols: + - Name: foo + - Name: bar + +## Check we can dump a SHT_GNU_versym section when it is linked to a custom dynamic symbol +## table that is not called ".dynsym". + +# RUN: yaml2obj --docnum=7 %s -o %t7 +# RUN: llvm-readelf -V %t7 2>&1 | FileCheck -DFILE=%t7 %s --check-prefix=CUSTOM-SYMTAB-GNU +# RUN: llvm-readobj -V %t7 2>&1 | FileCheck -DFILE=%t7 %s --check-prefix=CUSTOM-SYMTAB-LLVM + +# CUSTOM-SYMTAB-GNU: Version symbols section '.gnu.version' contains 1 entries: +# CUSTOM-SYMTAB-GNU-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 2 (.foo.dynsym) +# CUSTOM-SYMTAB-GNU-NEXT: 000: 0 (*local*) + +# CUSTOM-SYMTAB-LLVM: VersionSymbols [ +# CUSTOM-SYMTAB-LLVM-NEXT: Symbol { +# CUSTOM-SYMTAB-LLVM-NEXT: Version: 0 +# CUSTOM-SYMTAB-LLVM-NEXT: Name: +# CUSTOM-SYMTAB-LLVM-NEXT: } +# CUSTOM-SYMTAB-LLVM-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Link: .foo.dynsym + Entries: [ 0 ] +## A custom empty dynamic symbol table with a null entry. + - Name: .foo.dynsym + Type: SHT_DYNSYM + Link: .dynstr + EntSize: 24 + Size: 24 +DynamicSymbols: + - Name: foo + - Name: bar 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 @@ -339,6 +339,9 @@ const Elf_Hash *getHashTable() const { return HashTable; } const Elf_GnuHash *getGnuHashTable() const { return GnuHashTable; } + Expected> getVersionTable(const Elf_Shdr *Sec, + ArrayRef *SymTab, + StringRef *StrTab) const; Expected> getVersionDefinitions(const Elf_Shdr *Sec) const; Expected> @@ -368,6 +371,90 @@ return *StrTabOrErr; } +// Returns the linked symbol table and associated string table for a given section. +template +static Expected> +getLinkAsSymtab(const ELFFile *Obj, const typename ELFT::Shdr *Sec, + unsigned SecNdx, unsigned ExpectedType) { + Expected SymtabOrErr = + Obj->getSection(Sec->sh_link); + if (!SymtabOrErr) + return createError("invalid section linked to " + + object::getELFSectionTypeName( + Obj->getHeader()->e_machine, Sec->sh_type) + + " section with index " + Twine(SecNdx) + ": " + + toString(SymtabOrErr.takeError())); + + if ((*SymtabOrErr)->sh_type != ExpectedType) + return createError( + "invalid section linked to " + + object::getELFSectionTypeName(Obj->getHeader()->e_machine, + Sec->sh_type) + + " section with index " + Twine(SecNdx) + ": expected " + + object::getELFSectionTypeName(Obj->getHeader()->e_machine, + ExpectedType) + + ", but got " + + object::getELFSectionTypeName(Obj->getHeader()->e_machine, + (*SymtabOrErr)->sh_type)); + + Expected StrTabOrErr = + getLinkAsStrtab(Obj, *SymtabOrErr, Sec->sh_link); + if (!StrTabOrErr) + return createError( + "can't get a string table for the symbol table linked to " + + object::getELFSectionTypeName(Obj->getHeader()->e_machine, + Sec->sh_type) + + " section with index " + Twine(SecNdx) + ": " + + toString(StrTabOrErr.takeError())); + + Expected SymsOrErr = Obj->symbols(*SymtabOrErr); + if (!SymsOrErr) + return createError( + "unable to read symbols from the symbol table with index " + + Twine(Sec->sh_link) + ": " + toString(SymsOrErr.takeError())); + + return std::make_pair(*SymsOrErr, *StrTabOrErr); +} + +template +Expected> +ELFDumper::getVersionTable(const Elf_Shdr *Sec, ArrayRef *SymTab, + StringRef *StrTab) const { + assert((!SymTab && !StrTab) || (SymTab && StrTab)); + const ELFFile *Obj = ObjF->getELFFile(); + unsigned SecNdx = Sec - &cantFail(Obj->sections()).front(); + + if (uintptr_t(Obj->base() + Sec->sh_offset) % sizeof(uint16_t) != 0) + return createError("the SHT_GNU_versym section with index " + + Twine(SecNdx) + " is misaligned"); + + Expected> VersionsOrErr = + Obj->template getSectionContentsAsArray(Sec); + if (!VersionsOrErr) + return createError( + "cannot read content of SHT_GNU_versym section with index " + + Twine(SecNdx) + ": " + toString(VersionsOrErr.takeError())); + + Expected, StringRef>> SymTabOrErr = + getLinkAsSymtab(Obj, Sec, SecNdx, SHT_DYNSYM); + if (!SymTabOrErr) { + ELFDumperStyle->reportUniqueWarning(SymTabOrErr.takeError()); + return *VersionsOrErr; + } + + if (SymTabOrErr->first.size() != VersionsOrErr->size()) + ELFDumperStyle->reportUniqueWarning( + createError("SHT_GNU_versym section with index " + Twine(SecNdx) + + ": the number of entries (" + Twine(VersionsOrErr->size()) + + ") does not match the number of symbols (" + + Twine(SymTabOrErr->first.size()) + + ") in the symbol table with index " + Twine(Sec->sh_link))); + + if (SymTab) + std::tie(*SymTab, *StrTab) = *SymTabOrErr; + return *VersionsOrErr; +} + template Expected> ELFDumper::getVersionDefinitions(const Elf_Shdr *Sec) const { @@ -4013,23 +4100,24 @@ if (!Sec) return; - unsigned Entries = Sec->sh_size / sizeof(Elf_Versym); - printGNUVersionSectionProlog(Obj, Sec, "Version symbols", Entries); - - const uint8_t *VersymBuf = - reinterpret_cast(Obj->base() + Sec->sh_offset); - const ELFDumper *Dumper = this->dumper(); + printGNUVersionSectionProlog(Obj, Sec, "Version symbols", + Sec->sh_size / sizeof(Elf_Versym)); + Expected> VerTableOrErr = + this->dumper()->getVersionTable(Sec, /*SymTab=*/nullptr, + /*StrTab=*/nullptr); + if (!VerTableOrErr) { + this->reportUniqueWarning(VerTableOrErr.takeError()); + return; + } // readelf prints 4 entries per line. + uint64_t Entries = VerTableOrErr->size(); 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) { + for (uint64_t I = 0; (I < 4) && (I + VersymRow) < Entries; ++I) { + unsigned Version = (*VerTableOrErr)[VersymRow + I].vs_index; + switch (Version) { case 0: OS << " 0 (*local*) "; break; @@ -4039,18 +4127,17 @@ default: bool IsDefault = true; std::string VersionName = - Dumper->getSymbolVersionByIndex(Versym->vs_index, IsDefault); + this->dumper()->getSymbolVersionByIndex(Version, IsDefault); if (!VersionName.empty()) VersionName = "(" + VersionName + ")"; else VersionName = "(*invalid*)"; - OS << format("%4x%c", Versym->vs_index & VERSYM_VERSION, - Versym->vs_index & VERSYM_HIDDEN ? 'h' : ' '); + OS << format("%4x%c", Version & VERSYM_VERSION, + Version & VERSYM_HIDDEN ? 'h' : ' '); OS << left_justify(VersionName, 13); } - VersymBuf += sizeof(Elf_Versym); } OS << '\n'; } @@ -5834,20 +5921,23 @@ if (!Sec) return; - const uint8_t *VersymBuf = - reinterpret_cast(Obj->base() + Sec->sh_offset); - const ELFDumper *Dumper = this->dumper(); - StringRef StrTable = Dumper->getDynamicStringTable(); + StringRef StrTable; + ArrayRef Syms; + Expected> VerTableOrErr = + this->dumper()->getVersionTable(Sec, &Syms, &StrTable); + if (!VerTableOrErr) { + this->reportUniqueWarning(VerTableOrErr.takeError()); + return; + } + + if (StrTable.empty() || Syms.empty() || Syms.size() != VerTableOrErr->size()) + return; - // Same number of entries in the dynamic symbol table (DT_SYMTAB). - for (const Elf_Sym &Sym : Dumper->dynamic_symbols()) { + for (size_t I = 0, E = Syms.size(); I < E; ++I) { DictScope S(W, "Symbol"); - const Elf_Versym *Versym = reinterpret_cast(VersymBuf); - std::string FullSymbolName = - Dumper->getFullSymbolName(&Sym, StrTable, true /* IsDynamic */); - W.printNumber("Version", Versym->vs_index & VERSYM_VERSION); - W.printString("Name", FullSymbolName); - VersymBuf += sizeof(Elf_Versym); + W.printNumber("Version", (*VerTableOrErr)[I].vs_index & VERSYM_VERSION); + W.printString("Name", this->dumper()->getFullSymbolName( + &Syms[I], StrTable, /*IsDynamic=*/true)); } }