[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