[v5] elf: Set image base address to the maximum page size
Checks
Commit Message
On Mon, Jun 29, 2026 at 9:24 AM Alan Modra <amodra@gmail.com> wrote:
>
> On Fri, Jun 26, 2026 at 12:06:50PM +0800, H.J. Lu wrote:
> > Here is the v4 patch.
>
> On x86_64-linux I see FAIL: ld-elf/textaddr8 due to not matching the
> expected header.
>
> Program Headers:
> Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
> LOAD 0x000000 0x0000000000800000 0x0000000000800000 0x0000e8 0x0000e8 R 0x800000
> LOAD 0x800000 0x0000000001000000 0x0000000001000000 0x000004 0x000004 R E 0x800000
> LOAD 0x1000000 0x0000000001800000 0x0000000001800000 0x000004 0x000004 RW 0x800000
>
> aarch64-linux-gnu +FAIL: ld-elf/textaddr8
> alpha-linux-gnu +FAIL: ld-elf/textaddr8
> am33_2.0-linux-gnu +FAIL: ld-elf/textaddr8
> armeb-linux-gnueabi +FAIL: ld-elf/textaddr8
> arm-linux-gnueabi +FAIL: ld-elf/textaddr8
> cris-linux-gnu +FAIL: ld-elf/textaddr8
> crisv32-linux-gnu +FAIL: ld-elf/textaddr8
> csky-linux-gnu +FAIL: ld-elf/textaddr8
> frv-linux-gnu +FAIL: ld-elf/textaddr8
> h8300-linux-gnu +FAIL: ld-elf/textaddr8
> hppa64-linux-gnu +FAIL: ld-elf/textaddr8
> hppa-linux-gnu +FAIL: ld-elf/textaddr8
> i586-linux-gnu +FAIL: ld-elf/textaddr8
> ia64-linux-gnu +FAIL: ld-elf/textaddr8
> kvx-linux-gnu +FAIL: ld-elf/textaddr8
> lm32-linux-gnu +FAIL: ld-elf/textaddr8
> loongarch64-linux-gnu +FAIL: ld-elf/textaddr8
> m32r-linux-gnu +FAIL: ld-elf/textaddr8
> m68k-linux-gnu +FAIL: ld-elf/textaddr8
> metag-linux-gnu +FAIL: ld-elf/textaddr8
> microblaze-linux-gnu +FAIL: ld-elf/textaddr8
> microblaze-linux-gnu +FAIL: ld-elf/textaddr9
> mips64-linux-gnuabi64 +FAIL: ld-elf/textaddr8
> mipsel-linux-gnu +FAIL: ld-elf/textaddr8
> mipsisa32el-linux-gnu +FAIL: ld-elf/textaddr8
> mips-linux-gnu +FAIL: ld-elf/textaddr8
> nds32le-linux-gnu +FAIL: ld-elf/textaddr8
> nds32le-linux-gnu +FAIL: ld-elf/textaddr9
> or1k-linux-gnu +FAIL: ld-elf/textaddr8
> powerpc64le-linux-gnu +FAIL: ld-elf/textaddr8
> powerpc64-linux-gnu +FAIL: ld-elf/textaddr8
> powerpc-linux-gnu +FAIL: ld-elf/textaddr8
> riscv64-linux-gnu +FAIL: ld-elf/textaddr8
> s390-linux-gnu +FAIL: ld-elf/textaddr8
> s390x-linux-gnu +FAIL: ld-elf/textaddr8
> sh4-linux-gnu +FAIL: ld-elf/textaddr8
> sparc64-linux-gnu +FAIL: ld-elf/textaddr8
> sparc-linux-gnu +FAIL: ld-elf/textaddr8
> tilegx-linux-gnu +FAIL: ld-elf/textaddr8
> tilepro-linux-gnu +FAIL: ld-elf/textaddr8
> x86_64-pc-linux-gnu +FAIL: ld-elf/textaddr8
> x86_64-pc-linux-gnux32 +FAIL: ld-elf/textaddr8
>
>
Changes in v5:
1. Adjust ld-elf/textaddr8 and ld-elf/textaddr9.
2. Add testsuite/ld-elf/textaddr10.d.
Comments
On Mon, Jun 29, 2026 at 11:40:53AM +0800, H.J. Lu wrote:
> PR ld/34184
> * ldexp.c (fold_binary): Set the default image base address to
> the maximum page size for ELF PDE output if it is lower than
> the maximum page size set on command-line and issue an warning
> if the image base address set on command-line is lower than the
> maximum page size.
> * testsuite/ld-elf/elf.exp: Add ld/34184 tests for PDE, PIE
> static PDE and static PIE.
> * testsuite/ld-elf/pr34184.c: New file.
> * testsuite/ld-elf/textaddr3.d: Change -Ttext-segment address
> to 0x200100 so that it > the maximum page size.
> * testsuite/ld-elf/textaddr5.d: Likewise.
> * testsuite/ld-elf/textaddr8.d: New test.
> * testsuite/ld-elf/textaddr9.d: Likewise.
> * testsuite/ld-elf/textaddr10.d: Likewise.
The testcases still introduce new failures.
alpha-linux-gnu +FAIL: ld-elf/textaddr10
h8300-linux-gnu +FAIL: ld-elf/textaddr8
microblaze-linux-gnu +FAIL: ld-elf/textaddr10
microblaze-linux-gnu +FAIL: ld-elf/textaddr9
alpha because the testsuite adds -Ttext-segment. h8300 with a RWE
segment starting at 0x800000, combining .text and .data. microblaze
also mashes .text and .data together. None of these are your problem,
so the patch is OK.
From c0b8ac0fedc9cf836a4ae1126b7540e58de54c1a Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 28 May 2026 10:47:37 +0800
Subject: [PATCH v5] elf: Set image base address to the maximum page size
When generating Position Dependent Executable for ELF with the maximum
page size set on command-line, set the default image base address to the
maximum page size to avoid segfault if it is lower than the maximum page
size and issue an warning if the image base address set on command-line
is lower than the maximum page size.
PR ld/34184
* ldexp.c (fold_binary): Set the default image base address to
the maximum page size for ELF PDE output if it is lower than
the maximum page size set on command-line and issue an warning
if the image base address set on command-line is lower than the
maximum page size.
* testsuite/ld-elf/elf.exp: Add ld/34184 tests for PDE, PIE
static PDE and static PIE.
* testsuite/ld-elf/pr34184.c: New file.
* testsuite/ld-elf/textaddr3.d: Change -Ttext-segment address
to 0x200100 so that it > the maximum page size.
* testsuite/ld-elf/textaddr5.d: Likewise.
* testsuite/ld-elf/textaddr8.d: New test.
* testsuite/ld-elf/textaddr9.d: Likewise.
* testsuite/ld-elf/textaddr10.d: Likewise.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
ld/ldexp.c | 44 ++++++++++++++++++++++++++++----
ld/testsuite/ld-elf/elf.exp | 36 ++++++++++++++++++++++++++
ld/testsuite/ld-elf/pr34184.c | 8 ++++++
ld/testsuite/ld-elf/textaddr10.d | 9 +++++++
ld/testsuite/ld-elf/textaddr3.d | 2 +-
ld/testsuite/ld-elf/textaddr5.d | 2 +-
ld/testsuite/ld-elf/textaddr8.d | 9 +++++++
ld/testsuite/ld-elf/textaddr9.d | 9 +++++++
8 files changed, 112 insertions(+), 7 deletions(-)
create mode 100644 ld/testsuite/ld-elf/pr34184.c
create mode 100644 ld/testsuite/ld-elf/textaddr10.d
create mode 100644 ld/testsuite/ld-elf/textaddr8.d
create mode 100644 ld/testsuite/ld-elf/textaddr9.d
@@ -552,20 +552,54 @@ fold_binary (etree_type *tree)
/* Check to see if the user has overridden the default
value. */
segment_name = tree->binary.rhs->name.name;
+
+ bool update_image_base
+ = ((bfd_get_flavour (link_info.output_bfd)
+ == bfd_target_elf_flavour)
+ && bfd_link_pde (&link_info)
+ && link_info.maxpagesize_is_set);
+
for (seg = segments; seg; seg = seg->next)
if (strcmp (seg->name, segment_name) == 0)
{
if (!seg->used
&& config.magic_demand_paged
- && link_info.maxpagesize != 0
- && (seg->value % link_info.maxpagesize) != 0)
- einfo (_("%P: warning: address of `%s' "
- "isn't multiple of maximum page size\n"),
- segment_name);
+ && link_info.maxpagesize != 0)
+ {
+ if (seg->value < link_info.maxpagesize)
+ {
+ if (update_image_base)
+ einfo (_("%P: warning: image base (0x%llx) < "
+ "maximum page size (0x%llx)\n"),
+ (unsigned long long) seg->value,
+ (unsigned long long) link_info.maxpagesize);
+ }
+ else if ((seg->value % link_info.maxpagesize) != 0)
+ einfo (_("%P: warning: address of `%s' "
+ "isn't multiple of maximum page size\n"),
+ segment_name);
+
+ /* Don't override image base from command-line. */
+ if (strcmp (segment_name, "text-segment") == 0)
+ update_image_base = false;
+
+ }
seg->used = true;
value = seg->value;
break;
}
+
+ /* When generating Position Dependent Executable for ELF with the
+ maximum page size set on command-line, if image base address
+ is lower than the maximum page size, set image base address
+ to the maximum page size to avoid segfault. NB: For ELF,
+ -Ttext-segment=ADDR is an alias of --image-base=ADDR, which
+ sets the base address of the ELF executable. */
+ if (update_image_base
+ && link_info.maxpagesize > value
+ && strcmp (segment_name, "text-segment") == 0)
+ value = link_info.maxpagesize;
+
new_rel_from_abs (value);
return;
}
@@ -535,6 +535,15 @@ if { [istarget *-*-linux*]
"pr14525.out" \
"-fPIE" \
] \
+ [list \
+ "Run PR ld/34184 test (static PIE)" \
+ "-pie -Wl,-z,max-page-size=0x800000" \
+ "" \
+ {pr34184.c} \
+ "pr34184-static-pie" \
+ "pass.out" \
+ "-fPIE" \
+ ] \
]
}
@@ -580,6 +589,33 @@ if { [istarget *-*-linux*]
{} \
"-Wl,-R,tmpdir tmpdir/pr32690.so" \
] \
+ [list \
+ "Run PR ld/34184 test (PDE)" \
+ "$NOPIE_LDFLAGS -Wl,-z,max-page-size=0x800000" \
+ "" \
+ {pr34184.c} \
+ "pr34184-pde" \
+ "pass.out" \
+ "$NOPIE_CFLAGS" \
+ ] \
+ [list \
+ "Run PR ld/34184 test (static PDE)" \
+ "-static $NOPIE_LDFLAGS -Wl,-z,max-page-size=0x800000" \
+ "" \
+ {pr34184.c} \
+ "pr34184-static-pde" \
+ "pass.out" \
+ "$NOPIE_CFLAGS" \
+ ] \
+ [list \
+ "Run PR ld/34184 test (PIE)" \
+ "-pie -Wl,-z,max-page-size=0x800000" \
+ "" \
+ {pr34184.c} \
+ "pr34184-pie" \
+ "pass.out" \
+ "-fPIE" \
+ ] \
]
}
new file mode 100644
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int
+main ()
+{
+ printf ("PASS\n");
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,9 @@
+#source: maxpage1.s
+#ld: -shared -z max-page-size=0x800000 -z noseparate-code
+#readelf: -l --wide
+#target: *-*-linux-gnu *-*-gnu* arm*-*-uclinuxfdpiceabi
+#xfail: ![check_shared_lib_support]
+
+#...
+ LOAD +0x0* 0x0* 0x0* 0x[0-9a-f]+ 0x[0-9a-f]+ R E 0x800000
+#pass
@@ -1,4 +1,4 @@
#source: maxpage1.s
-#ld: -Ttext-segment 0x10000 -z max-page-size=0x200000
+#ld: -Ttext-segment 0x200100 -z max-page-size=0x200000
#target: *-*-linux-gnu *-*-gnu* arm*-*-uclinuxfdpiceabi
#warning: .*address of `text-segment' isn't multiple of maximum page size
@@ -1,5 +1,5 @@
#source: maxpage1.s
-#ld: -shared -z max-page-size=0x200000 -Ttext-segment 0x10000
+#ld: -shared -z max-page-size=0x200000 -Ttext-segment 0x200100
#target: *-*-linux-gnu *-*-gnu* arm*-*-uclinuxfdpiceabi
#xfail: ![check_shared_lib_support]
#warning: .*address of `text-segment' isn't multiple of maximum page size
new file mode 100644
@@ -0,0 +1,9 @@
+#source: maxpage1.s
+#ld: -z max-page-size=0x800000 --image-base 0x40000 -z separate-code
+#warning: image base \(0x40000\) < maximum page size \(0x800000\)
+#readelf: -l --wide
+#target: *-*-linux-gnu *-*-gnu* arm*-*-uclinuxfdpiceabi
+
+#...
+ LOAD +0x0* 0x0*800000 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ R [E ] 0x800000
+#pass
new file mode 100644
@@ -0,0 +1,9 @@
+#source: maxpage1.s
+#ld: -shared -z max-page-size=0x800000 --image-base 0x40000 -z noseparate-code
+#readelf: -l --wide
+#target: *-*-linux-gnu *-*-gnu* arm*-*-uclinuxfdpiceabi
+#xfail: ![check_shared_lib_support]
+
+#...
+ LOAD +0x0* 0x0* 0x0* 0x[0-9a-f]+ 0x[0-9a-f]+ R E 0x800000
+#pass
--
2.54.0