[llvm-branch-commits] ELF: Do not rewrite IFUNC relocations to point to PLT if no GOT/PLT needed. (PR #133531)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Mar 28 15:33:59 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld
Author: Peter Collingbourne (pcc)
<details>
<summary>Changes</summary>
This enables the use of IFUNC to implement custom relocation types,
such as the PAuth relocation types that will be introduced in a
subsequent pull request.
TODO:
- Add tests.
- Fix broken tests.
---
Full diff: https://github.com/llvm/llvm-project/pull/133531.diff
3 Files Affected:
- (modified) lld/ELF/Relocations.cpp (+5-3)
- (modified) lld/ELF/Symbols.h (+2)
- (modified) lld/ELF/SyntheticSections.cpp (+5-1)
``````````diff
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 629702b45965b..46117a75ccea8 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -869,7 +869,8 @@ static void addRelativeReloc(Ctx &ctx, InputSectionBase &isec,
// relrDyn sections don't support odd offsets. Also, relrDyn sections
// don't store the addend values, so we must write it to the relocated
// address.
- if (part.relrDyn && isec.addralign >= 2 && offsetInSec % 2 == 0) {
+ if (part.relrDyn && isec.addralign >= 2 && offsetInSec % 2 == 0 &&
+ !sym.isGnuIFunc()) {
isec.addReloc({expr, type, offsetInSec, addend, &sym});
if (shard)
part.relrDyn->relocsVec[parallel::getThreadIndex()].push_back(
@@ -1107,8 +1108,6 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
}
} else if (needsPlt(expr)) {
sym.setFlags(NEEDS_PLT);
- } else if (LLVM_UNLIKELY(isIfunc)) {
- sym.setFlags(HAS_DIRECT_RELOC);
}
// If the relocation is known to be a link-time constant, we know no dynamic
@@ -1194,6 +1193,9 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
}
}
+ if (LLVM_UNLIKELY(isIfunc && !needsGot(expr) && !needsPlt(expr)))
+ sym.setFlags(HAS_DIRECT_RELOC);
+
// When producing an executable, we can perform copy relocations (for
// STT_OBJECT) and canonical PLT (for STT_FUNC) if sym is defined by a DSO.
// Copy relocations/canonical PLT entries are unsupported for
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 64f2f6eaa8d09..d4280f367d23b 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -42,6 +42,8 @@ void printTraceSymbol(const Symbol &sym, StringRef name);
enum {
NEEDS_GOT = 1 << 0,
NEEDS_PLT = 1 << 1,
+ // True if this is an ifunc with a direct relocation that cannot be
+ // represented as a RELATIVE relocation.
HAS_DIRECT_RELOC = 1 << 2,
// True if this symbol needs a canonical PLT entry, or (during
// postScanRelocations) a copy relocation.
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index b03c4282ab1aa..afa0482bae3ba 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1707,9 +1707,13 @@ void RelocationBaseSection::mergeRels() {
}
void RelocationBaseSection::partitionRels() {
+ const RelType relativeRel = ctx.target->relativeRel;
+ const RelType iRelativeRel = ctx.target->iRelativeRel;
+ for (auto &r : relocs)
+ if (r.type == relativeRel && r.sym->isGnuIFunc())
+ r.type = iRelativeRel;
if (!combreloc)
return;
- const RelType relativeRel = ctx.target->relativeRel;
numRelativeRelocs =
std::stable_partition(relocs.begin(), relocs.end(),
[=](auto &r) { return r.type == relativeRel; }) -
``````````
</details>
https://github.com/llvm/llvm-project/pull/133531
More information about the llvm-branch-commits
mailing list