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(); @@ -62,7 +63,7 @@ } } - Target->relocateOne(Buf, reinterpret_cast(&RI), Type, + Target->relocateOne(Buf, BufEnd, reinterpret_cast(&RI), Type, BaseAddr, SymVA); } } @@ -81,9 +82,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,8 +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) 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(); @@ -58,8 +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) 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 { @@ -69,8 +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) 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; }; @@ -81,8 +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) 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; }; @@ -93,8 +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) 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 { @@ -104,8 +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) 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 { @@ -115,8 +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) 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 { @@ -126,8 +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) 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 Target; Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -64,8 +64,9 @@ 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::Elf_Rel Elf_Rel; auto &Rel = *reinterpret_cast(RelP); @@ -165,9 +166,9 @@ } } -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::Elf_Rela Elf_Rela; auto &Rel = *reinterpret_cast(RelP); @@ -306,7 +307,8 @@ } } -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::Elf_Rela Elf_Rela; auto &Rel = *reinterpret_cast(RelP); @@ -397,6 +399,14 @@ if (!isInt<24>(R - P)) error("Relocation R_PPC64_REL24 overflow"); write32be(L, (read32be(L) & ~Mask) | ((R - P) & Mask)); + + uint64_t PltStart = Out::Plt->getVA(); + uint64_t PltEnd = PltStart + Out::Plt->getSize(); + bool ForPltEntry = PltStart <= S + A && S + A < PltEnd; + + if (ForPltEntry && L + 8 < BufEnd && + read32be(L + 4) == 0x60000000 /* nop */) + write32be(L + 4, 0xe8410028); // ld %r2, 40(%r1) break; } case R_PPC64_REL32: @@ -430,7 +440,8 @@ 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() { @@ -446,7 +457,8 @@ 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() { @@ -479,9 +491,9 @@ return Expr & (~static_cast(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::Elf_Rela Elf_Rela; auto &Rel = *reinterpret_cast(RelP); @@ -547,7 +559,8 @@ 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 {} } } Index: test/elf2/Inputs/shared-ppc64.s =================================================================== --- /dev/null +++ test/elf2/Inputs/shared-ppc64.s @@ -0,0 +1,10 @@ +.section ".opd","aw" +.global bar +bar: +# FIXME: This should be: .quad .Lbar,.TOC.@tocbase,0 +# But we can't handle .TOC.@tocbase for shared libraries yet +.quad .Lbar,0,0 + +.text +.Lbar: + blr Index: test/elf2/ppc64-toc-restore.s =================================================================== --- /dev/null +++ test/elf2/ppc64-toc-restore.s @@ -0,0 +1,45 @@ +// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o +// RUN: ld.lld2 -shared %t2.o -o %t2.so +// RUN: ld.lld2 -dynamic-linker /lib64/ld64.so.1 -rpath foo -rpath bar --export-dynamic %t.o %t2.so -o %t +// RUN: llvm-objdump -d %t | FileCheck %s +// REQUIRES: ppc + +// CHECK: Disassembly of section .text: + +.global _start +_start: + bl bar + nop + +// CHECK: _start: +// CHECK: 10020000: 48 00 00 21 bl .+32 +// CHECK-NOT: 10020004: 60 00 00 00 nop +// CHECK: 10020004: e8 41 00 28 ld 2, 40(1) + +.global noret +noret: + bl bar + li 5, 7 + +// CHECK: noret: +// CHECK: 10020008: 48 00 00 19 bl .+24 +// CHECK: 1002000c: 38 a0 00 07 li 5, 7 + +.global noretend +noretend: + bl bar + +// CHECK: noretend: +// CHECK: 10020010: 48 00 00 11 bl .+16 + +.global noretb +noretb: + b bar + +// CHECK: noretb: +// CHECK: 10020014: 48 00 00 0c b .+12 + +// CHECK: Disassembly of section .plt: +// CHECK: .plt: +// CHECK: 10020020: