[ELF][PPC64] Don't perform toc-indirect to toc-relative relaxation for R_PPC64_TOC16_...
authorFangrui Song <maskray@google.com>
Sat, 18 Apr 2020 06:08:11 +0000 (23:08 -0700)
committerFangrui Song <maskray@google.com>
Tue, 28 Apr 2020 19:13:27 +0000 (12:13 -0700)
commit03ffe5860549e97a0f2d8262b100e8910f61c528
tree553d9819a5d455b756932bb7eeb1652c0d6fb1bf
parent2a3cf5e5834302a9525a721627c17902399b8d62
[ELF][PPC64] Don't perform toc-indirect to toc-relative relaxation for R_PPC64_TOC16_HA not followed by R_PPC64_TOC16_LO_DS

The current implementation assumes that R_PPC64_TOC16_HA is always followed
by R_PPC64_TOC16_LO_DS. This can break with:

// Load the address of the TOC entry, instead of the value stored at that address
  addis 3, 2, .LC0@tloc@ha  # R_PPC64_TOC16_HA
  addi  3, 3, .LC0@tloc@l   # R_PPC64_TOC16_LO
  blr

which is used by boringssl's util/fipstools/delocate/delocate.go
https://github.com/google/boringssl/blob/master/crypto/fipsmodule/FIPS.md has some documentation.
In short, this tool converts an assembly file to avoid any potential relocations.
The distance to an input .toc is not a constant after linking, so the assembly cannot use an `addis;ld` pair.
Instead, delocate changes the code to jump to a stub (`addis;addi`) which loads the TOC entry address.

Reviewed By: sfertile

Differential Revision: https://reviews.llvm.org/D78431
lld/ELF/InputSection.cpp
lld/test/ELF/ppc64-toc-relax2.s [new file with mode: 0644]