Re: ld.bfd: handle modern SPARC GOTDATA relocations

Kirill A. Korinsky <[email protected]>
Newsgroups gmane.os.openbsd.tech
Message-ID <[email protected]>
On Tue, 04 Aug 2026 21:59:42 +0200,
Kirill A. Korinsky <[email protected]> wrote:
> 
> tech@,
> 
> Modern GAS emits R_SPARC_GOTDATA_OP_HIX22, R_SPARC_GOTDATA_OP_LOX10, and
> R_SPARC_GOTDATA_OP, which are unknown to BFD 2.17 and cause the final link
> to fail with "Bad value".
> 
> This diff fixed bulding devel/gmp which passed make test.
> 
> Ok?
>

Here a version which includes suggested tweaks from claudio@ and which I
think he run on his bulk build.

Anyone?

Index: gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h
===================================================================
RCS file: /home/cvs/src/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h,v
diff -u -p -r1.12 bfd-in2.h
--- gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h	11 Jan 2024 12:31:37 -0000	1.12
+++ gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h	4 Aug 2026 19:35:03 -0000
@@ -2373,6 +2373,11 @@ relocation types already defined.  */
   BFD_RELOC_SPARC_UA16,
   BFD_RELOC_SPARC_UA32,
   BFD_RELOC_SPARC_UA64,
+  BFD_RELOC_SPARC_GOTDATA_HIX22,
+  BFD_RELOC_SPARC_GOTDATA_LOX10,
+  BFD_RELOC_SPARC_GOTDATA_OP_HIX22,
+  BFD_RELOC_SPARC_GOTDATA_OP_LOX10,
+  BFD_RELOC_SPARC_GOTDATA_OP,
 
 /* I think these are specific to SPARC a.out (e.g., Sun 4).  */
   BFD_RELOC_SPARC_BASE13,
