Fix ld bloat introduced between binutils-2.38 and 2.39
Checks
Commit Message
(Subject is for email list use, see below for a better
commit title.)
Ok to commit? If so, binutils-2.39 and 2.40 branches too?
If not, suggestion of other approaches, no later than
configure-time?
--- 8< ---
Subject: Let --with-elf-maxpagesize=N override target ELF_MAXPAGESIZE
Since commit 9833b7757d24, "PR28824, relro security issues",
ELF_MAXPAGESIZE matters much more, with regards to layout of
the linked file. That commit fixed an actual bug, but also
exposes a problem for targets were that value is too high.
For example, for ARM(32, a.k.a. "Aarch32") specifically
bfd_arch_arm, it's set to 64 KiB, making all Linux(/GNU)
targets pay an extra amount of up to 60 KiB of bloat in
DSO:s and executables. This matters when there are many
such files, and where storage is expensive.
It's *mostly* bloat when using a Linux kernel, as ARM(32) is
a good example of an target where ELF_MAXPAGESIZE is set to
an extreme value for an obscure corner-case. The ARM
(32-bit) kernel has 4 KiB pages, has had that value forever,
and can't be configured to any other value. The use-case is
IIUC "Aarch32" emulation on an "Aarch64" (arm64) kernel, but
not just that, but a setup where the Linux page-size is
configured to something other than the *default* 4 KiB. Not
sure there actually any such systems in use, again with
both Aarch32 compatibility support and a non-4KiB pagesize,
with all the warnings in the kernel config and requiring the
"EXPERT" level set on.
That may sound like an argument for setting the bfd_arch_arm
ELF_MAXPAGESIZE to 4 KiB, but then the obscure corner-case
wouldn't be properly handled. I wouldn't oppose that, but I
prefer not to regress the linker by default in my own patch.
I know about the linker option "-z max-page-size=0x1000",
but that requires finding every linker invocation or
patching gcc -and still finding all stray naked ld calls.
There was for a short while config.relro_use_commonpagesize
in the linker (commit 31b4d3a16f20) but besides the
self-explanatory ld_config_type member, IMHO it's too
obscure to re-introduce.
Instead, I suggest simply making ELF_MAXPAGESIZE generally
overridable by means of a --with option at linker
configuration time. In the patch I make the option
ELF-specific mostly for simplicity (more object-formats
means more places to find and patch, also the original
problem is ELF-specific).
bfd:
Let --with-elf-maxpagesize=N override target ELF_MAXPAGESIZE.
* configure.ac: Define FORCED_ELF_MAXPAGESIZE if
--with-elf-maxpagesize=N is passed.
* elfxx-target.h: Let FORCED_ELF_MAXPAGESIZE] override ELF_MAXPAGESIZE.
* configure, config.in: Regenerate.
---
bfd/config.in | 3 +++
bfd/configure | 22 ++++++++++++++++++++--
bfd/configure.ac | 10 ++++++++++
bfd/elfxx-target.h | 5 +++++
4 files changed, 38 insertions(+), 2 deletions(-)
Comments
On Mon, Jan 02, 2023 at 05:08:57PM +0100, Hans-Peter Nilsson via Binutils wrote:
> That may sound like an argument for setting the bfd_arch_arm
> ELF_MAXPAGESIZE to 4 KiB, but then the obscure corner-case
> wouldn't be properly handled.
Agreed. It's what x86 did when facing the same thing. If anybody
cares about the obscure corner-case you identify then they can just
use -z max-page-size. Or edit elf32-arm.c.
> Instead, I suggest simply making ELF_MAXPAGESIZE generally
> overridable by means of a --with option at linker
> configuration time.
I dislike configure time options that affect linker behaviour, but I
realise I'm flogging a dead horse since we already have a lot of them.
However, this particular option is worse than most since it affects
all ELF targets. That can't be correct or useful with
--enable-targets=all.
@@ -115,6 +115,16 @@ AC_ARG_WITH(mmap,
*) AC_MSG_ERROR(bad value ${withval} for BFD with-mmap option) ;;
esac],[want_mmap=false])dnl
+ac_default_elf_maxpagesize=unset
+AC_ARG_WITH(elf_maxpagesize,
+ AS_HELP_STRING([--with-elf-maxpagesize=N],
+ [Set ELF_MAXPAGESIZE to N instead of using the target value]),
+[ac_default_elf_maxpagesize=$withval]) dnl
+if test ${ac_default_elf_maxpagesize} != unset; then
+ AC_DEFINE_UNQUOTED(FORCED_ELF_MAXPAGESIZE, ${ac_default_elf_maxpagesize},
+ [Define to a value with which to override the target ELF_MAXPAGESIZE.])
+fi
+
AC_ARG_ENABLE(secureplt,
[ --enable-secureplt Default to creating read-only plt entries],
[case "${enableval}" in
@@ -374,6 +374,11 @@
#define ELF_OSABI ELFOSABI_NONE
#endif
+#ifdef FORCED_ELF_MAXPAGESIZE
+#undef ELF_MAXPAGESIZE
+#define ELF_MAXPAGESIZE FORCED_ELF_MAXPAGESIZE
+#endif
+
#ifndef ELF_MAXPAGESIZE
# error ELF_MAXPAGESIZE is not defined
#define ELF_MAXPAGESIZE 1