SuccessChanges

Summary

  1. [ELF][PPC64] Implement IPLT code sequence for non-preemptible IFUNC (details)
  2. [ELF][PPC32] Implement IPLT code sequence for non-preemptible IFUNC (details)
  3. [ELF][PPC64] Improve "call lacks nop" diagnostic and make it compatible (details)
Commit 45acc35ac21323bafaf5d4367df10ebc4eed35f4 by maskray
[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
The file was modifiedlld/ELF/Arch/PPC64.cpp
The file was modifiedlld/test/ELF/ppc64-ifunc.s
The file was modifiedlld/test/ELF/ppc64-toc-relax-ifunc.s
The file was modifiedlld/ELF/Thunks.cpp
The file was modifiedlld/ELF/Thunks.h
Commit fb2944bd7f8ac6d7c4bccd3ac2033ba58c690038 by maskray
[ELF][PPC32] Implement IPLT code sequence for non-preemptible IFUNC
Similar to D71509 (EM_PPC64), on EM_PPC, the IPLT code sequence should
be similar to a PLT call stub. Unlike EM_PPC64, EM_PPC -msecure-plt has
small/large PIC model differences.
* -fpic/-fpie: R_PPC_PLTREL24 r_addend=0.  The call stub loads an
address relative to `_GLOBAL_OFFSET_TABLE_`.
* -fPIC/-fPIE: R_PPC_PLTREL24 r_addend=0x8000. (A partial linked object
file may have an addend larger than 0x8000.) The call stub loads an
address relative to .got2+0x8000.
Just assume large PIC model for now. This patch makes:
  // clang -fuse-ld=lld -msecure-plt -fno-pie -no-pie a.c
// clang -fuse-ld=lld -msecure-plt -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. -fpie will crash because the compiler and the
linker do not agree on the value which r30 stores (_GLOBAL_OFFSET_TABLE_
vs .got2+0x8000).
Differential Revision: https://reviews.llvm.org/D71621
The file was addedlld/test/ELF/ppc32-ifunc-nonpreemptible-pic.s
The file was modifiedlld/ELF/Thunks.h
The file was modifiedlld/ELF/Thunks.cpp
The file was removedlld/test/ELF/ppc32-gnu-ifunc-nonpreemptable.s
The file was addedlld/test/ELF/ppc32-ifunc-nonpreemptible-nopic.s
The file was modifiedlld/ELF/Arch/PPC.cpp
Commit bb87364f26ce6b1fbb2cc5e155fd8ff82aafbe8d by maskray
[ELF][PPC64] Improve "call lacks nop" diagnostic and make it compatible
with GCC<5.5 and GCC<6.4
GCC before r245813 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79439)
did not emit nop after b/bl. This can happen with recursive calls.
r245813 was back ported to GCC 5.5 and GCC 6.4.
This is common, for example, libstdc++.a(locale.o) shipped with GCC 4.9
and many objects in netlib lapack can cause lld to error.  gold allows
such calls to the same section. Our __plt_foo symbol's `section` field
is used for ThunkSection, so we can't implement a similar loosen rule
easily. But we can make use of its `file` field which is currently NULL.
Differential Revision: https://reviews.llvm.org/D71639
The file was modifiedlld/ELF/InputSection.cpp
The file was modifiedlld/test/ELF/ppc64-error-toc-restore.s
The file was modifiedlld/test/ELF/ppc64-bsymbolic-toc-restore.s
The file was modifiedlld/ELF/Thunks.cpp
The file was modifiedlld/test/ELF/ppc64-error-toc-tail-call.s