Index: gnu/usr.bin/binutils-2.17/bfd/elfxx-sparc.c
===================================================================
RCS file: /home/cvs/src/gnu/usr.bin/binutils-2.17/bfd/elfxx-sparc.c,v
diff -u -p -r1.7 elfxx-sparc.c
--- gnu/usr.bin/binutils-2.17/bfd/elfxx-sparc.c	15 Apr 2017 10:23:35 -0000	1.7
+++ gnu/usr.bin/binutils-2.17/bfd/elfxx-sparc.c	5 Aug 2026 13:13:57 -0000
@@ -256,7 +256,12 @@ static reloc_howto_type _bfd_sparc_elf_h
   HOWTO(R_SPARC_TLS_DTPOFF32,0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_TLS_DTPOFF32",FALSE,0,0xffffffff,TRUE),
   HOWTO(R_SPARC_TLS_DTPOFF64,0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_TLS_DTPOFF64",FALSE,0,MINUS_ONE,TRUE),
   HOWTO(R_SPARC_TLS_TPOFF32,0,0, 0,FALSE,0,complain_overflow_dont,   bfd_elf_generic_reloc,  "R_SPARC_TLS_TPOFF32",FALSE,0,0x00000000,TRUE),
-  HOWTO(R_SPARC_TLS_TPOFF64,0,0, 0,FALSE,0,complain_overflow_dont,   bfd_elf_generic_reloc,  "R_SPARC_TLS_TPOFF64",FALSE,0,0x00000000,TRUE)
+  HOWTO(R_SPARC_TLS_TPOFF64,0,0, 0,FALSE,0,complain_overflow_dont,   bfd_elf_generic_reloc,  "R_SPARC_TLS_TPOFF64",FALSE,0,0x00000000,TRUE),
+  HOWTO(R_SPARC_GOTDATA_HIX22,0,2,0,FALSE,0,complain_overflow_dont,  sparc_elf_hix22_reloc,"R_SPARC_GOTDATA_HIX22",FALSE,0,0x003fffff,FALSE),
+  HOWTO(R_SPARC_GOTDATA_LOX10,0,2,0,FALSE,0,complain_overflow_dont,  sparc_elf_lox10_reloc,  "R_SPARC_GOTDATA_LOX10",FALSE,0,0x000003ff,FALSE),
+  HOWTO(R_SPARC_GOTDATA_OP_HIX22,0,2,0,FALSE,0,complain_overflow_dont,sparc_elf_hix22_reloc,"R_SPARC_GOTDATA_OP_HIX22",FALSE,0,0x003fffff,FALSE),
+  HOWTO(R_SPARC_GOTDATA_OP_LOX10,0,2,0,FALSE,0,complain_overflow_dont,sparc_elf_lox10_reloc,"R_SPARC_GOTDATA_OP_LOX10",FALSE,0,0x000003ff,FALSE),
+  HOWTO(R_SPARC_GOTDATA_OP,0,0,0,FALSE,0,complain_overflow_dont,     bfd_elf_generic_reloc,  "R_SPARC_GOTDATA_OP",FALSE,0,0x00000000,TRUE)
 };
 static reloc_howto_type sparc_vtinherit_howto =
   HOWTO (R_SPARC_GNU_VTINHERIT, 0,2,0,FALSE,0,complain_overflow_dont, NULL, "R_SPARC_GNU_VTINHERIT", FALSE,0, 0, FALSE);
@@ -340,6 +345,11 @@ static const struct elf_reloc_map sparc_
   { BFD_RELOC_SPARC_TLS_DTPOFF64, R_SPARC_TLS_DTPOFF64 },
   { BFD_RELOC_SPARC_TLS_TPOFF32, R_SPARC_TLS_TPOFF32 },
   { BFD_RELOC_SPARC_TLS_TPOFF64, R_SPARC_TLS_TPOFF64 },
+  { BFD_RELOC_SPARC_GOTDATA_HIX22, R_SPARC_GOTDATA_HIX22 },
+  { BFD_RELOC_SPARC_GOTDATA_LOX10, R_SPARC_GOTDATA_LOX10 },
+  { BFD_RELOC_SPARC_GOTDATA_OP_HIX22, R_SPARC_GOTDATA_OP_HIX22 },
+  { BFD_RELOC_SPARC_GOTDATA_OP_LOX10, R_SPARC_GOTDATA_OP_LOX10 },
+  { BFD_RELOC_SPARC_GOTDATA_OP, R_SPARC_GOTDATA_OP },
   { BFD_RELOC_SPARC_PLT32, R_SPARC_PLT32 },
   { BFD_RELOC_SPARC_PLT64, R_SPARC_PLT64 },
   { BFD_RELOC_SPARC_HIX22, R_SPARC_HIX22 },
@@ -1147,6 +1157,10 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, 
 	case R_SPARC_GOT10:
 	case R_SPARC_GOT13:
 	case R_SPARC_GOT22:
+	case R_SPARC_GOTDATA_HIX22:
+	case R_SPARC_GOTDATA_LOX10:
+	case R_SPARC_GOTDATA_OP_HIX22:
+	case R_SPARC_GOTDATA_OP_LOX10:
 	case R_SPARC_TLS_GD_HI22:
 	case R_SPARC_TLS_GD_LO10:
 	  /* This symbol requires a global offset table entry.  */
@@ -1607,6 +1621,10 @@ _bfd_sparc_elf_gc_sweep_hook (bfd *abfd,
 	case R_SPARC_GOT10:
 	case R_SPARC_GOT13:
 	case R_SPARC_GOT22:
+	case R_SPARC_GOTDATA_HIX22:
+	case R_SPARC_GOTDATA_LOX10:
+	case R_SPARC_GOTDATA_OP_HIX22:
+	case R_SPARC_GOTDATA_OP_LOX10:
 	  if (h != NULL)
 	    {
 	      if (h->got.refcount > 0)
@@ -2563,6 +2581,19 @@ _bfd_sparc_elf_relocate_section (bfd *ou
 
       switch (r_type)
 	{
+	case R_SPARC_GOTDATA_HIX22:
+	case R_SPARC_GOTDATA_LOX10:
+	  if (htab->sgot == NULL)
+	    abort ();
+	  relocation -= (htab->sgot->output_section->vma
+			 + htab->sgot->output_offset + got_base);
+	  break;
+
+	case R_SPARC_GOTDATA_OP:
+	  continue;
+
+	case R_SPARC_GOTDATA_OP_HIX22:
+	case R_SPARC_GOTDATA_OP_LOX10:
 	case R_SPARC_GOT10:
 	case R_SPARC_GOT13:
 	case R_SPARC_GOT22:
@@ -3332,28 +3363,41 @@ _bfd_sparc_elf_relocate_section (bfd *ou
 
 	  r = bfd_reloc_ok;
 	}
-      else if (r_type == R_SPARC_HIX22)
+      else if (r_type == R_SPARC_HIX22
+	       || r_type == R_SPARC_GOTDATA_HIX22
+	       || r_type == R_SPARC_GOTDATA_OP_HIX22)
 	{
 	  bfd_vma x;
 
 	  relocation += rel->r_addend;
-	  relocation = relocation ^ MINUS_ONE;
+	  if (r_type == R_SPARC_HIX22
+	      || (bfd_signed_vma) relocation < 0)
+	    relocation = relocation ^ MINUS_ONE;
 
 	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
 	  x = (x & ~(bfd_vma) 0x3fffff) | ((relocation >> 10) & 0x3fffff);
 	  bfd_put_32 (input_bfd, x, contents + rel->r_offset);
 
-	  r = bfd_check_overflow (howto->complain_on_overflow,
-				  howto->bitsize, howto->rightshift,
-				  bfd_arch_bits_per_address (input_bfd),
-				  relocation);
+	  if (howto->complain_on_overflow != complain_overflow_dont)
+	    r = bfd_check_overflow (howto->complain_on_overflow,
+				    howto->bitsize, howto->rightshift,
+				    bfd_arch_bits_per_address (input_bfd),
+				    relocation);
+	  else
+	    r = bfd_reloc_ok;
 	}
-      else if (r_type == R_SPARC_LOX10)
+      else if (r_type == R_SPARC_LOX10
+	       || r_type == R_SPARC_GOTDATA_LOX10
+	       || r_type == R_SPARC_GOTDATA_OP_LOX10)
 	{
 	  bfd_vma x;
 
 	  relocation += rel->r_addend;
-	  relocation = (relocation & 0x3ff) | 0x1c00;
+	  if (r_type == R_SPARC_LOX10
+	      || (bfd_signed_vma) relocation < 0)
+	    relocation = (relocation & 0x3ff) | 0x1c00;
+	  else
+	    relocation &= 0x3ff;
 
 	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
 	  x = (x & ~(bfd_vma) 0x1fff) | relocation;
Index: gnu/usr.bin/binutils-2.17/bfd/libbfd.h
===================================================================
RCS file: /home/cvs/src/gnu/usr.bin/binutils-2.17/bfd/libbfd.h,v
diff -u -p -r1.8 libbfd.h
--- gnu/usr.bin/binutils-2.17/bfd/libbfd.h	11 Jan 2024 12:31:37 -0000	1.8
+++ gnu/usr.bin/binutils-2.17/bfd/libbfd.h	4 Aug 2026 19:41:03 -0000
@@ -853,6 +853,11 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_SPARC_UA16",
   "BFD_RELOC_SPARC_UA32",
   "BFD_RELOC_SPARC_UA64",
+  "BFD_RELOC_SPARC_GOTDATA_HIX22",
+  "BFD_RELOC_SPARC_GOTDATA_LOX10",
+  "BFD_RELOC_SPARC_GOTDATA_OP_HIX22",
+  "BFD_RELOC_SPARC_GOTDATA_OP_LOX10",
+  "BFD_RELOC_SPARC_GOTDATA_OP",
   "BFD_RELOC_SPARC_BASE13",
   "BFD_RELOC_SPARC_BASE22",
   "BFD_RELOC_SPARC_10",
Index: gnu/usr.bin/binutils-2.17/bfd/reloc.c
===================================================================
RCS file: /home/cvs/src/gnu/usr.bin/binutils-2.17/bfd/reloc.c,v
diff -u -p -r1.4 reloc.c
--- gnu/usr.bin/binutils-2.17/bfd/reloc.c	25 Feb 2017 22:53:36 -0000	1.4
+++ gnu/usr.bin/binutils-2.17/bfd/reloc.c	4 Aug 2026 19:35:03 -0000
@@ -1768,6 +1768,16 @@ ENUMX
   BFD_RELOC_SPARC_UA32
 ENUMX
   BFD_RELOC_SPARC_UA64
+ENUMX
+  BFD_RELOC_SPARC_GOTDATA_HIX22
+ENUMX
+  BFD_RELOC_SPARC_GOTDATA_LOX10
+ENUMX
+  BFD_RELOC_SPARC_GOTDATA_OP_HIX22
+ENUMX
+  BFD_RELOC_SPARC_GOTDATA_OP_LOX10
+ENUMX
+  BFD_RELOC_SPARC_GOTDATA_OP
 ENUMDOC
   SPARC ELF relocations.  There is probably some overlap with other
   relocation types already defined.
Index: gnu/usr.bin/binutils-2.17/include/elf/sparc.h
===================================================================
RCS file: /home/cvs/src/gnu/usr.bin/binutils-2.17/include/elf/sparc.h,v
diff -u -p -r1.1.1.1 sparc.h
--- gnu/usr.bin/binutils-2.17/include/elf/sparc.h	24 Apr 2011 20:14:48 -0000	1.1.1.1
+++ gnu/usr.bin/binutils-2.17/include/elf/sparc.h	4 Aug 2026 19:35:03 -0000
@@ -151,6 +151,12 @@ START_RELOC_NUMBERS (elf_sparc_reloc_typ
   RELOC_NUMBER (R_SPARC_TLS_DTPOFF64, 77)
   RELOC_NUMBER (R_SPARC_TLS_TPOFF32, 78)
   RELOC_NUMBER (R_SPARC_TLS_TPOFF64, 79)
+
+  RELOC_NUMBER (R_SPARC_GOTDATA_HIX22, 80)
+  RELOC_NUMBER (R_SPARC_GOTDATA_LOX10, 81)
+  RELOC_NUMBER (R_SPARC_GOTDATA_OP_HIX22, 82)
+  RELOC_NUMBER (R_SPARC_GOTDATA_OP_LOX10, 83)
+  RELOC_NUMBER (R_SPARC_GOTDATA_OP, 84)
   
   EMPTY_RELOC  (R_SPARC_max_std)
 


-- 
wbr, Kirill
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.