diff options
Diffstat (limited to 'lld/ELF')
-rw-r--r-- | lld/ELF/InputSection.cpp | 13 | ||||
-rw-r--r-- | lld/ELF/InputSection.h | 2 | ||||
-rw-r--r-- | lld/ELF/Target.cpp | 37 | ||||
-rw-r--r-- | lld/ELF/Target.h | 40 |
4 files changed, 57 insertions, 35 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index fde71270cf4..eabfeb15d68 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -28,7 +28,8 @@ InputSection<ELFT>::InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header) template <class ELFT> template <bool isRela> void InputSection<ELFT>::relocate( - uint8_t *Buf, iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels, + uint8_t *Buf, uint8_t *BufEnd, + iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels, const ObjectFile<ELFT> &File, uintX_t BaseAddr) { typedef Elf_Rel_Impl<ELFT, isRela> RelType; bool IsMips64EL = File.getObj().isMips64EL(); @@ -41,8 +42,8 @@ void InputSection<ELFT>::relocate( const Elf_Shdr *SymTab = File.getSymbolTable(); if (SymIndex < SymTab->sh_info) { uintX_t SymVA = getLocalRelTarget(File, RI); - Target->relocateOne(Buf, reinterpret_cast<const void *>(&RI), Type, - BaseAddr, SymVA); + Target->relocateOne(Buf, BufEnd, reinterpret_cast<const void *>(&RI), + Type, BaseAddr, SymVA); continue; } @@ -60,7 +61,7 @@ void InputSection<ELFT>::relocate( } else if (isa<SharedSymbol<ELFT>>(Body)) { continue; } - Target->relocateOne(Buf, reinterpret_cast<const void *>(&RI), Type, + Target->relocateOne(Buf, BufEnd, reinterpret_cast<const void *>(&RI), Type, BaseAddr, SymVA); } } @@ -79,9 +80,9 @@ template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) { // Iterate over all relocation sections that apply to this section. for (const Elf_Shdr *RelSec : RelocSections) { if (RelSec->sh_type == SHT_RELA) - relocate(Base, EObj.relas(RelSec), *File, BaseAddr); + relocate(Base, Base + Data.size(), EObj.relas(RelSec), *File, BaseAddr); else - relocate(Base, EObj.rels(RelSec), *File, BaseAddr); + relocate(Base, Base + Data.size(), EObj.rels(RelSec), *File, BaseAddr); } } diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 038c659d144..eea4c2df5e6 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -60,7 +60,7 @@ public: private: template <bool isRela> - void relocate(uint8_t *Buf, + void relocate(uint8_t *Buf, uint8_t *BufEnd, llvm::iterator_range< const llvm::object::Elf_Rel_Impl<ELFT, isRela> *> Rels, const ObjectFile<ELFT> &File, uintX_t BaseAddr); diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 8d3a3515d5a..6f84ada243a 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -64,8 +64,9 @@ bool X86TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { static void add32le(uint8_t *L, int32_t V) { write32le(L, read32le(L) + V); } static void or32le(uint8_t *L, int32_t V) { write32le(L, read32le(L) | V); } -void X86TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, - uint64_t BaseAddr, uint64_t SymVA) const { +void X86TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, + uint64_t SymVA) const { typedef ELFFile<ELF32LE>::Elf_Rel Elf_Rel; auto &Rel = *reinterpret_cast<const Elf_Rel *>(RelP); @@ -164,9 +165,9 @@ bool X86_64TargetInfo::isRelRelative(uint32_t Type) const { } } -void X86_64TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, - uint32_t Type, uint64_t BaseAddr, - uint64_t SymVA) const { +void X86_64TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, + const void *RelP, uint32_t Type, + uint64_t BaseAddr, uint64_t SymVA) const { typedef ELFFile<ELF64LE>::Elf_Rela Elf_Rela; auto &Rel = *reinterpret_cast<const Elf_Rela *>(RelP); @@ -306,7 +307,8 @@ bool PPC64TargetInfo::isRelRelative(uint32_t Type) const { } } -void PPC64TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, +void PPC64TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, + const void *RelP, uint32_t Type, uint64_t BaseAddr, uint64_t SymVA) const { typedef ELFFile<ELF64BE>::Elf_Rela Elf_Rela; auto &Rel = *reinterpret_cast<const Elf_Rela *>(RelP); @@ -397,6 +399,14 @@ void PPC64TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, if (!isInt<24>(R - P)) error("Relocation R_PPC64_REL24 overflow"); write32be(L, (read32be(L) & ~Mask) | ((R - P) & Mask)); + + uint64_t PltStart = Out<ELF64BE>::Plt->getVA(); + uint64_t PltEnd = PltStart + Out<ELF64BE>::Plt->getSize(); + bool InPlt = PltStart <= S + A && S + A < PltEnd; + + if (InPlt && L + 8 < BufEnd && + read32be(L + 4) == 0x60000000 /* nop */) + write32be(L + 4, 0xe8410028); // ld %r2, 40(%r1) break; } case R_PPC64_REL32: @@ -429,7 +439,8 @@ bool PPCTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { bool PPCTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { return false; } -void PPCTargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, +void PPCTargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, + const void *RelP, uint32_t Type, uint64_t BaseAddr, uint64_t SymVA) const {} ARMTargetInfo::ARMTargetInfo() { @@ -445,7 +456,8 @@ bool ARMTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { bool ARMTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { return false; } -void ARMTargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, +void ARMTargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, + const void *RelP, uint32_t Type, uint64_t BaseAddr, uint64_t SymVA) const {} AArch64TargetInfo::AArch64TargetInfo() { @@ -478,9 +490,9 @@ static uint64_t getAArch64Page(uint64_t Expr) { return Expr & (~static_cast<uint64_t>(0xFFF)); } -void AArch64TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, - uint32_t Type, uint64_t BaseAddr, - uint64_t SymVA) const { +void AArch64TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, + const void *RelP, uint32_t Type, + uint64_t BaseAddr, uint64_t SymVA) const { typedef ELFFile<ELF64LE>::Elf_Rela Elf_Rela; auto &Rel = *reinterpret_cast<const Elf_Rela *>(RelP); @@ -544,7 +556,8 @@ bool MipsTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { return false; } -void MipsTargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, +void MipsTargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, + const void *RelP, uint32_t Type, uint64_t BaseAddr, uint64_t SymVA) const { typedef ELFFile<ELF32LE>::Elf_Rel Elf_Rel; auto &Rel = *reinterpret_cast<const Elf_Rel *>(RelP); diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index 0eb28a1a9fb..94a343030ac 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -33,8 +33,9 @@ public: virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0; virtual bool relocPointsToGot(uint32_t Type) const; virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0; - virtual void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, - uint64_t BaseAddr, uint64_t SymVA) const = 0; + virtual void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, + uint64_t SymVA) const = 0; virtual ~TargetInfo(); @@ -56,8 +57,9 @@ public: bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocPointsToGot(uint32_t Type) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; - void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, - uint64_t BaseAddr, uint64_t SymVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, + uint64_t SymVA) const override; }; class X86_64TargetInfo final : public TargetInfo { @@ -67,8 +69,9 @@ public: uint64_t PltEntryAddr) const override; bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; - void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, - uint64_t BaseAddr, uint64_t SymVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, + uint64_t SymVA) const override; bool isRelRelative(uint32_t Type) const override; }; @@ -79,8 +82,9 @@ public: uint64_t PltEntryAddr) const override; bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; - void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, - uint64_t BaseAddr, uint64_t SymVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, + uint64_t SymVA) const override; bool isRelRelative(uint32_t Type) const override; }; @@ -91,8 +95,9 @@ public: uint64_t PltEntryAddr) const override; bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; - void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, - uint64_t BaseAddr, uint64_t SymVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, + uint64_t SymVA) const override; }; class ARMTargetInfo final : public TargetInfo { @@ -102,8 +107,9 @@ public: uint64_t PltEntryAddr) const override; bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; - void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, - uint64_t BaseAddr, uint64_t SymVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, + uint64_t SymVA) const override; }; class AArch64TargetInfo final : public TargetInfo { @@ -113,8 +119,9 @@ public: uint64_t PltEntryAddr) const override; bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; - void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, - uint64_t BaseAddr, uint64_t SymVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, + uint64_t SymVA) const override; }; class MipsTargetInfo final : public TargetInfo { @@ -124,8 +131,9 @@ public: uint64_t PltEntryAddr) const override; bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; - void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, - uint64_t BaseAddr, uint64_t SymVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, + uint64_t SymVA) const override; }; extern std::unique_ptr<TargetInfo> Target; |