SuccessChanges

Changes from Git (git http://labmaster3.local/git/llvm-project.git)

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)
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/Thunks.h
The file was modifiedlld/test/ELF/ppc64-ifunc.s
The file was modifiedlld/ELF/Arch/PPC64.cpp
The file was modifiedlld/test/ELF/ppc64-toc-relax-ifunc.s
The file was modifiedlld/ELF/Thunks.cpp
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 removedlld/test/ELF/ppc32-gnu-ifunc-nonpreemptable.s
The file was addedlld/test/ELF/ppc32-ifunc-nonpreemptible-pic.s
The file was modifiedlld/ELF/Thunks.cpp
The file was modifiedlld/ELF/Arch/PPC.cpp
The file was addedlld/test/ELF/ppc32-ifunc-nonpreemptible-nopic.s
The file was modifiedlld/ELF/Thunks.h