Index | Thread | Search

From:
Kirill A. Korinsky <kirill@korins.ky>
Subject:
ld.bfd: handle modern SPARC GOTDATA relocations
To:
OpenBSD tech <tech@openbsd.org>
Cc:
kmos@openbsd.org
Date:
Tue, 04 Aug 2026 21:59:42 +0200

Download raw body.

Thread
  • Kirill A. Korinsky:

    ld.bfd: handle modern SPARC GOTDATA relocations

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?

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	4 Aug 2026 19:38:17 -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_bitfield,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_bitfield,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,12 +3363,16 @@ _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);
@@ -3348,12 +3383,18 @@ _bfd_sparc_elf_relocate_section (bfd *ou
 				  bfd_arch_bits_per_address (input_bfd),
 				  relocation);
 	}
-      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