## Summary
-fno-plt is a gcc flag that disables the use of PLT stubs for function
calls. I suggest we enable it for x86 and x86_64. The code size bloat is
substantial on aarch64, and (as far as I could tell) it is silently
ignored on arm32, mips64, s390x, riscv64, and ppc64le. On mips64 and
riscv64, there is -mno-plt, but it significantly bloats code size and
instruction count.
## Benefits
Each PLT thunk adds at least 32 bytes to the binary size on x86 and
x86_64. The PLT also occupies valuable instruction cache space and, on
x86, indirect jump predictor space (the actual function call occupies
one slot, plus PLT accesses on x86 use indirect calls so occupy another
slot).
I did a quick test, and building apk-tools on x86_64 with -fno-plt (plus
the standard abuild.conf flags) reduces package size from 119480 to
115686 (-3794) and install size from 253648 to 245384 (-8264).
## Downsides
As far as I know, the main reason why -fno-plt is not used by default in
gcc is because it is incompatible with lazy linking. This is not
relevant to Alpine Linux, as musl does not support lazy linking anyways.
There is another, less documented issue: -fno-plt increases code size
for non-interposable ELF function calls on x86 and x86_64 from 5 bytes
to 6 bytes. On aarch64, calls double from 8 bytes to 16 bytes, plus 8
more bytes per function to get the GOT address. On rv64gc, -mno-plt
inflates calls from 4 bytes to 10 bytes. Note that these numbers are
with -fPIE; -fno-PIE numbers differ.
Certain packages may not compile or run properly with -fno-plt, but
these are likely to be minimal. See the next section for more
information.
## Other distros
Arch Linux has enabled -fno-plt by default (and supports only x86_64)
since 2017: https://github.com/archlinux/svntogit-packages/commit/72de4d337e02e5626598038b801517e47988b4c8.
It is disabled for xorg, glibc, valgrind, and openjdk:
https://github.com/archlinux/svntogit-packages/search?q=%22-fno-plt%22
Gentoo does not use -fno-plt but a third-party overlay enables -fno-plt
along with other optimization flags such as LTO. There are minimal
issues reported with -fno-plt, mostly around the usual suspects doing
sketchy things like wine, glibc, and xorg-server:
https://github.com/InBetweenNames/gentooLTO/blob/master/sys-config/ltoize/files/package.cflags/no-plt.conf
I strongly suspect the remaining packages are false positives, since
exceptions are applied for basically anybody that reports an issue, and
they ave almost never removed.
OpenWRT has enabled -fno-plt since 2016:
https://github.com/openwrt/openwrt/commit/fb713ddd4dd49fb60ee4ab732071abf2c3ad5fc5.
As far as I could tell, Debian, Fedora, and openSUSE do not use
-fno-plt by default. I believe for Debian, this is because BIND_NOW is
still not enabled by default. For Fedora and openSUSE, I think binary
size is not a priority.
## Conclusion
I think -fno-plt has moderate benefits, and minimal costs for x86 and
x86_64. There is some risk of breaking some packages, but I think the
risk is minimal as long as the known-broken packages (xorg, glibc,
valgrind, and openjdk) have -fno-plt fully tested and disabled if
necessary, and the flag overall is given enough time to test in edge
before a stable release.
I am primarily concerned with and have primarily analyzed x86 and
x86_64, but am not opposed to enabling it also for other architectures
if someone does better analysis and finds a better cost-benefit ratio.