diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -96,6 +96,10 @@ std::vector, uint64_t>> getPltAddresses() const; + + /// Returns a vector containing a symbol version for each dynamic symbol. + /// Returns an empty vector if version sections do not exist. + Expected> readDynsymVersions() const; }; class ELFSectionRef : public SectionRef { diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -654,3 +654,72 @@ } return Result; } + +template +static Expected> +readDynsymVersionsImpl(const ELFFile &EF, + ELFObjectFileBase::elf_symbol_iterator_range Symbols) { + using Elf_Shdr = typename ELFT::Shdr; + const Elf_Shdr *VerSec = nullptr; + const Elf_Shdr *VerNeedSec = nullptr; + const Elf_Shdr *VerDefSec = nullptr; + // The user should ensure sections() can't fail here. + for (const Elf_Shdr &Sec : cantFail(EF.sections())) { + if (Sec.sh_type == ELF::SHT_GNU_versym) + VerSec = &Sec; + else if (Sec.sh_type == ELF::SHT_GNU_verdef) + VerDefSec = &Sec; + else if (Sec.sh_type == ELF::SHT_GNU_verneed) + VerNeedSec = &Sec; + } + if (!VerSec) + return std::vector(); + + Expected, 0>> MapOrErr = + EF.loadVersionMap(VerNeedSec, VerDefSec); + if (!MapOrErr) + return MapOrErr.takeError(); + + std::vector Ret; + size_t I = 0; + for (auto It = Symbols.begin(), E = Symbols.end(); It != E; ++It) { + ++I; + Expected VerEntryOrErr = + EF.template getEntry(*VerSec, I); + if (!VerEntryOrErr) + return createError("unable to read an entry with index " + Twine(I) + + " from " + describe(EF, *VerSec) + ": " + + toString(VerEntryOrErr.takeError())); + + Expected FlagsOrErr = It->getFlags(); + if (!FlagsOrErr) + return createError("unable to read flags for symbol with index " + + Twine(I) + ": " + toString(FlagsOrErr.takeError())); + + bool IsDefault; + Expected VerOrErr = EF.getSymbolVersionByIndex( + (*VerEntryOrErr)->vs_index, IsDefault, *MapOrErr, + (*FlagsOrErr) & SymbolRef::SF_Undefined); + if (!VerOrErr) + return createError("unable to get a version for entry " + Twine(I) + + " of " + describe(EF, *VerSec) + ": " + + toString(VerOrErr.takeError())); + + Ret.push_back({(*VerOrErr).str(), IsDefault}); + } + + return Ret; +} + +Expected> +ELFObjectFileBase::readDynsymVersions() const { + elf_symbol_iterator_range Symbols = getDynamicSymbolIterators(); + if (const auto *Obj = dyn_cast(this)) + return readDynsymVersionsImpl(Obj->getELFFile(), Symbols); + if (const auto *Obj = dyn_cast(this)) + return readDynsymVersionsImpl(Obj->getELFFile(), Symbols); + if (const auto *Obj = dyn_cast(this)) + return readDynsymVersionsImpl(Obj->getELFFile(), Symbols); + return readDynsymVersionsImpl(cast(this)->getELFFile(), + Symbols); +} diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -1575,90 +1575,11 @@ } } -namespace { -struct SymbolVersion { - std::string Name; - bool IsDefault; -}; -} // namespace - -template -static Expected> -readSymbolVersionsELF(const ELFFile &Obj, StringRef FileName, - ELFObjectFileBase::elf_symbol_iterator_range Symbols) { - using Elf_Shdr = typename ELFT::Shdr; - - // We called sections() earlier, so can't fail here. - typename ELFT::ShdrRange SectionsOrErr = cantFail(Obj.sections()); - const Elf_Shdr *SymVerSec = nullptr; - const Elf_Shdr *SymVerNeedSec = nullptr; - const Elf_Shdr *SymVerDefSec = nullptr; - for (const Elf_Shdr &Sec : SectionsOrErr) { - if (Sec.sh_type == ELF::SHT_GNU_versym) - SymVerSec = &Sec; - else if (Sec.sh_type == ELF::SHT_GNU_verdef) - SymVerDefSec = &Sec; - else if (Sec.sh_type == ELF::SHT_GNU_verneed) - SymVerNeedSec = &Sec; - } - - if (!SymVerSec) - return std::vector{}; - - Expected, 0>> MapOrErr = - Obj.loadVersionMap(SymVerNeedSec, SymVerDefSec); - if (!MapOrErr) - return MapOrErr.takeError(); - - std::vector Ret; - size_t I = 0; - for (auto It = Symbols.begin(), E = Symbols.end(); It != E; ++It) { - ++I; - Expected VerEntryOrErr = - Obj.template getEntry(*SymVerSec, I); - if (!VerEntryOrErr) - return createError("unable to read an entry with index " + Twine(I) + - " from " + describe(Obj, *SymVerSec) + ": " + - toString(VerEntryOrErr.takeError())); - - Expected FlagsOrErr = It->getFlags(); - if (!FlagsOrErr) - return createError("unable to read flags for symbol with index " + - Twine(I) + ": " + toString(FlagsOrErr.takeError())); - - bool IsDefault; - Expected VerOrErr = Obj.getSymbolVersionByIndex( - (*VerEntryOrErr)->vs_index, IsDefault, *MapOrErr, - (*FlagsOrErr) & SymbolRef::SF_Undefined); - if (!VerOrErr) - return createError("unable to get a version for entry " + Twine(I) + - " of " + describe(Obj, *SymVerSec) + ": " + - toString(VerOrErr.takeError())); - - Ret.push_back({(*VerOrErr).str(), IsDefault}); - } - - return Ret; -} - -static Expected> -readSymbolVersionsELF(const ELFObjectFileBase &Obj, - ELFObjectFileBase::elf_symbol_iterator_range Symbols) { - if (const auto *ELF = dyn_cast(&Obj)) - return readSymbolVersionsELF(ELF->getELFFile(), Obj.getFileName(), Symbols); - else if (const auto *ELF = dyn_cast(&Obj)) - return readSymbolVersionsELF(ELF->getELFFile(), Obj.getFileName(), Symbols); - else if (const auto *ELF = dyn_cast(&Obj)) - return readSymbolVersionsELF(ELF->getELFFile(), Obj.getFileName(), Symbols); - return readSymbolVersionsELF(cast(&Obj)->getELFFile(), - Obj.getFileName(), Symbols); -} - static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, StringRef ArchiveName = {}, StringRef ArchitectureName = {}) { auto Symbols = Obj.symbols(); - std::vector SymbolVersions; + std::vector SymbolVersions; if (DynamicSyms) { const auto *E = dyn_cast(&Obj); if (!E) { @@ -1667,8 +1588,8 @@ } Symbols = E->getDynamicSymbolIterators(); - if (Expected> VersionsOrErr = - readSymbolVersionsELF(*E, Symbols)) + if (Expected> VersionsOrErr = + E->readDynsymVersions()) SymbolVersions = std::move(*VersionsOrErr); else WithColor::warning(errs(), ToolName) @@ -1738,7 +1659,7 @@ } if (!SymbolVersions.empty() && !SymbolVersions[I].Name.empty()) S.Name += - (SymbolVersions[I].IsDefault ? "@@" : "@") + SymbolVersions[I].Name; + (SymbolVersions[I].IsVerDef ? "@@" : "@") + SymbolVersions[I].Name; S.Sym = Sym; SymbolList.push_back(S);