From d36fb48a274bd6c53ce289e968be4c53c189e0a7 Mon Sep 17 00:00:00 2001 From: Joel Galenson Date: Fri, 24 Aug 2018 15:21:56 +0000 Subject: 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 --- llvm/lib/Object/ELFObjectFile.cpp | 65 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) (limited to 'llvm/lib/Object/ELFObjectFile.cpp') 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 #include #include @@ -327,3 +329,66 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { TheTriple.setArchName(Triple); } + +std::vector> +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 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 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 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> 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; +} -- cgit v1.1