diff options
author | Fangrui Song <maskray@google.com> | 2022-01-04 18:41:03 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2022-04-26 10:16:11 -0700 |
commit | e895cff59aa562cad83fa0fdd187bfe4b45312d5 (patch) | |
tree | a2524a2b8557001b3896bff8cb1483f8ca88efb3 /elf/Makefile | |
parent | 57292f574156f817b7cbeb33ea6278c6eab22bcc (diff) | |
download | glibc-e895cff59aa562cad83fa0fdd187bfe4b45312d5.zip glibc-e895cff59aa562cad83fa0fdd187bfe4b45312d5.tar.gz glibc-e895cff59aa562cad83fa0fdd187bfe4b45312d5.tar.bz2 |
elf: Support DT_RELR relative relocation format [BZ #27924]
PIE and shared objects usually have many relative relocations. In
2017/2018, SHT_RELR/DT_RELR was proposed on
https://groups.google.com/g/generic-abi/c/bX460iggiKg/m/GxjM0L-PBAAJ
("Proposal for a new section type SHT_RELR") and is a pre-standard. RELR
usually takes 3% or smaller space than R_*_RELATIVE relocations. The
virtual memory size of a mostly statically linked PIE is typically 5~10%
smaller.
---
Notes I will not include in the submitted commit:
Available on https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/maskray/relr
"pre-standard": even Solaris folks are happy with the refined generic-abi
proposal. Cary Coutant will apply the change
https://sourceware.org/pipermail/libc-alpha/2021-October/131781.html
This patch is simpler than Chrome OS's glibc patch and makes ELF_DYNAMIC_DO_RELR
available to all ports. I don't think the current glibc implementation
supports ia64 in an ELFCLASS32 container. That said, the style I used is
works with an ELFCLASS32 container for 64-bit machine if ElfW(Addr) is
64-bit.
* Chrome OS folks have carried a local patch since 2018 (latest version:
https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/refs/heads/main/sys-libs/glibc/files/local/glibc-2.32).
I.e. this feature has been battle tested.
* Android bionic supports 2018 and switched to DT_RELR==36 in 2020.
* The Linux kernel has supported CONFIG_RELR since 2019-08
(https://git.kernel.org/linus/5cf896fb6be3effd9aea455b22213e27be8bdb1d).
* A musl patch (by me) exists but is not applied:
https://www.openwall.com/lists/musl/2019/03/06/3
* rtld-elf from FreeBSD 14 will support DT_RELR.
I believe upstream glibc should support DT_RELR to benefit all Linux
distributions. I filed some feature requests to get their attention:
* Gentoo: https://bugs.gentoo.org/818376
* Arch Linux: https://bugs.archlinux.org/task/72433
* Debian https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=996598
* Fedora https://bugzilla.redhat.com/show_bug.cgi?id=2014699
As of linker support (to the best of my knowledge):
* LLD support DT_RELR.
* https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/refs/heads/main/sys-devel/binutils/files/
has a gold patch.
* GNU ld feature request https://sourceware.org/bugzilla/show_bug.cgi?id=27923
Changes from the original patch:
1. Check the linker option, -z pack-relative-relocs, which add a
GLIBC_ABI_DT_RELR symbol version dependency on the shared C library if
it provides a GLIBC_2.XX symbol version.
2. Change make variale to have-dt-relr.
3. Rename tst-relr-no-pie to tst-relr-pie for --disable-default-pie.
4. Use TEST_VERIFY in tst-relr.c.
5. Add the check-tst-relr-pie.out test to check for linker generated
libc.so version dependency on GLIBC_ABI_DT_RELR.
6. Move ELF_DYNAMIC_DO_RELR before ELF_DYNAMIC_DO_REL.
Diffstat (limited to 'elf/Makefile')
-rw-r--r-- | elf/Makefile | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/elf/Makefile b/elf/Makefile index 073807b..3dcc550 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -542,6 +542,25 @@ tests-special += \ # tests-special endif endif +ifeq ($(have-dt-relr),yes) +tests += \ + tst-relr \ +# tests +ifeq ($(have-fpie),yes) +tests += \ + tst-relr-pie \ +# tests +tests-pie += \ + tst-relr-pie \ +# tests-pie +tests-special += \ + $(objpfx)check-tst-relr-pie.out \ +# tests-special +endif +CFLAGS-tst-relr-pie.c += $(pie-ccflag) +LDFLAGS-tst-relr += -Wl,-z,pack-relative-relocs +LDFLAGS-tst-relr-pie += -Wl,-z,pack-relative-relocs +endif endif tests-special += $(objpfx)tst-relro-ldso.out $(objpfx)tst-relro-libc.out @@ -2789,3 +2808,9 @@ $(objpfx)check-abi-version-libc.out: $(common-objpfx)libc.so | sed -ne '/.gnu.version_d/, /.gnu.version_r/ p' \ | grep GLIBC_ABI_DT_RELR > $@; \ $(evaluate-test) + +$(objpfx)check-tst-relr-pie.out: $(objpfx)tst-relr-pie + LC_ALL=C $(OBJDUMP) -p $< \ + | sed -ne '/required from libc.so/,$$ p' \ + | grep GLIBC_ABI_DT_RELR > $@; \ + $(evaluate-test) |