Re: [PATCH v3 1/1] aarch64: mingw: Prevent relocation types from being overwritten

Alan Modra <[email protected]> Thu, 23 Jul 2026 13:07:28 +0930
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
On Wed, Jul 22, 2026 at 10:34:08PM +0930, Alan Modra wrote:
> Firstly, is it really necessary?  What exactly goes wrong with the
> current code?

I am asking for some details on the following statement:

> On Wed, Jul 22, 2026 at 01:04:00PM +0200, Evgeny Karpov wrote:
> > However, it impacts another relocation logic, as the initial relocation type
> > is no longer known.

This is the patch I'll commit if you convince me.
===

Add a means of controlling _bfd_coff_generic_relocate_section for
cases where a backend relocate_section has already handled the reloc.

include/
	* coff/internal.h (struct internal_reloc): Reorganise.  Make
	r_type, r_size and r_extern bitfields.  Add r_ignore bitfield.
bfd/
	* coff-alpha.c (alpha_ecoff_swap_reloc_in): Init all fields of
	struct internal_reloc.
	* coff-mips.c (mips_ecoff_swap_reloc_in): Likewise.  Remove
	unnecessary casts.
	* coffswap.h (coff_swap_reloc_in): Likewise.
	* peicode.h (coff_swap_reloc_in): Likewise.
	* coffcode.h (coff_slurp_reloc_table): Don't clear r_offset.
	* cofflink.c (_bfd_coff_generic_relocate_section): Skip relocs
	with r_ignore set.

diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c
index f0823cdcaa9..dd1208ab064 100644
--- a/bfd/coff-alpha.c
+++ b/bfd/coff-alpha.c
@@ -496,6 +496,7 @@ alpha_ecoff_swap_reloc_in (bfd *abfd,
 {
   const RELOC *ext = ext_ptr;
 
+  memset (intern, 0, sizeof (*intern));
   intern->r_vaddr = H_GET_64 (abfd, ext->r_vaddr);
   intern->r_symndx = H_GET_32 (abfd, ext->r_symndx);
 
diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c
index da7a666cebc..d5fc416bf58 100644
--- a/bfd/coff-mips.c
+++ b/bfd/coff-mips.c
@@ -272,8 +272,9 @@ mips_ecoff_swap_reloc_in (bfd *  abfd,
 			  void * ext_ptr,
 			  struct internal_reloc *intern)
 {
-  const RELOC *ext = (RELOC *) ext_ptr;
+  const RELOC *ext = ext_ptr;
 
+  memset (intern, 0, sizeof (*intern));
   intern->r_vaddr = H_GET_32 (abfd, ext->r_vaddr);
   if (bfd_header_big_endian (abfd))
     {
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 267c6ce2782..964d2c3e173 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -5315,7 +5315,6 @@ coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols)
       cache_ptr = reloc_cache + idx;
       src = native_relocs + idx * (size_t) bfd_coff_relsz (abfd);
 
-      dst.r_offset = 0;
       bfd_coff_swap_reloc_in (abfd, src, &dst);
 
 #ifdef RELOC_PROCESSING
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index d029bec1678..ae03ba855b2 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -3113,6 +3113,9 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
       reloc_howto_type *howto;
       bfd_reloc_status_type rstat;
 
+      if (rel->r_ignore)
+	continue;
+
       symndx = rel->r_symndx;
 
       if (symndx == -1)
diff --git a/bfd/coffswap.h b/bfd/coffswap.h
index ffc662036b7..655a4b4817f 100644
--- a/bfd/coffswap.h
+++ b/bfd/coffswap.h
@@ -214,9 +214,10 @@
 static void
 coff_swap_reloc_in (bfd * abfd, void * src, void * dst)
 {
-  RELOC *reloc_src = (RELOC *) src;
-  struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
+  RELOC *reloc_src = src;
+  struct internal_reloc *reloc_dst = dst;
 
+  memset (reloc_dst, 0, sizeof (*reloc_dst));
   reloc_dst->r_vaddr  = GET_RELOC_VADDR (abfd, reloc_src->r_vaddr);
   reloc_dst->r_symndx = H_GET_S32 (abfd, reloc_src->r_symndx);
   reloc_dst->r_type   = H_GET_16 (abfd, reloc_src->r_type);
diff --git a/bfd/peicode.h b/bfd/peicode.h
index 441652622b2..e858632312f 100644
--- a/bfd/peicode.h
+++ b/bfd/peicode.h
@@ -134,9 +134,10 @@ bfd_cleanup coff_real_object_p
 static void
 coff_swap_reloc_in (bfd *abfd, void *src, void *dst)
 {
-  RELOC *reloc_src = (RELOC *) src;
-  struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
+  RELOC *reloc_src = src;
+  struct internal_reloc *reloc_dst = dst;
 
+  memset (reloc_dst, 0, sizeof (*reloc_dst));
   reloc_dst->r_vaddr  = H_GET_32 (abfd, reloc_src->r_vaddr);
   reloc_dst->r_symndx = H_GET_S32 (abfd, reloc_src->r_symndx);
   reloc_dst->r_type   = H_GET_16 (abfd, reloc_src->r_type);
diff --git a/include/coff/internal.h b/include/coff/internal.h
index f466d25f779..0191add5aea 100644
--- a/include/coff/internal.h
+++ b/include/coff/internal.h
@@ -680,10 +680,11 @@ struct internal_reloc
 {
   bfd_vma r_vaddr;		/* Virtual address of reference */
   long r_symndx;		/* Index into symbol table	*/
-  unsigned short r_type;	/* Relocation type		*/
-  unsigned char r_size;		/* Used by RS/6000 and ECOFF	*/
-  unsigned char r_extern;	/* Used by ECOFF		*/
   unsigned long r_offset;	/* Used by Alpha ECOFF, SPARC, others */
+  unsigned int r_type:16;	/* Relocation type		*/
+  unsigned int r_size:8;	/* Used by RS/6000 and ECOFF	*/
+  unsigned int r_extern:1;	/* Used by ECOFF		*/
+  unsigned int r_ignore:1;	/* Control _bfd_coff_generic_relocate_section */
 };
 
 #define IMAGE_REL_BASED_ABSOLUTE		0


-- 
Alan Modra