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

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

Message

Xi Ruoyao June 30, 2024, 7:18 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.

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 is
  https://sourceware.org/pipermail/binutils/2024-June/135021.html but
  it does not work with old Glibc, thus it cannot be upstreamed until we
  figure out how to skip it for old Glibc.
- 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 100+ hours.

Changes from v2:

Incremental changes can be reviewed at
https://github.com/xry111/binutils-gdb/commits/xry111/loongarch-relr-2024-v2.1/.

- Fix the comment of the relr field in struct
  loongarch_elf_section_data.
- Reuse loongarch_elf_section_data macro for casting to
  (struct loongarch_elf_section_data *).
- Allow R_LARCH_64 -> R_LARCH_RELATIVE in ELFCLASS32 for now since
  there's no real reason it won't work.  Using R_LARCH_64 in ELFCLASS32
  may be stupid though and we can reconsider when we finalize ilp32
  ABIs.
- Move R_LARCH_32 vs ELFCLASS64 diagnostic to check_relocs.  A guard
  against it is still in relocate_section to avoid an assertion failure.
  (Note that even if check_relocs return false relocate_section is still
  executed.)
- Fix relr-text-pie test to really link a PIE.
- Fix typos in comments describing allocating ifunc PLT step by step.
- Fix wrong indents in loongarch_elf_late_size_sections.

Changes from v1:

- No real code change.
- Rebase to current master branch (resolving a conflict with AArch64 ILP32
  DT_RELR commit)
- "preemptable" -> "preemptible", "unpreemptable" -> "non-preemptible"
  for all patches (commit messages & comments)
- Clarify "OOB write", fix a typo, and remove "for DLL [should be DSO] or
  PIE" in the commit message of patch 1: it's not important if the output
  is DSO/PIE or not; even for DSO/PIE the R_LARCH_32 relocs *resolved at
  link time* are perfectly fine and they are massively used in debug
  info.  So the important thing is we cannot leave it unresolved for
  Glibc.
- Reword comment for LARCH_REF_LOCAL in patch 3 to (hopefully) avoid some
  confusion.
- Move the explanation of the test suite from this cover letter to patch
  5 commit message.

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                         | 665 +++++++++++++++++-
 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, 1224 insertions(+), 35 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
  

Comments

mengqinggang July 5, 2024, 4:13 a.m. UTC | #1
This series patches have been applied, thank you!


在 2024/6/30 下午3:18, Xi Ruoyao 写道:
> 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.
>
> 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 is
>    https://sourceware.org/pipermail/binutils/2024-June/135021.html but
>    it does not work with old Glibc, thus it cannot be upstreamed until we
>    figure out how to skip it for old Glibc.
> - 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 100+ hours.
>
> Changes from v2:
>
> Incremental changes can be reviewed at
> https://github.com/xry111/binutils-gdb/commits/xry111/loongarch-relr-2024-v2.1/.
>
> - Fix the comment of the relr field in struct
>    loongarch_elf_section_data.
> - Reuse loongarch_elf_section_data macro for casting to
>    (struct loongarch_elf_section_data *).
> - Allow R_LARCH_64 -> R_LARCH_RELATIVE in ELFCLASS32 for now since
>    there's no real reason it won't work.  Using R_LARCH_64 in ELFCLASS32
>    may be stupid though and we can reconsider when we finalize ilp32
>    ABIs.
> - Move R_LARCH_32 vs ELFCLASS64 diagnostic to check_relocs.  A guard
>    against it is still in relocate_section to avoid an assertion failure.
>    (Note that even if check_relocs return false relocate_section is still
>    executed.)
> - Fix relr-text-pie test to really link a PIE.
> - Fix typos in comments describing allocating ifunc PLT step by step.
> - Fix wrong indents in loongarch_elf_late_size_sections.
>
> Changes from v1:
>
> - No real code change.
> - Rebase to current master branch (resolving a conflict with AArch64 ILP32
>    DT_RELR commit)
> - "preemptable" -> "preemptible", "unpreemptable" -> "non-preemptible"
>    for all patches (commit messages & comments)
> - Clarify "OOB write", fix a typo, and remove "for DLL [should be DSO] or
>    PIE" in the commit message of patch 1: it's not important if the output
>    is DSO/PIE or not; even for DSO/PIE the R_LARCH_32 relocs *resolved at
>    link time* are perfectly fine and they are massively used in debug
>    info.  So the important thing is we cannot leave it unresolved for
>    Glibc.
> - Reword comment for LARCH_REF_LOCAL in patch 3 to (hopefully) avoid some
>    confusion.
> - Move the explanation of the test suite from this cover letter to patch
>    5 commit message.
>
> 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                         | 665 +++++++++++++++++-
>   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, 1224 insertions(+), 35 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
>