[all-commits] [llvm/llvm-project] 45acc3: [ELF][PPC64] Implement IPLT code sequence for non-...
Fangrui Song via All-commits
all-commits at lists.llvm.org
Sun Dec 29 22:42:16 PST 2019
Branch: refs/heads/master
Home: https://github.com/llvm/llvm-project
Commit: 45acc35ac21323bafaf5d4367df10ebc4eed35f4
https://github.com/llvm/llvm-project/commit/45acc35ac21323bafaf5d4367df10ebc4eed35f4
Author: Fangrui Song <maskray at google.com>
Date: 2019-12-29 (Sun, 29 Dec 2019)
Changed paths:
M lld/ELF/Arch/PPC64.cpp
M lld/ELF/Thunks.cpp
M lld/ELF/Thunks.h
M lld/test/ELF/ppc64-ifunc.s
M lld/test/ELF/ppc64-toc-relax-ifunc.s
Log Message:
-----------
[ELF][PPC64] Implement IPLT code sequence for non-preemptible IFUNC
Non-preemptible IFUNC are placed in in.iplt (.glink on EM_PPC64). If
there is a non-GOT non-PLT relocation, for pointer equality, we change
the type of the symbol from STT_IFUNC and STT_FUNC and bind it to the
.glink entry.
On EM_386, EM_X86_64, EM_ARM, and EM_AARCH64, the PLT code sequence
loads the address from its associated .got.plt slot. An IPLT also has an
associated .got.plt slot and can use the same code sequence.
On EM_PPC64, the PLT code sequence is actually a bl instruction in
.glink . It jumps to `__glink_PLTresolve` (the PLT header). and
`__glink_PLTresolve` computes the .plt slot (relocated by
R_PPC64_JUMP_SLOT).
An IPLT does not have an associated R_PPC64_JUMP_SLOT, so we cannot use
`bl` in .iplt . Instead, create a call stub which has a similar code
sequence as PPC64PltCallStub. We don't save the TOC pointer, so such
scenarios will not work: a function pointer to a non-preemptible ifunc,
which resolves to a function defined in another DSO. This is the
restriction described by https://sourceware.org/glibc/wiki/GNU_IFUNC
(though on many architectures it works in practice):
Requirement (a): Resolver must be defined in the same translation unit as the implementations.
If an ifunc is taken address but not called, technically we don't need
an entry for it, but we currently do that.
This patch makes
// clang -fuse-ld=lld -fno-pie -no-pie a.c
// clang -fuse-ld=lld -fPIE -pie a.c
#include <stdio.h>
static void impl(void) { puts("meow"); }
void thefunc(void) __attribute__((ifunc("resolver")));
void *resolver(void) { return &impl; }
int main(void) {
thefunc();
void (*theptr)(void) = &thefunc;
theptr();
}
work on Linux glibc and FreeBSD. Calling a function pointer pointing to
a Non-preemptible IFUNC never worked before.
Differential Revision: https://reviews.llvm.org/D71509
More information about the All-commits
mailing list