mips: Assert dynamic symbol counts only with dynamic sections

Message ID CAMe9rOotgDmy9B3eGXZ8QuhrJmAGWaQUyP8aw2yhpzy-SDM8QA@mail.gmail.com
State New
Headers
Series mips: Assert dynamic symbol counts only with dynamic sections |

Commit Message

H.J. Lu Nov. 30, 2025, 7:50 a.m. UTC
  On Sun, Nov 30, 2025 at 11:10 AM Alan Modra <amodra@gmail.com> wrote:
>
> OK.
>

After

commit 54fbc12d6404b645363f901110a21f4410067df5
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Nov 28 16:07:57 2025 +0800

    elf: Renumber local dynamic symbols only if needed

mips-linux got

FAIL: MIPS magic __ehdr_start symbol test 1 (o32)
FAIL: PR ld/21334 MIPS GOT16 relocation in static binary

with assertion failures on

BFD_ASSERT (hsd.max_local_dynindx <= htab->root.local_dynsymcount + 1);

Since there are dynamic symbols only if there are dynamic sections,
assert dynamic symbol counts only if there are dynamic sections.

* elfxx-mips.c (mips_elf_sort_hash_table): Assert dynamic symbol
counts only if there are dynamic sections.
  

Comments

Alan Modra Nov. 30, 2025, 10:50 p.m. UTC | #1
On Sun, Nov 30, 2025 at 03:50:39PM +0800, H.J. Lu wrote:
>     elf: Renumber local dynamic symbols only if needed
> 
> mips-linux got
> 
> FAIL: MIPS magic __ehdr_start symbol test 1 (o32)
> FAIL: PR ld/21334 MIPS GOT16 relocation in static binary

That commit broke hppa64-linux too.

hppa64-linux-gnu  +FAIL: -u --export-dynamic-symbol foo archive
hppa64-linux-gnu  +FAIL: strip -shared (maxpage1)
hppa64-linux-gnu  +FAIL: objcopy -shared (maxpage1)
hppa64-linux-gnu  +FAIL: ld-elf/mbind1b
hppa64-linux-gnu  +FAIL: ld-elf/pr19617a
hppa64-linux-gnu  +FAIL: ld-elf/pr21384
hppa64-linux-gnu  +FAIL: ld-elf/pr21389a
hppa64-linux-gnu  +FAIL: ld-elf/pr21389b
hppa64-linux-gnu  +FAIL: ld-elf/pr21562e
hppa64-linux-gnu  +FAIL: ld-elf/pr21562f
hppa64-linux-gnu  +FAIL: ld-elf/pr21562g
hppa64-linux-gnu  +FAIL: ld-elf/pr21562h
hppa64-linux-gnu  +FAIL: ld-elf/pr21903a
hppa64-linux-gnu  +FAIL: ld-elf/pr21903b
hppa64-linux-gnu  +FAIL: ld-elf/pr23658-1c
hppa64-linux-gnu  +FAIL: ld-elf/pr23658-1f
hppa64-linux-gnu  +FAIL: ld-elf/pr24511
hppa64-linux-gnu  +FAIL: ld-elf/pr26979a
hppa64-linux-gnu  +FAIL: ld-elf/pr26979b
hppa64-linux-gnu  +FAIL: ld-elf/pr33291
hppa64-linux-gnu  +FAIL: ld-elf/pr33599
hppa64-linux-gnu  +FAIL: ld-elf/sizeofb
hppa64-linux-gnu  +FAIL: ld-elf/startofb
hppa64-linux-gnu  +FAIL: ld-elf/textaddr2
hppa64-linux-gnu  +FAIL: ld-elf/textaddr5
hppa64-linux-gnu  +FAIL: ld-elf/textaddr6
hppa64-linux-gnu  +FAIL: Symbol export class test (auxiliary shared object)
hppa64-linux-gnu  +FAIL: objcopy --strip-section-headers --hash-style=sysv -shared (start)
hppa64-linux-gnu  +FAIL: strip --strip-section-headers --hash-style=sysv -shared (start)
hppa64-linux-gnu  -FAIL: readelf version information
hppa64-linux-gnu  +FAIL: Build pr22649-1.so
hppa64-linux-gnu  +FAIL: Build shared library for pr14170
hppa64-linux-gnu  +FAIL: Build shared library for broken linker script test
hppa64-linux-gnu  +FAIL: Build pr17068.so
hppa64-linux-gnu  +FAIL: pr17068 link --as-needed lib in group
hppa64-linux-gnu  +FAIL: Build pr20995.so
hppa64-linux-gnu  +FAIL: Weak symbols in dynamic objects 1 (support)
hppa64-linux-gnu  +FAIL: Weak symbols in dynamic objects 1 (main test)
  
