[binutils-gdb] RELOC_AGAINST_DISCARDED_SECTION zero size reloc sections

Alan Modra amodra@sourceware.org
Fri Jul 18 23:05:02 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=129cdfc16433bd755c81357bb2f665ca93edb0b4

commit 129cdfc16433bd755c81357bb2f665ca93edb0b4
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Jul 18 09:26:10 2025 +0930

    RELOC_AGAINST_DISCARDED_SECTION zero size reloc sections
    
    For some reason the initial implementation (commit 0672748ac053) of
    this macro didn't allow discarding of all relocs in a section, perhaps
    because doing so would require a testsuite change.  This patch allows
    zero size relocation sections to result, and adjusts the testsuite.
    i386, x86_64, ppc and ppc64 code that avoids a memmove is also changed
    to allow zero size reloc sections, and arc fixed to actually adjust
    the reloc section header.

Diff:
---
 bfd/elf-bfd.h                   | 27 +++++++++++----------------
 bfd/elf32-arc.c                 | 12 ++++++++++++
 bfd/elf32-i386.c                |  8 --------
 bfd/elf32-ppc.c                 |  9 ---------
 bfd/elf64-ppc.c                 |  8 --------
 bfd/elf64-x86-64.c              |  8 --------
 ld/testsuite/ld-elf/linkonce1.d |  5 ++---
 7 files changed, 25 insertions(+), 52 deletions(-)

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index fbb1cd9e890..c02e34e75ba 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -3287,25 +3287,20 @@ extern asection _bfd_elf_large_com_section;
 	&& ((input_section->flags & SEC_DEBUGGING) != 0			\
 	    || elf_section_type (input_section) == SHT_GNU_SFRAME))	\
       {									\
-	Elf_Internal_Shdr *rel_hdr;					\
+	Elf_Internal_Shdr *rel_hdr					\
+	  = _bfd_elf_single_rel_hdr (input_section->output_section);	\
 									\
-	rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section); \
+	rel_hdr->sh_size -= rel_hdr->sh_entsize;			\
+	rel_hdr = _bfd_elf_single_rel_hdr (input_section);		\
+	rel_hdr->sh_size -= rel_hdr->sh_entsize;			\
 									\
-	/* Avoid empty output section.  */				\
-	if (rel_hdr->sh_size > rel_hdr->sh_entsize)			\
-	  {								\
-	    rel_hdr->sh_size -= rel_hdr->sh_entsize;			\
-	    rel_hdr = _bfd_elf_single_rel_hdr (input_section);		\
-	    rel_hdr->sh_size -= rel_hdr->sh_entsize;			\
+	memmove (rel, rel + count,					\
+		 (relend - rel - count) * sizeof (*rel));		\
 									\
-	    memmove (rel, rel + count,					\
-		     (relend - rel - count) * sizeof (*rel));		\
-									\
-	    input_section->reloc_count -= count;			\
-	    relend -= count;						\
-	    rel--;							\
-	    continue;							\
-	  }								\
+	input_section->reloc_count -= count;				\
+	relend -= count;						\
+	rel--;								\
+	continue;							\
       }									\
 									\
     for (int i_ = 0; i_ < count; i_++)					\
diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c
index 0a6e66569ba..a78516dc12f 100644
--- a/bfd/elf32-arc.c
+++ b/bfd/elf32-arc.c
@@ -1947,6 +1947,18 @@ elf_arc_relocate_section (bfd *			  output_bfd,
       return false;
     }
 
+  if (wrel != rel)
+    {
+      Elf_Internal_Shdr *rel_hdr;
+      size_t deleted = rel - wrel;
+
+      rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section);
+      rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
+      rel_hdr = _bfd_elf_single_rel_hdr (input_section);
+      rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
+      input_section->reloc_count -= deleted;
+    }
+
   return true;
 }
 
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index b417cb0d67a..abe26e476ff 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -3600,14 +3600,6 @@ elf_i386_relocate_section (bfd *output_bfd,
 
       rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section);
       rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
-      if (rel_hdr->sh_size == 0)
-	{
-	  /* It is too late to remove an empty reloc section.  Leave
-	     one NONE reloc.
-	     ??? What is wrong with an empty section???  */
-	  rel_hdr->sh_size = rel_hdr->sh_entsize;
-	  deleted -= 1;
-	}
       rel_hdr = _bfd_elf_single_rel_hdr (input_section);
       rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
       input_section->reloc_count -= deleted;
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index f17effdf176..3fd9f28cd52 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -9142,15 +9142,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
       rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section);
       rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
-      if (rel_hdr->sh_size == 0)
-	{
-	  /* It is too late to remove an empty reloc section.  Leave
-	     one NONE reloc.
-	     ??? What is wrong with an empty section???  */
-	  rel_hdr->sh_size = rel_hdr->sh_entsize;
-	  deleted -= 1;
-	  wrel++;
-	}
       relend = wrel;
       rel_hdr = _bfd_elf_single_rel_hdr (input_section);
       rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 00c1c32ffd2..e6c90a68b82 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -18082,14 +18082,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
       rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section);
       rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
-      if (rel_hdr->sh_size == 0)
-	{
-	  /* It is too late to remove an empty reloc section.  Leave
-	     one NONE reloc.
-	     ??? What is wrong with an empty section???  */
-	  rel_hdr->sh_size = rel_hdr->sh_entsize;
-	  deleted -= 1;
-	}
       rel_hdr = _bfd_elf_single_rel_hdr (input_section);
       rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
       input_section->reloc_count -= deleted;
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index ebd2eb4299f..b6f97b5b69b 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -5099,14 +5099,6 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 
       rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section);
       rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
-      if (rel_hdr->sh_size == 0)
-	{
-	  /* It is too late to remove an empty reloc section.  Leave
-	     one NONE reloc.
-	     ??? What is wrong with an empty section???  */
-	  rel_hdr->sh_size = rel_hdr->sh_entsize;
-	  deleted -= 1;
-	}
       rel_hdr = _bfd_elf_single_rel_hdr (input_section);
       rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
       input_section->reloc_count -= deleted;
diff --git a/ld/testsuite/ld-elf/linkonce1.d b/ld/testsuite/ld-elf/linkonce1.d
index e4f9a70826f..654171dc7a6 100644
--- a/ld/testsuite/ld-elf/linkonce1.d
+++ b/ld/testsuite/ld-elf/linkonce1.d
@@ -2,11 +2,10 @@
 #source: linkonce1b.s
 #ld: -r
 #objdump: -r
+#xfail: [is_generic]
 
 .*:     file format .*
 #...
-RELOCATION RECORDS FOR \[.debug_frame\]:
-OFFSET[ 	]+TYPE[ 	]+VALUE[ 	]*
-.*(NONE|unused|UNUSED).*\*ABS\*
+RELOCATION RECORDS FOR \[.debug_frame\]: \(none\)
 
 #pass


More information about the Binutils-cvs mailing list