aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/ELFObjectFile.cpp
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2021-08-17 09:06:39 -0700
committerFangrui Song <i@maskray.me>2021-08-17 09:06:39 -0700
commit78cb1adc5c17850e1a1b33f78f5657ca38493c8d (patch)
treeb3cd3d0ebd48cbd25dba0e3c4609814c2da78a80 /llvm/lib/Object/ELFObjectFile.cpp
parentb28cb53eac70b5044b5bd0fef77530fcc6b29fb0 (diff)
downloadllvm-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.cpp69
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);
+}