H.J. Lu Nov. 30, 2025, 11:13 p.m. UTC | #2
On Mon, Dec 1, 2025 at 6:50 AM Alan Modra <amodra@gmail.com> wrote:
>
> On Sun, Nov 30, 2025 at 03:50:39PM +0800, H.J. Lu wrote:
> >     elf: Renumber local dynamic symbols only if needed
> >
> > mips-linux got
> >
> > FAIL: MIPS magic __ehdr_start symbol test 1 (o32)
> > FAIL: PR ld/21334 MIPS GOT16 relocation in static binary
>
> That commit broke hppa64-linux too.
>
> hppa64-linux-gnu  +FAIL: -u --export-dynamic-symbol foo archive
> hppa64-linux-gnu  +FAIL: strip -shared (maxpage1)
> hppa64-linux-gnu  +FAIL: objcopy -shared (maxpage1)
> hppa64-linux-gnu  +FAIL: ld-elf/mbind1b
> hppa64-linux-gnu  +FAIL: ld-elf/pr19617a
> hppa64-linux-gnu  +FAIL: ld-elf/pr21384
> hppa64-linux-gnu  +FAIL: ld-elf/pr21389a
> hppa64-linux-gnu  +FAIL: ld-elf/pr21389b
> hppa64-linux-gnu  +FAIL: ld-elf/pr21562e
> hppa64-linux-gnu  +FAIL: ld-elf/pr21562f
> hppa64-linux-gnu  +FAIL: ld-elf/pr21562g
> hppa64-linux-gnu  +FAIL: ld-elf/pr21562h
> hppa64-linux-gnu  +FAIL: ld-elf/pr21903a
> hppa64-linux-gnu  +FAIL: ld-elf/pr21903b
> hppa64-linux-gnu  +FAIL: ld-elf/pr23658-1c
> hppa64-linux-gnu  +FAIL: ld-elf/pr23658-1f
> hppa64-linux-gnu  +FAIL: ld-elf/pr24511
> hppa64-linux-gnu  +FAIL: ld-elf/pr26979a
> hppa64-linux-gnu  +FAIL: ld-elf/pr26979b
> hppa64-linux-gnu  +FAIL: ld-elf/pr33291
> hppa64-linux-gnu  +FAIL: ld-elf/pr33599
> hppa64-linux-gnu  +FAIL: ld-elf/sizeofb
> hppa64-linux-gnu  +FAIL: ld-elf/startofb
> hppa64-linux-gnu  +FAIL: ld-elf/textaddr2
> hppa64-linux-gnu  +FAIL: ld-elf/textaddr5
> hppa64-linux-gnu  +FAIL: ld-elf/textaddr6
> hppa64-linux-gnu  +FAIL: Symbol export class test (auxiliary shared object)
> hppa64-linux-gnu  +FAIL: objcopy --strip-section-headers --hash-style=sysv -shared (start)
> hppa64-linux-gnu  +FAIL: strip --strip-section-headers --hash-style=sysv -shared (start)
> hppa64-linux-gnu  -FAIL: readelf version information
> hppa64-linux-gnu  +FAIL: Build pr22649-1.so
> hppa64-linux-gnu  +FAIL: Build shared library for pr14170
> hppa64-linux-gnu  +FAIL: Build shared library for broken linker script test
> hppa64-linux-gnu  +FAIL: Build pr17068.so
> hppa64-linux-gnu  +FAIL: pr17068 link --as-needed lib in group
> hppa64-linux-gnu  +FAIL: Build pr20995.so
> hppa64-linux-gnu  +FAIL: Weak symbols in dynamic objects 1 (support)
> hppa64-linux-gnu  +FAIL: Weak symbols in dynamic objects 1 (main test)
>
> --
> Alan Modra

How can I reproduce it?  I only got

