Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -58,7 +58,7 @@ private: template - void relocate(uint8_t *Buf, + void relocate(uint8_t *Buf, uint8_t *BufEnd, llvm::iterator_range< const llvm::object::Elf_Rel_Impl *> Rels, const ObjectFile &File, uintX_t BaseAddr); Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -28,7 +28,8 @@ template template void InputSection::relocate( - uint8_t *Buf, iterator_range *> Rels, + uint8_t *Buf, uint8_t *BufEnd, + iterator_range *> Rels, const ObjectFile &File, uintX_t BaseAddr) { typedef Elf_Rel_Impl RelType; bool IsMips64EL = File.getObj().isMips64EL(); @@ -37,6 +38,7 @@ uint32_t Type = RI.getType(IsMips64EL); uintX_t GotVA = Out::Got->getVA(); uintX_t SymVA; + bool ForPltEntry = false; // Handle relocations for local symbols -- they never get // resolved so we don't allocate a SymbolBody. @@ -57,6 +59,7 @@ if (Target->relocNeedsPlt(Type, Body)) { SymVA = Out::Plt->getEntryAddr(Body); Type = Target->getPCRelReloc(); + ForPltEntry = true; } else if (Target->relocNeedsGot(Type, Body)) { SymVA = Out::Got->getEntryAddr(Body); Type = Target->getGotRefReloc(); @@ -68,8 +71,9 @@ } } - Target->relocateOne(Buf, reinterpret_cast(&RI), Type, - BaseAddr, SymVA, GotVA); + Target->relocateOne(Buf, BufEnd, + reinterpret_cast(&RI), Type, + BaseAddr, SymVA, GotVA, ForPltEntry); } } @@ -87,9 +91,9 @@ // 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); } } Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -34,9 +34,9 @@ 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, - uint64_t GotVA) const = 0; + virtual void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, uint64_t SymVA, + uint64_t GotVA, bool ForPltEntry) const = 0; virtual ~TargetInfo(); @@ -59,9 +59,9 @@ 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, - uint64_t GotVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, uint64_t SymVA, + uint64_t GotVA, bool ForPltEntry) const override; }; class X86_64TargetInfo final : public TargetInfo { @@ -71,9 +71,9 @@ 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, - uint64_t GotVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, uint64_t SymVA, + uint64_t GotVA, bool ForPltEntry) const override; bool isRelRelative(uint32_t Type) const override; }; @@ -84,9 +84,9 @@ 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, - uint64_t GotVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, uint64_t SymVA, + uint64_t GotVA, bool ForPltEntry) const override; bool isRelRelative(uint32_t Type) const override; }; @@ -97,9 +97,9 @@ 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, - uint64_t GotVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, uint64_t SymVA, + uint64_t GotVA, bool ForPltEntry) const override; }; class ARMTargetInfo final : public TargetInfo { @@ -109,9 +109,9 @@ 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, - uint64_t GotVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, uint64_t SymVA, + uint64_t GotVA, bool ForPltEntry) const override; }; class AArch64TargetInfo final : public TargetInfo { @@ -121,9 +121,9 @@ 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, - uint64_t GotVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, uint64_t SymVA, + uint64_t GotVA, bool ForPltEntry) const override; }; class MipsTargetInfo final : public TargetInfo { @@ -133,9 +133,9 @@ 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, - uint64_t GotVA) const override; + void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, uint64_t SymVA, + uint64_t GotVA, bool ForPltEntry) const override; }; extern std::unique_ptr Target; Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -68,9 +68,9 @@ static void or32le(uint8_t *L, int32_t V) { write32le(L, read32le(L) | V); } static void or64le(uint8_t *L, int64_t V) { write64le(L, read64le(L) | V); } -void X86TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, - uint64_t BaseAddr, uint64_t SymVA, - uint64_t GotVA) const { +void X86TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP, + uint32_t Type, uint64_t BaseAddr, uint64_t SymVA, + uint64_t GotVA, bool ForPltEntry) const { typedef ELFFile::Elf_Rel Elf_Rel; auto &Rel = *reinterpret_cast(RelP); @@ -172,9 +172,11 @@ } } -void X86_64TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, - uint32_t Type, uint64_t BaseAddr, - uint64_t SymVA, uint64_t GotVA) const { +void X86_64TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, + const void *RelP, uint32_t Type, + uint64_t BaseAddr, + uint64_t SymVA, uint64_t GotVA, + bool ForPltEntry) const { typedef ELFFile::Elf_Rela Elf_Rela; auto &Rel = *reinterpret_cast(RelP); @@ -313,9 +315,10 @@ return true; } } -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, - uint64_t GotVA) const { + uint64_t GotVA, bool ForPltEntry) const { typedef ELFFile::Elf_Rela Elf_Rela; auto &Rel = *reinterpret_cast(RelP); int64_t Addend = Rel.r_addend; @@ -431,6 +434,10 @@ if (SignExtend32<24>(delta) != delta) error("Relocation R_PPC64_REL24 overflow"); write32be(Loc, (read32be(Loc) & ~Mask) | (delta & Mask)); + + if (ForPltEntry && Loc + 8 < BufEnd && + read32be(Loc + 4) == 0x60000000 /* nop */) + write32be(Loc + 4, 0xe8410028); // ld r2,40(r1) } break; case R_PPC64_REL32: { uint64_t FinalAddress = (BaseAddr + Offset); @@ -468,9 +475,10 @@ 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, - uint64_t GotVA) const {} + uint64_t GotVA, bool ForPltEntry) const {} ARMTargetInfo::ARMTargetInfo() { // PCRelReloc = FIXME @@ -487,9 +495,10 @@ 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, - uint64_t GotVA) const {} + uint64_t GotVA, bool ForPltEntry) const {} AArch64TargetInfo::AArch64TargetInfo() { // PCRelReloc = FIXME @@ -523,9 +532,10 @@ return Expr & (~static_cast(0xFFF)); } -void AArch64TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, - uint32_t Type, uint64_t BaseAddr, - uint64_t SymVA, uint64_t GotVA) const { +void AArch64TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, + const void *RelP, uint32_t Type, + uint64_t BaseAddr, uint64_t SymVA, + uint64_t GotVA, bool ForPltEntry) const { typedef ELFFile::Elf_Rela Elf_Rela; auto &Rel = *reinterpret_cast(RelP); @@ -592,8 +602,9 @@ 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, - uint64_t GotVA) const {} + uint64_t GotVA, bool ForPltEntry) const {} } }