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
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
index 7a192b7..b7aab91 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
@@ -384,6 +384,9 @@
const MCInst &Inst) const override;
bool clearsSuperRegisters(const MCRegisterInfo &MRI, const MCInst &Inst,
APInt &Mask) const override;
+ std::vector<std::pair<uint64_t, uint64_t>>
+ findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents,
+ uint64_t GotSectionVA, const Triple &TargetTriple) const;
};
bool X86MCInstrAnalysis::isDependencyBreaking(const MCSubtargetInfo &STI,
@@ -510,6 +513,64 @@
return Mask.getBoolValue();
}
+static std::vector<std::pair<uint64_t, uint64_t>>
+findX86PltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents,
+ uint64_t GotPltSectionVA) {
+ // Do a lightweight parsing of PLT entries.
+ std::vector<std::pair<uint64_t, uint64_t>> Result;
+ for (uint64_t Byte = 0, End = PltContents.size(); Byte + 6 < End; ) {
+ // Recognize a jmp.
+ if (PltContents[Byte] == 0xff && PltContents[Byte + 1] == 0xa3) {
+ // The jmp instruction at the beginning of each PLT entry jumps to the
+ // address of the base of the .got.plt section plus the immediate.
+ uint32_t Imm = support::endian::read32le(PltContents.data() + Byte + 2);
+ Result.push_back(
+ std::make_pair(PltSectionVA + Byte, GotPltSectionVA + Imm));
+ Byte += 6;
+ } else if (PltContents[Byte] == 0xff && PltContents[Byte + 1] == 0x25) {
+ // The jmp instruction at the beginning of each PLT entry jumps to the
+ // immediate.
+ uint32_t Imm = support::endian::read32le(PltContents.data() + Byte + 2);
+ Result.push_back(std::make_pair(PltSectionVA + Byte, Imm));
+ Byte += 6;
+ } else
+ Byte++;
+ }
+ return Result;
+}
+
+static std::vector<std::pair<uint64_t, uint64_t>>
+findX86_64PltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents) {
+ // Do a lightweight parsing of PLT entries.
+ std::vector<std::pair<uint64_t, uint64_t>> Result;
+ for (uint64_t Byte = 0, End = PltContents.size(); Byte + 6 < End; ) {
+ // Recognize a jmp.
+ if (PltContents[Byte] == 0xff && PltContents[Byte + 1] == 0x25) {
+ // The jmp instruction at the beginning of each PLT entry jumps to the
+ // address of the next instruction plus the immediate.
+ uint32_t Imm = support::endian::read32le(PltContents.data() + Byte + 2);
+ Result.push_back(
+ std::make_pair(PltSectionVA + Byte, PltSectionVA + Byte + 6 + Imm));
+ Byte += 6;
+ } else
+ Byte++;
+ }
+ return Result;
+}
+
+std::vector<std::pair<uint64_t, uint64_t>> X86MCInstrAnalysis::findPltEntries(
+ uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents,
+ uint64_t GotPltSectionVA, const Triple &TargetTriple) const {
+ switch (TargetTriple.getArch()) {
+ case Triple::x86:
+ return findX86PltEntries(PltSectionVA, PltContents, GotPltSectionVA);
+ case Triple::x86_64:
+ return findX86_64PltEntries(PltSectionVA, PltContents);
+ default:
+ return {};
+ }
+}
+
} // end of namespace X86_MC
} // end of namespace llvm