FAIL: ld-elf/pr19539
FAIL: ld-elf/pr19617a
FAIL: PR ld/22269
FAIL: PR ld/22269 (-z dynamic-undefined-weak)
FAIL: objcopy --strip-section-headers --hash-style=sysv -shared (start)
FAIL: strip --strip-section-headers --hash-style=sysv -shared (start)
FAIL: ld-elf/64ksec
FAIL: DT_TEXTREL in shared lib
FAIL: DT_TEXTREL map file warning
FAIL: Build shared library for broken linker script test
FAIL: Link using broken linker script
FAIL: pr17068 link --as-needed lib in group
FAIL: pr20995

with hppa64-linux-gnu cross binutils.
  
Alan Modra Dec. 1, 2025, 1:27 a.m. UTC | #3
On Mon, Dec 01, 2025 at 07:13:00AM +0800, H.J. Lu wrote:
> How can I reproduce it?  I only got

~/src/binutils-gdb/configure \
--disable-nls \
--disable-gdb --disable-gdbserver --disable-sim --disable-readline \
--disable-libbacktrace --disable-libdecnumber --disable-gprofng \
--enable-obsolete --target=hppa64-linux-gnu

Here's an example of a failing test

../gas/as-new   -I/home/alan/src/binutils-gdb/ld/testsuite/ld-elf   -o tmpdir/maxpage1.o /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/maxpage1.s
./ld-new   -o tmpdir/maxpage1 -shared -z stack-size=0 tmpdir/maxpage1.o
corrupted size vs. prev_size
Aborted (core dumped)

FAIL: strip -shared (maxpage1)
  
Alan Modra Dec. 1, 2025, 1:36 a.m. UTC | #4
On Mon, Dec 01, 2025 at 11:57:44AM +1030, Alan Modra wrote:
> On Mon, Dec 01, 2025 at 07:13:00AM +0800, H.J. Lu wrote:
> > How can I reproduce it?  I only got
> 
> ~/src/binutils-gdb/configure \
> --disable-nls \
> --disable-gdb --disable-gdbserver --disable-sim --disable-readline \
> --disable-libbacktrace --disable-libdecnumber --disable-gprofng \
> --enable-obsolete --target=hppa64-linux-gnu
> 
> Here's an example of a failing test
> 
> ../gas/as-new   -I/home/alan/src/binutils-gdb/ld/testsuite/ld-elf   -o tmpdir/maxpage1.o /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/maxpage1.s
> ./ld-new   -o tmpdir/maxpage1 -shared -z stack-size=0 tmpdir/maxpage1.o
> corrupted size vs. prev_size
> Aborted (core dumped)
> 
> FAIL: strip -shared (maxpage1)

A sanitizer build shows this is due to a buffer overflow at
bfd/elflink.c:6504 in elf_collect_hash_codes.
  
H.J. Lu Dec. 1, 2025, 2:18 a.m. UTC | #5
On Mon, Dec 1, 2025 at 9:27 AM Alan Modra <amodra@gmail.com> wrote:
>
> On Mon, Dec 01, 2025 at 07:13:00AM +0800, H.J. Lu wrote:
> > How can I reproduce it?  I only got
>
> ~/src/binutils-gdb/configure \
> --disable-nls \
> --disable-gdb --disable-gdbserver --disable-sim --disable-readline \
> --disable-libbacktrace --disable-libdecnumber --disable-gprofng \
> --enable-obsolete --target=hppa64-linux-gnu

I used a similar configuration with GCC 15.  Which compiler did you use?

> Here's an example of a failing test
>
> ../gas/as-new   -I/home/alan/src/binutils-gdb/ld/testsuite/ld-elf   -o tmpdir/maxpage1.o /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/maxpage1.s
> ./ld-new   -o tmpdir/maxpage1 -shared -z stack-size=0 tmpdir/maxpage1.o
> corrupted size vs. prev_size
> Aborted (core dumped)
>
> FAIL: strip -shared (maxpage1)
>
> --
> Alan Modra
  
