summaryrefslogtreecommitdiff
path: root/lld/ELF/InputSection.cpp
diff options
context:
space:
mode:
authorIgor Kudrin <ikudrin@accesssoftek.com>2018-07-11 12:52:04 +0000
committerIgor Kudrin <ikudrin@accesssoftek.com>2018-07-11 12:52:04 +0000
commitb6a5d886963a296d6d2f0be87252d9491d8f8646 (patch)
tree535a26888e429f0f6414dcba7b0bbe3ab716c649 /lld/ELF/InputSection.cpp
parentdac85c5778473c75c4542072544a05f213699215 (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.cpp21
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>());