diff options
author | Joel Galenson <jgalenson@google.com> | 2018-08-24 15:21:56 +0000 |
---|---|---|
committer | Joel Galenson <jgalenson@google.com> | 2018-08-24 15:21:56 +0000 |
commit | d36fb48a274bd6c53ce289e968be4c53c189e0a7 (patch) | |
tree | 7b990eb796bb4742421d2d4fdb0013bae3672532 /llvm/lib/Object/ELFObjectFile.cpp | |
parent | 954d4a2235865af388f3d8ce4dc7793ba4703139 (diff) | |
download | llvm-d36fb48a274bd6c53ce289e968be4c53c189e0a7.zip llvm-d36fb48a274bd6c53ce289e968be4c53c189e0a7.tar.gz llvm-d36fb48a274bd6c53ce289e968be4c53c189e0a7.tar.bz2 |
Find PLT entries for x86, x86_64, and AArch64.
This adds a new method to ELFObjectFileBase that returns the symbols and addresses of PLT entries.
This design was suggested by pcc and eugenis in https://reviews.llvm.org/D49383.
Differential Revision: https://reviews.llvm.org/D50203
llvm-svn: 340610
Diffstat (limited to 'llvm/lib/Object/ELFObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/ELFObjectFile.cpp | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp index e806c8f..173cb30 100644 --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -14,6 +14,7 @@ #include "llvm/Object/ELFObjectFile.h" #include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Object/ELF.h" #include "llvm/Object/ELFTypes.h" @@ -23,6 +24,7 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/TargetRegistry.h" #include <algorithm> #include <cstddef> #include <cstdint> @@ -327,3 +329,66 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { TheTriple.setArchName(Triple); } + +std::vector<std::pair<DataRefImpl, uint64_t>> +ELFObjectFileBase::getPltAddresses() const { + std::string Err; + const auto Triple = makeTriple(); + const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err); + if (!T) + return {}; + uint64_t JumpSlotReloc = 0; + switch (Triple.getArch()) { + case Triple::x86: + JumpSlotReloc = ELF::R_386_JUMP_SLOT; + break; + case Triple::x86_64: + JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; + break; + case Triple::aarch64: + JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; + break; + default: + return {}; + } + const auto *MIA = T->createMCInstrAnalysis(T->createMCInstrInfo()); + if (!MIA) + return {}; + Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None; + for (const SectionRef &Section : sections()) { + StringRef Name; + if (Section.getName(Name)) + continue; + if (Name == ".plt") + Plt = Section; + else if (Name == ".rela.plt" || Name == ".rel.plt") + RelaPlt = Section; + else if (Name == ".got.plt") + GotPlt = Section; + } + if (!Plt || !RelaPlt || !GotPlt) + return {}; + StringRef PltContents; + if (Plt->getContents(PltContents)) + return {}; + ArrayRef<uint8_t> PltBytes((const uint8_t *)PltContents.data(), + Plt->getSize()); + auto PltEntries = MIA->findPltEntries(Plt->getAddress(), PltBytes, + GotPlt->getAddress(), Triple); + // Build a map from GOT entry virtual address to PLT entry virtual address. + DenseMap<uint64_t, uint64_t> GotToPlt; + for (const auto &Entry : PltEntries) + GotToPlt.insert(std::make_pair(Entry.second, Entry.first)); + // Find the relocations in the dynamic relocation table that point to + // locations in the GOT for which we know the corresponding PLT entry. + std::vector<std::pair<DataRefImpl, uint64_t>> Result; + for (const auto &Relocation : RelaPlt->relocations()) { + if (Relocation.getType() != JumpSlotReloc) + continue; + auto PltEntryIter = GotToPlt.find(Relocation.getOffset()); + if (PltEntryIter != GotToPlt.end()) + Result.push_back(std::make_pair( + Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second)); + } + return Result; +} |