H.J. Lu Dec. 1, 2025, 2:49 a.m. UTC | #6
On Mon, Dec 1, 2025 at 9:36 AM Alan Modra <amodra@gmail.com> wrote:
>
> On Mon, Dec 01, 2025 at 11:57:44AM +1030, Alan Modra wrote:
> > On Mon, Dec 01, 2025 at 07:13:00AM +0800, H.J. Lu wrote:
> > > How can I reproduce it?  I only got
> >
> > ~/src/binutils-gdb/configure \
> > --disable-nls \
> > --disable-gdb --disable-gdbserver --disable-sim --disable-readline \
> > --disable-libbacktrace --disable-libdecnumber --disable-gprofng \
> > --enable-obsolete --target=hppa64-linux-gnu
> >
> > Here's an example of a failing test
> >
> > ../gas/as-new   -I/home/alan/src/binutils-gdb/ld/testsuite/ld-elf   -o tmpdir/maxpage1.o /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/maxpage1.s
> > ./ld-new   -o tmpdir/maxpage1 -shared -z stack-size=0 tmpdir/maxpage1.o
> > corrupted size vs. prev_size
> > Aborted (core dumped)
> >
> > FAIL: strip -shared (maxpage1)
>
> A sanitizer build shows this is due to a buffer overflow at
> bfd/elflink.c:6504 in elf_collect_hash_codes.

I used --enable-default-hash-style=gnu.  Remove it reproduced the error.

> --
> Alan Modra
  
Alan Modra Dec. 2, 2025, 12:48 a.m. UTC | #7
The mips patch looks wrong to me.  Why is mips_elf_sort_hash_table
even doing anything?  Oh, the test htab->root.dynsymcount == 0 should
be htab->root.dynsymcount <= 1, because dynsymcount is initialised to
1 in _bfd_elf_link_hash_table_init.

I'll apply that fix.
  
Maciej W. Rozycki Dec. 2, 2025, 4:11 a.m. UTC | #8
On Tue, 2 Dec 2025, Alan Modra wrote:

> The mips patch looks wrong to me.  Why is mips_elf_sort_hash_table
> even doing anything?  Oh, the test htab->root.dynsymcount == 0 should
> be htab->root.dynsymcount <= 1, because dynsymcount is initialised to
> 1 in _bfd_elf_link_hash_table_init.
> 
> I'll apply that fix.

 Yeah, it seems to me like the right fix.  Thank you for looking into it.

  Maciej
  

Patch

From e63ad8aeb72c21a00397d2366cb89d65e638b39c Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sun, 30 Nov 2025 15:32:53 +0800
Subject: [PATCH] mips: Assert dynamic symbol counts only with dynamic sections

After

commit 54fbc12d6404b645363f901110a21f4410067df5
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Nov 28 16:07:57 2025 +0800

    elf: Renumber local dynamic symbols only if needed

mips-linux got

FAIL: MIPS magic __ehdr_start symbol test 1 (o32)
FAIL: PR ld/21334 MIPS GOT16 relocation in static binary

with assertion failures on

BFD_ASSERT (hsd.max_local_dynindx <= htab->root.local_dynsymcount + 1);

Since there are dynamic symbols only if there are dynamic sections,
assert dynamic symbol counts only if there are dynamic sections.

	* elfxx-mips.c (mips_elf_sort_hash_table): Assert dynamic symbol
	counts only if there are dynamic sections.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 bfd/elfxx-mips.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index e37c45fec15..fe896839d76 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -4034,12 +4034,15 @@  mips_elf_sort_hash_table (bfd *abfd, struct bfd_link_info *info)
     hsd.mipsxhash = NULL;
   mips_elf_link_hash_traverse (htab, mips_elf_sort_hash_table_f, &hsd);
 
-  /* There should have been enough room in the symbol table to
-     accommodate both the GOT and non-GOT symbols.  */
-  BFD_ASSERT (hsd.max_local_dynindx <= htab->root.local_dynsymcount + 1);
-  BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx);
-  BFD_ASSERT (hsd.max_unref_got_dynindx == htab->root.dynsymcount);
-  BFD_ASSERT (htab->root.dynsymcount - hsd.min_got_dynindx == g->global_gotno);
+  if (htab->root.dynamic_sections_created)
+    {
+      /* There should have been enough room in the symbol table to
+	 accommodate both the GOT and non-GOT symbols.  */
+      BFD_ASSERT (hsd.max_local_dynindx <= htab->root.local_dynsymcount + 1);
+      BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx);
+      BFD_ASSERT (hsd.max_unref_got_dynindx == htab->root.dynsymcount);
+      BFD_ASSERT (htab->root.dynsymcount - hsd.min_got_dynindx == g->global_gotno);
+    }
 
   /* Now we know which dynamic symbol has the lowest dynamic symbol
      table index in the GOT.  */
-- 
2.52.0