[lld] [ELF] Fix non-preemptible IFUNC IRELATIVE addends (PR #179037)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 31 06:00:02 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld-elf

Author: Zihong Yao (yaozihong)

<details>
<summary>Changes</summary>

## Summary
- Fix non-preemptible IFUNC IRELATIVE addends to use resolver symbol unless direct relocations require canonicalization
- Prevent ld.so crashes in glibc on RISC-V

## Evidence

### Before the fix

```
readelf -rW ~/build/glibc-main/libc.so.6 | rg R_RISCV_IRELATIVE
000000000013d960  000000000000003a R_RISCV_IRELATIVE                         c62ac
000000000013d968  000000000000003a R_RISCV_IRELATIVE                         c591a

readelf -sW ~/build/glibc-main/libc.so.6 | rg "__libc_memcpy_ifunc|__libc_memset_ifunc"
 11660: 00000000000c0c00     4 FUNC    LOCAL  DEFAULT   47 __libc_memcpy_ifunc
 11746: 00000000000c1558     4 FUNC    LOCAL  DEFAULT   47 __libc_memset_ifunc
```

These addends don't match the resolver symbols, leading to a crash in glibc ld.so when resolving symbols.

### After the fix

```
readelf -rW ~/build/glibc-after/libc.so.6 | rg R_RISCV_IRELATIVE
000000000013d960  000000000000003a R_RISCV_IRELATIVE                         c1558
000000000013d968  000000000000003a R_RISCV_IRELATIVE                         c0c00

readelf -sW ~/build/glibc-after/libc.so.6 | rg "__libc_memcpy_ifunc|__libc_memset_ifunc"
 11660: 00000000000c0c00     4 FUNC    LOCAL  DEFAULT   47 __libc_memcpy_ifunc
 11746: 00000000000c1558     4 FUNC    LOCAL  DEFAULT   47 __libc_memset_ifunc
```

These addends match the resolver symbols:
- `__libc_memset_ifunc` at `0xc1558`
- `__libc_memcpy_ifunc` at `0xc0c00`

## Testing

### glibc relink + readelf verification
As shown above.

### `ninja check-lld` 
```
Total Discovered Tests: 3177
  Unsupported      :   20 (0.63%)
  Passed           : 3156 (99.34%)
  Expectedly Failed:    1 (0.03%)
```

---
Full diff: https://github.com/llvm/llvm-project/pull/179037.diff


1 Files Affected:

- (modified) lld/ELF/Relocations.cpp (+14-5) 


``````````diff
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 90c1a22c81d96..876e32dd90f1d 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1507,13 +1507,22 @@ static bool handleNonPreemptibleIfunc(Ctx &ctx, Symbol &sym, uint16_t flags) {
   // original section/value pairs. For non-GOT non-PLT relocation case below, we
   // may alter section/value, so create a copy of the symbol to make
   // section/value fixed.
-  auto *directSym = makeDefined(cast<Defined>(sym));
-  directSym->allocateAux(ctx);
+  Defined *directSym = nullptr;
+  Symbol *irelSym = &sym;
+  if (flags & HAS_DIRECT_RELOC) {
+    directSym = makeDefined(cast<Defined>(sym));
+    directSym->allocateAux(ctx);
+    irelSym = directSym;
+  } else {
+    sym.allocateAux(ctx);
+  }
   auto &dyn = getIRelativeSection(ctx);
   addPltEntry(ctx, *ctx.in.iplt, *ctx.in.igotPlt, dyn, ctx.target->iRelativeRel,
-              *directSym);
-  sym.allocateAux(ctx);
-  ctx.symAux.back().pltIdx = ctx.symAux[directSym->auxIdx].pltIdx;
+              *irelSym);
+  if (directSym) {
+    sym.allocateAux(ctx);
+    ctx.symAux.back().pltIdx = ctx.symAux[directSym->auxIdx].pltIdx;
+  }
 
   if (flags & HAS_DIRECT_RELOC) {
     // Change the value to the IPLT and redirect all references to it.

``````````

</details>


https://github.com/llvm/llvm-project/pull/179037


More information about the llvm-commits mailing list