diff options
author | Igor Kudrin <ikudrin@accesssoftek.com> | 2018-07-11 12:52:04 +0000 |
---|---|---|
committer | Igor Kudrin <ikudrin@accesssoftek.com> | 2018-07-11 12:52:04 +0000 |
commit | b6a5d886963a296d6d2f0be87252d9491d8f8646 (patch) | |
tree | 535a26888e429f0f6414dcba7b0bbe3ab716c649 /lld/ELF/InputSection.cpp | |
parent | dac85c5778473c75c4542072544a05f213699215 (diff) |
[ELF] Update addends in non-allocatable sections for REL targets when creating a relocatable output.
This fixes PR37735.
Differential Revision: https://reviews.llvm.org/D48929
Diffstat (limited to 'lld/ELF/InputSection.cpp')
-rw-r--r-- | lld/ELF/InputSection.cpp | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 89b29294765..1f963e6ec5e 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -729,6 +729,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) { @@ -737,7 +754,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>()); |