[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