Skip to content

Commit c55c059

Browse files
committed
[ELF][PPC] Don't relax ifunc toc-indirect accesses to toc-relative
Fixes PR42759. ``` // If ifunc is taken address in -fPIC code, it may have a toc entry .section .toc,"aw",@progbits .quad ifunc // ifunc may be defined as STT_GNU_IFUNC in another object file .type ifunc, %gnu_indirect_function ``` If ifunc is non-preemptable (e.g. when linking an executable), the toc entry will be relocated by R_PPC64_IRELATIVE. R_*_IRELATIVE represents the symbolic value of a non-preemptable ifunc (not associated with a canonical PLT) in a writable location. It has an unknown value at link time, so we cannot apply toc-indirect to toc-relative relaxation. Reviewed By: luporl, sfertile Differential Revision: https://reviews.llvm.org/D65755 llvm-svn: 368057
1 parent 9c52f66 commit c55c059

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

lld/ELF/Arch/PPC64.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,11 @@ bool elf::tryRelaxPPC64TocIndirection(RelType type, const Relocation &rel,
172172
: getRelaTocSymAndAddend<ELF64BE>(tocISB, rel.addend);
173173

174174
// Only non-preemptable defined symbols can be relaxed.
175-
if (!d || d->isPreemptible)
175+
//
176+
// The toc entry of a non-preemptable ifunc is relocated by R_PPC64_IRELATIVE,
177+
// which will run at load time to determine the relocated value. It is not
178+
// known until load time, so the access cannot be relaxed.
179+
if (!d || d->isPreemptible || d->isGnuIFunc())
176180
return false;
177181

178182
// Two instructions can materialize a 32-bit signed offset from the toc base.

lld/test/ELF/ppc64-toc-relax-ifunc.s

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# REQUIRES: ppc
2+
3+
# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
4+
# RUN: echo '.globl ifunc; .type ifunc, %gnu_indirect_function; ifunc:' | \
5+
# RUN: llvm-mc -filetype=obj -triple=powerpc64le - -o %t1.o
6+
# RUN: ld.lld %t.o %t1.o -o %t
7+
# RUN: llvm-objdump -d %t | FileCheck %s
8+
9+
## ifunc is a non-preemptable STT_GNU_IFUNC. Its toc entry will be
10+
## relocated by R_PPC64_IRELATIVE, not representable by a toc-relative value.
11+
## Check the toc-indirect access is not relaxed.
12+
13+
# CHECK: nop
14+
# CHECK-NEXT: ld 3, -32768(2)
15+
16+
addis 3, 2, .toc@toc@ha
17+
ld 3, .toc@toc@l(3)
18+
19+
.section .toc,"aw",@progbits
20+
.quad ifunc

0 commit comments

Comments
 (0)