lld: fix addends with partial linking

[ELF] Update addends in non-allocatable sections for REL targets when
creating a relocatable output.

LLVM PR: 37735
LLVM Differential Revision: https://reviews.llvm.org/D48929

PR:		225128
Obtained from:	LLVM r336799 by Igor Kudrin
This commit is contained in:
Ed Maste 2018-07-24 11:35:22 +00:00
parent daa1e39110
commit 33683c3d3c

View File

@ -686,6 +686,23 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
}
}
// This is used when '-r' is given.
// For REL targets, InputSection::copyRelocations() may store artificial
// relocations aimed to update addends. They are handled in relocateAlloc()
// for allocatable sections, and this function does the same for
// non-allocatable sections, such as sections with debug information.
static void relocateNonAllocForRelocatable(InputSection *Sec, uint8_t *Buf) {
const unsigned Bits = Config->Is64 ? 64 : 32;
for (const Relocation &Rel : Sec->Relocations) {
// InputSection::copyRelocations() adds only R_ABS relocations.
assert(Rel.Expr == R_ABS);
uint8_t *BufLoc = Buf + Rel.Offset + Sec->OutSecOff;
uint64_t TargetVA = SignExtend64(Rel.Sym->getVA(Rel.Addend), Bits);
Target->relocateOne(BufLoc, Rel.Type, TargetVA);
}
}
template <class ELFT>
void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) {
if (Flags & SHF_ALLOC) {
@ -694,7 +711,9 @@ void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) {
}
auto *Sec = cast<InputSection>(this);
if (Sec->AreRelocsRela)
if (Config->Relocatable)
relocateNonAllocForRelocatable(Sec, Buf);
else if (Sec->AreRelocsRela)
Sec->relocateNonAlloc<ELFT>(Buf, Sec->template relas<ELFT>());
else
Sec->relocateNonAlloc<ELFT>(Buf, Sec->template rels<ELFT>());