[lld] [ELF] Fix non-preemptible IFUNC IRELATIVE addends (PR #179037)
Zihong Yao via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 31 05:59:14 PST 2026
https://github.com/yaozihong created https://github.com/llvm/llvm-project/pull/179037
## 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%)
```
>From fad4efbcee5948b45827659fa6557c633c4d608f Mon Sep 17 00:00:00 2001
From: Yao Zihong <zihongyao at outlook.com>
Date: Wed, 28 Jan 2026 11:18:30 +0800
Subject: [PATCH] [ELF] Fix non-preemptible IFUNC IRELATIVE addends
Avoid using a cloned symbol unless HAS_DIRECT_RELOC is set.
---
lld/ELF/Relocations.cpp | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
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.
More information about the llvm-commits
mailing list