[binutils-gdb] elf: Set image base address to the maximum page size
"H.J. Lu via Binutils-cvs" <[email protected]> Mon, 29 Jun 2026 23:53:38 +0000 (GMT)
| Newsgroups | gmane.comp.gnu.binutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6286d4a211871078952fd51282f53f7f9626956f commit 6286d4a211871078952fd51282f53f7f9626956f Author: H.J. Lu <[email protected]> Date: Thu May 28 10:47:37 2026 +0800 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 <[email protected]> Diff: --- 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(-) diff --git a/ld/ldexp.c b/ld/ldexp.c index 7bda6acc4c9..19542ad99c6 100644 --- a/ld/ldexp.c +++ b/ld/ldexp.c @@ -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; } diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp index 8fca30dbeeb..51b8c942648 100644 --- a/ld/testsuite/ld-elf/elf.exp +++ b/ld/testsuite/ld-elf/elf.exp @@ -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" \ + ] \ ] } diff --git a/ld/testsuite/ld-elf/pr34184.c b/ld/testsuite/ld-elf/pr34184.c new file mode 100644 index 00000000000..8fb892c6aaa --- /dev/null +++ b/ld/testsuite/ld-elf/pr34184.c @@ -0,0 +1,8 @@ +#include <stdio.h> + +int +main () +{ + printf ("PASS\n"); + return 0; +} diff --git a/ld/testsuite/ld-elf/textaddr10.d b/ld/testsuite/ld-elf/textaddr10.d new file mode 100644 index 00000000000..570aeb74b4f --- /dev/null +++ b/ld/testsuite/ld-elf/textaddr10.d @@ -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 diff --git a/ld/testsuite/ld-elf/textaddr3.d b/ld/testsuite/ld-elf/textaddr3.d index 3796b7dcb98..284d5a47015 100644 --- a/ld/testsuite/ld-elf/textaddr3.d +++ b/ld/testsuite/ld-elf/textaddr3.d @@ -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 diff --git a/ld/testsuite/ld-elf/textaddr5.d b/ld/testsuite/ld-elf/textaddr5.d index ab1097f40cf..1f65c5136e0 100644 --- a/ld/testsuite/ld-elf/textaddr5.d +++ b/ld/testsuite/ld-elf/textaddr5.d @@ -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 diff --git a/ld/testsuite/ld-elf/textaddr8.d b/ld/testsuite/ld-elf/textaddr8.d new file mode 100644 index 00000000000..1d8607c1d59 --- /dev/null +++ b/ld/testsuite/ld-elf/textaddr8.d @@ -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 diff --git a/ld/testsuite/ld-elf/textaddr9.d b/ld/testsuite/ld-elf/textaddr9.d new file mode 100644 index 00000000000..29b13879a1d --- /dev/null +++ b/ld/testsuite/ld-elf/textaddr9.d @@ -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