diff options
author | Fangrui Song <i@maskray.me> | 2021-08-17 09:06:39 -0700 |
---|---|---|
committer | Fangrui Song <i@maskray.me> | 2021-08-17 09:06:39 -0700 |
commit | 78cb1adc5c17850e1a1b33f78f5657ca38493c8d (patch) | |
tree | b3cd3d0ebd48cbd25dba0e3c4609814c2da78a80 /llvm/lib/Object/ELFObjectFile.cpp | |
parent | b28cb53eac70b5044b5bd0fef77530fcc6b29fb0 (diff) | |
download | llvm-78cb1adc5c17850e1a1b33f78f5657ca38493c8d.zip llvm-78cb1adc5c17850e1a1b33f78f5657ca38493c8d.tar.gz llvm-78cb1adc5c17850e1a1b33f78f5657ca38493c8d.tar.bz2 |
[Object] Move llvm-nm's symbol version utility to ELFObjectFile::readDynsymVersions
The utility can be reused by llvm-objdump -T.
Reviewed By: jhenderson
Differential Revision: https://reviews.llvm.org/D108096
Diffstat (limited to 'llvm/lib/Object/ELFObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/ELFObjectFile.cpp | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp index 9efb28c..2d6d25d 100644 --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -654,3 +654,72 @@ ELFObjectFileBase::getPltAddresses() const { } return Result; } + +template <class ELFT> +static Expected<std::vector<VersionEntry>> +readDynsymVersionsImpl(const ELFFile<ELFT> &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<VersionEntry>(); + + Expected<SmallVector<Optional<VersionEntry>, 0>> MapOrErr = + EF.loadVersionMap(VerNeedSec, VerDefSec); + if (!MapOrErr) + return MapOrErr.takeError(); + + std::vector<VersionEntry> Ret; + size_t I = 0; + for (auto It = Symbols.begin(), E = Symbols.end(); It != E; ++It) { + ++I; + Expected<const typename ELFT::Versym *> VerEntryOrErr = + EF.template getEntry<typename ELFT::Versym>(*VerSec, I); + if (!VerEntryOrErr) + return createError("unable to read an entry with index " + Twine(I) + + " from " + describe(EF, *VerSec) + ": " + + toString(VerEntryOrErr.takeError())); + + Expected<uint32_t> FlagsOrErr = It->getFlags(); + if (!FlagsOrErr) + return createError("unable to read flags for symbol with index " + + Twine(I) + ": " + toString(FlagsOrErr.takeError())); + + bool IsDefault; + Expected<StringRef> 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<std::vector<VersionEntry>> +ELFObjectFileBase::readDynsymVersions() const { + elf_symbol_iterator_range Symbols = getDynamicSymbolIterators(); + if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(this)) + return readDynsymVersionsImpl(Obj->getELFFile(), Symbols); + if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(this)) + return readDynsymVersionsImpl(Obj->getELFFile(), Symbols); + if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(this)) + return readDynsymVersionsImpl(Obj->getELFFile(), Symbols); + return readDynsymVersionsImpl(cast<ELF64BEObjectFile>(this)->getELFFile(), + Symbols); +} |