aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/ELFObjectFile.cpp
diff options
context:
space:
mode:
authorJoel Galenson <jgalenson@google.com>2018-08-24 15:21:56 +0000
committerJoel Galenson <jgalenson@google.com>2018-08-24 15:21:56 +0000
commitd36fb48a274bd6c53ce289e968be4c53c189e0a7 (patch)
tree7b990eb796bb4742421d2d4fdb0013bae3672532 /llvm/lib/Object/ELFObjectFile.cpp
parent954d4a2235865af388f3d8ce4dc7793ba4703139 (diff)
downloadllvm-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.cpp65
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;
+}