aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/Relocations.cpp
diff options
context:
space:
mode:
authorArthur Eubanks <aeubanks@google.com>2023-08-03 11:00:24 -0700
committerArthur Eubanks <aeubanks@google.com>2023-10-04 13:03:56 -0700
commit9d6ec280fc537b55ef8641ea85d3522426bc5766 (patch)
treed38dc25e9d31bb5fb6ceb02e472585689686fb64 /lld/ELF/Relocations.cpp
parentbfcfc2a6d43f9cd86d66e7e68c03f3200bb1e366 (diff)
downloadllvm-9d6ec280fc537b55ef8641ea85d3522426bc5766.zip
llvm-9d6ec280fc537b55ef8641ea85d3522426bc5766.tar.gz
llvm-9d6ec280fc537b55ef8641ea85d3522426bc5766.tar.bz2
[lld/ELF] Don't relax R_X86_64_(REX_)GOTPCRELX when offset is too far
For each R_X86_64_(REX_)GOTPCRELX relocation, check that the offset to the symbol is representable with 2^32 signed offset. If not, add a GOT entry for it and set its expr to R_GOT_PC so that we emit the GOT load instead of the relaxed lea. Do this in finalizeAddressDependentContent() where we iteratively attempt this (e.g. RISCV uses this for relaxation, ARM uses this to insert thunks). Decided not to do the opposite of inserting GOT entries initially and removing them when relaxable because removing GOT entries isn't simple. One drawback of this approach is that if we see any GOTPCRELX relocation, we'll create an empty .got even if it's not required in the end. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D157020
Diffstat (limited to 'lld/ELF/Relocations.cpp')
-rw-r--r--lld/ELF/Relocations.cpp6
1 files changed, 5 insertions, 1 deletions
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 9305c95..ee27cc1 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -904,7 +904,7 @@ static void addPltEntry(PltSection &plt, GotPltSection &gotPlt,
sym, 0, R_ABS});
}
-static void addGotEntry(Symbol &sym) {
+void elf::addGotEntry(Symbol &sym) {
in.got->addEntry(sym);
uint64_t off = sym.getGotOffset();
@@ -1055,6 +1055,10 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
} else if (!isAbsoluteValue(sym)) {
expr =
target->adjustGotPcExpr(type, addend, sec->content().data() + offset);
+ // If the target adjusted the expression to R_RELAX_GOT_PC, we may end up
+ // needing the GOT if we can't relax everything.
+ if (expr == R_RELAX_GOT_PC)
+ in.got->hasGotOffRel.store(true, std::memory_order_relaxed);
}
}