sh: handle Linux core notes in the generic ELF vector

Message ID 20260926041603.736177-1-mattst88@gmail.com
State New
Headers
Series sh: handle Linux core notes in the generic ELF vector |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

Matt Turner Sept. 26, 2026, 4:16 a.m. UTC
  A Linux sh core file matches elf32-shl, elf32-sh-linux, elf32-shl-nbsd
and elf32-shl-vxworks with equal priority, and bfd_check_format_matches
picks the first, elf32-shl. Only the Linux vector handled NT_PRSTATUS
and NT_PRPSINFO notes, so the core had no .reg section and gdb found no
registers.

Handle the notes in the generic vector, which the NetBSD, Linux and
FDPIC vectors inherit. VxWorks still undefines them.

	PR 34676
---
 bfd/elf32-sh.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
  

Comments

Alan Modra Sept. 30, 2026, 2:26 a.m. UTC | #1
On Sat, Sep 26, 2026 at 12:16:03AM -0400, Matt Turner wrote:
> A Linux sh core file matches elf32-shl, elf32-sh-linux, elf32-shl-nbsd
> and elf32-shl-vxworks with equal priority, and bfd_check_format_matches
> picks the first, elf32-shl. Only the Linux vector handled NT_PRSTATUS
> and NT_PRPSINFO notes, so the core had no .reg section and gdb found no
> registers.
> 
> Handle the notes in the generic vector, which the NetBSD, Linux and
> FDPIC vectors inherit. VxWorks still undefines them.
> 
> 	PR 34676

This seems a hack to me, despite being used elsewhere.  Ideally we'd
choose the correct target.  Please test the following.

This patch aims to improve core file support in cases where binutils
was configured with the target needed to interpret notes not being the
default target.  In such cases multiple targets may match the object
file with nothing to choose between them.  As per the PR, elf32-shl,
elf32-sh-linux, elf32-shl-nbsd and elf32-shl-vxworks all match with
the same priority, but only elf32-sh-linux interprets NT_PRSTATUS and
creates a .reg section.

	PR 34676
	* format.c (bfd_check_format_matches): Prefer higher section
	count targets if all else is equivalent.

diff --git a/bfd/format.c b/bfd/format.c
index 9e597877084..a99c2d8f01b 100644
--- a/bfd/format.c
+++ b/bfd/format.c
@@ -450,7 +450,8 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
   const bfd_target **matching_vector;
   const bfd_target *save_targ, *right_targ, *ar_right_targ, *match_targ;
   const bfd_target *fail_targ;
-  int match_count, best_count, best_match;
+  int match_count, best_count;
+  unsigned int best_match;
   int ar_match_index;
   unsigned int initial_section_id;
   struct bfd_preserve preserve, preserve_match;
@@ -566,7 +567,7 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
   right_targ = NULL;
   ar_right_targ = NULL;
   match_targ = NULL;
-  best_match = 256;
+  best_match = -1u;
   best_count = 0;
   match_count = 0;
   ar_match_index = _bfd_target_vector_entries;
@@ -634,7 +635,7 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
 	      matching_vector[match_count] = abfd->xvec;
 	      match_count++;
 
-	      int match_priority = abfd->xvec->match_priority;
+	      unsigned int match_priority = abfd->xvec->match_priority;
 	      if (match_priority == 1
 		  && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
 		{
@@ -646,6 +647,12 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
 		      && i_ehdrp->e_ident[EI_OSABI] == bed->elf_osabi)
 		    match_priority = 0;
 		}
+	      match_priority <<= 16;
+	      /* A target that produces more sections is given a higher
+		 priority (smaller values of match_priority are higher
+		 priority) in order to prefer targets that decode note
+		 sections.  */
+	      match_priority |= (0xffff - abfd->section_count) & 0xffff;
 	      if (match_priority < best_match)
 		{
 		  best_match = match_priority;
@@ -715,7 +722,7 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
 
 	  while (--i >= 0)
 	    if (matching_vector[i] == right_targ
-		&& right_targ->match_priority <= best_match)
+		&& right_targ->match_priority <= best_match >> 16)
 	      break;
 
 	  if (i >= 0)
@@ -736,7 +743,7 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
       for (i = 0; i < match_count; i++)
 	{
 	  right_targ = matching_vector[i];
-	  if (right_targ->match_priority <= best_match)
+	  if (right_targ->match_priority <= best_match >> 16)
 	    break;
 	}
       match_count = 1;
  
Matt Turner Sept. 30, 2026, 8:38 p.m. UTC | #2
On Tue, Sep 29, 2026 at 10:26 PM Alan Modra <amodra@gmail.com> wrote:
>
> On Sat, Sep 26, 2026 at 12:16:03AM -0400, Matt Turner wrote:
> > A Linux sh core file matches elf32-shl, elf32-sh-linux, elf32-shl-nbsd
> > and elf32-shl-vxworks with equal priority, and bfd_check_format_matches
> > picks the first, elf32-shl. Only the Linux vector handled NT_PRSTATUS
> > and NT_PRPSINFO notes, so the core had no .reg section and gdb found no
> > registers.
> >
> > Handle the notes in the generic vector, which the NetBSD, Linux and
> > FDPIC vectors inherit. VxWorks still undefines them.
> >
> >       PR 34676
>
> This seems a hack to me, despite being used elsewhere.  Ideally we'd
> choose the correct target.  Please test the following.

