[0/5] LoongArch: Add DT_RELR (packing relative relocs) support

Message ID 20240622100307.9498-1-xry111@xry111.site
Headers
Series LoongArch: Add DT_RELR (packing relative relocs) support |

Message

Xi Ruoyao June 22, 2024, 10:03 a.m. UTC
  This series adds DT_RELR support for LoongArch.

The leading 3 patches pave the way for DT_RELR:

The first patch rejects turning R_LARCH_32 as a runtime reloc in
ELFCLASS64, specifically R_LARCH_32 won't be turned to an
R_LARCH_RELATIVE in ELFCLASS64 silently.  This avoids an OOB write at
runtime, and also simplifies the logic of DT_RELR implementation.

The second patch fixes a long-standing bug causing some relocs missing
(overwritten by another reloc, or written out of the .rela.dyn section)
when multiple STT_GNU_IFUNC symbol is defined locally with different
visibilities and we are linking a shared object.  Without DT_RELR in
most cases an R_LARCH_RELATIVE against __dso_handle is overwritten by
an R_LARCH_JUMP_SLOT and the issue is mostly latent.  But with DT_RELR
the R_LARCH_RELATIVE is packed, and other relocs start to be
overwritten, causing Glibc test failures.  Thus the bug must be fixed
before implementing DT_RELR.

The third patch makes STV_PROTECTED function (STT_FUNC and
STT_GNU_IFUNC) symbols referenced locally when linking a shared library.
The other ports don't do this only because they rely on copy relocation
and -mdirect-extern-access to remove unnecessary GOT access, and with
-mdirect-extern-access locally referencing STV_PROTECTED functions can
break pointer equality.  This is not a problem for us because we don't
and won't support copy relocation, and a programmer shouldn't use
-mdirect-extern-access unless they can make sure no dynamic link is
performed.  So we can just make STV_PROTECTED functions referenced
locally.  This makes the code slightly faster, and also simplifies the
logic of DT_RELR implementation.

The fourth patch implements DT_RELR.  The algorithm is based on the
AArch64 implementation by Szabolcs and simplified because we don't have
as many features as AArch64 (for example we don't have -z
dynamic-undefined-weak).  The linker relaxation pass is adapted to fix
up the relative relocations to be packed when deleting bytes from the
section where the relative relocations are against.

The fifth patch adds tests for DT_RELR.  Most tests are also ported from
AArch64.  Several tests were added to check the addend (link-time
address) is correctly written into the relocated section (doing so is
not strictly needed for RELA, but strictly needed for RELR).  Besides
these tests, the DT_RELR implementation is also tested by:

- Running ld bootstrap test with -z pack-relative-relocs.  The test
  has passed.  (The patch adding this test isn't included in this series
  because it's not a target specific change and better reviewed
  separately.)
- Building Glibc (which enables -z pack-relative-relocs by default if
  available) with the patched linker and run its test suite.  All
  relative relocs in libc.so are packed and the test result is all clean.
- Building patched Linux kernel with DT_RELR enabled.  All relative
  relocs in vmlinux is packed, the kernel booted fine and it has been
  running fine for 24 hours.

Xi Ruoyao (5):
  LoongArch: Reject R_LARCH_32 from becoming a runtime reloc in
    ELFCLASS64
  LoongArch: Fix bad reloc with mixed visibility ifunc symbols in shared
    libraries
  LoongArch: Make protected function symbols local for -shared
  LoongArch: Add DT_RELR support
  LoongArch: Add DT_RELR tests

 bfd/elfnn-loongarch.c                         | 654 +++++++++++++++++-
 binutils/testsuite/lib/binutils-common.exp    |   1 +
 ld/emulparams/elf64loongarch.sh               |   1 +
 ld/testsuite/ld-loongarch-elf/ifunc-reloc.d   |  19 +
 ld/testsuite/ld-loongarch-elf/ifunc-reloc.s   |  55 ++
 .../ld-loongarch-elf/ld-loongarch-elf.exp     |  13 +
 .../ld-loongarch-elf/protected-func.d         |   6 +
 .../ld-loongarch-elf/protected-func.s         |  17 +
 .../ld-loongarch-elf/r_larch_32_elf64.d       |   4 +
 .../ld-loongarch-elf/r_larch_32_elf64.s       |   3 +
 ld/testsuite/ld-loongarch-elf/relr-addend.d   |  11 +
 ld/testsuite/ld-loongarch-elf/relr-addend.s   |  17 +
 ld/testsuite/ld-loongarch-elf/relr-align.d    |  22 +
 ld/testsuite/ld-loongarch-elf/relr-align.s    | 106 +++
 ld/testsuite/ld-loongarch-elf/relr-data-pie.d |  18 +
 .../ld-loongarch-elf/relr-data-shared.d       |  18 +
 ld/testsuite/ld-loongarch-elf/relr-data.s     |  71 ++
 .../ld-loongarch-elf/relr-discard-pie.d       |   8 +
 .../ld-loongarch-elf/relr-discard-shared.d    |  11 +
 ld/testsuite/ld-loongarch-elf/relr-discard.ld |  13 +
 ld/testsuite/ld-loongarch-elf/relr-discard.s  |  61 ++
 ld/testsuite/ld-loongarch-elf/relr-got-pie.d  |  15 +
 .../ld-loongarch-elf/relr-got-shared.d        |  15 +
 ld/testsuite/ld-loongarch-elf/relr-got.s      |  27 +
 ld/testsuite/ld-loongarch-elf/relr-relocs.ld  |  24 +
 ld/testsuite/ld-loongarch-elf/relr-text-pie.d |  14 +
 .../ld-loongarch-elf/relr-text-shared.d       |  14 +
 ld/testsuite/ld-loongarch-elf/relr-text.s     |  10 +
 28 files changed, 1215 insertions(+), 33 deletions(-)
 create mode 100644 ld/testsuite/ld-loongarch-elf/ifunc-reloc.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/ifunc-reloc.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/protected-func.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/protected-func.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/r_larch_32_elf64.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/r_larch_32_elf64.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-addend.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-addend.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-align.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-align.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-data-pie.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-data-shared.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-data.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-discard-pie.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-discard-shared.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-discard.ld
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-discard.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-got-pie.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-got-shared.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-got.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-relocs.ld
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-text-pie.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-text-shared.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/relr-text.s