r336664 | emaste | 2018-07-24 13:35:22 +0200 (Tue, 24 Jul 2018) | 11 lines 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 Index: tools/lld/ELF/InputSection.cpp =================================================================== --- tools/lld/ELF/InputSection.cpp (revision 336663) +++ tools/lld/ELF/InputSection.cpp (revision 336664) @@ -686,6 +686,23 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, } } +// 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 void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { if (Flags & SHF_ALLOC) { @@ -694,7 +711,9 @@ void InputSectionBase::relocate(uint8_t *Buf, uint } auto *Sec = cast(this); - if (Sec->AreRelocsRela) + if (Config->Relocatable) + relocateNonAllocForRelocatable(Sec, Buf); + else if (Sec->AreRelocsRela) Sec->relocateNonAlloc(Buf, Sec->template relas()); else Sec->relocateNonAlloc(Buf, Sec->template rels());