summaryrefslogtreecommitdiffstats
path: root/lld/ELF
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF')
-rw-r--r--lld/ELF/InputSection.cpp13
-rw-r--r--lld/ELF/InputSection.h2
-rw-r--r--lld/ELF/Target.cpp37
-rw-r--r--lld/ELF/Target.h40
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;
OpenPOWER on IntegriCloud