Thanks, that works. With --enable-targets=all on x86_64, and your
patch instead of mine, a qemu-sh4 Linux core is now recognized as
elf32-sh-linux, has a .reg section, and gdb reads the registers and
gives a full backtrace.

A few small things I noticed:

- The associated vector loop and the "first of the best matches" loop
  only compare best_match >> 16, so if more than one target shares
  the best priority and section count, they can still pick a target
  with fewer sections.

- (0xffff - abfd->section_count) & 0xffff wraps for files with more
  than 65535 sections. Probably harmless?

- If the default vector matches, we return before any of this, so an
  sh-elf toolchain opening a Linux core still gets elf32-shl. That
  seems unlikely to matter in practice.

Anyway, this looks good to me. Thank you!
  
Alan Modra Oct. 1, 2026, 6:17 a.m. UTC | #3
On Wed, Sep 30, 2026 at 04:38:09PM -0400, Matt Turner wrote:
> On Tue, Sep 29, 2026 at 10:26 PM Alan Modra <amodra@gmail.com> wrote:
> >
> > On Sat, Sep 26, 2026 at 12:16:03AM -0400, Matt Turner wrote:
> > > A Linux sh core file matches elf32-shl, elf32-sh-linux, elf32-shl-nbsd
> > > and elf32-shl-vxworks with equal priority, and bfd_check_format_matches
> > > picks the first, elf32-shl. Only the Linux vector handled NT_PRSTATUS
> > > and NT_PRPSINFO notes, so the core had no .reg section and gdb found no
> > > registers.
> > >
> > > Handle the notes in the generic vector, which the NetBSD, Linux and
> > > FDPIC vectors inherit. VxWorks still undefines them.
> > >
> > >       PR 34676
> >
> > This seems a hack to me, despite being used elsewhere.  Ideally we'd
> > choose the correct target.  Please test the following.
> 
> Thanks, that works. With --enable-targets=all on x86_64, and your
> patch instead of mine, a qemu-sh4 Linux core is now recognized as
> elf32-sh-linux, has a .reg section, and gdb reads the registers and
> gives a full backtrace.
> 
> A few small things I noticed:
> 
> - The associated vector loop and the "first of the best matches" loop
>   only compare best_match >> 16, so if more than one target shares
>   the best priority and section count, they can still pick a target
>   with fewer sections.

That's true, but I figure we'll deal with that if it becomes a real
problem.  For anyone reading this thread and wondering what this is
about, if for example elf32-shl-nbsd and elf32-sh-linux both
interpreted the core file SHT_NOTE section and produced a .reg section
for the prstatus note, then we would have two "best" targets and the
main loop wouldn't know which one to choose.  The last tie-breaker
loop might choose elf32-shl even though that target didn't interpret
the SHT_NOTE section.  This is only a hypothetical as elf32-shl-nbsd
won't interpret the SHT_NOTE section.

> - (0xffff - abfd->section_count) & 0xffff wraps for files with more
>   than 65535 sections. Probably harmless?

I think we are unlikely to exceed the limit in core files, but it may
be better to write
	      if (abfd->section_count < 0xffff)
		match_priority |= 0xffff - abfd->section_count;
I'll update the patch.

> - If the default vector matches, we return before any of this, so an
>   sh-elf toolchain opening a Linux core still gets elf32-shl. That
>   seems unlikely to matter in practice.
> 
> Anyway, this looks good to me. Thank you!

Thanks for reviewing!
  

Patch

diff --git ./bfd/elf32-sh.c ./bfd/elf32-sh.c
index 1b111f3611b..ca1b708d737 100644
--- ./bfd/elf32-sh.c
+++ ./bfd/elf32-sh.c
@@ -6628,6 +6628,8 @@  sh_elf_encode_eh_address (bfd *abfd,
 #define elf_backend_dtrel_excludes_plt	1
 
 #define elf_backend_linux_prpsinfo32_ugid16	true
+#define elf_backend_grok_prstatus	elf32_shlin_grok_prstatus
+#define elf_backend_grok_psinfo		elf32_shlin_grok_psinfo
 
 #if !defined SH_TARGET_ALREADY_DEFINED
 
@@ -6665,10 +6667,6 @@  sh_elf_encode_eh_address (bfd *abfd,
 #undef	ELF_COMMONPAGESIZE
 #define	ELF_COMMONPAGESIZE		0x1000
 
-#undef	elf_backend_grok_prstatus
-#define	elf_backend_grok_prstatus	elf32_shlin_grok_prstatus
-#undef	elf_backend_grok_psinfo
-#define	elf_backend_grok_psinfo		elf32_shlin_grok_psinfo
 #undef	elf32_bed
 #define	elf32_bed			elf32_sh_lin_bed