[committed] MIPS/GAS: Add HI16/LO16 pairing for REL TLS relocs

Maciej W. Rozycki macro@orcam.me.uk
Thu Oct 30 14:28:47 GMT 2025


Complementing commit 7ea90d9316d3 ("MIPS: Fix linker for REL TLS 
HI16/LO16 relocs") also add pairing for HI16/LO16 REL TLS relocations 
in GAS, which is where it needs to be done in the first place and 
which is required for later linker operation on the objects produced.

Pairing also corrects in-place addend installation for the high-part 
relocations, which used not to happen in the absence of this fix for 
ones not already followed by the corresponding low-part relocation.

Add test cases to verify relocation ordering and addend installation.
---
 gas/config/tc-mips.c                               |   58 +++++++++++++++-
 gas/testsuite/gas/mips/micromips-tls-hilo-addend.d |   62 ++++++++++++++++++
 gas/testsuite/gas/mips/micromips-tls-hilo-match.d  |   31 +++++++++
 gas/testsuite/gas/mips/mips-tls-hilo-match.s       |   72 +++++++++++++++++++++
 gas/testsuite/gas/mips/mips.exp                    |    4 +
 gas/testsuite/gas/mips/mips16-tls-hilo-addend.d    |   63 ++++++++++++++++++
 gas/testsuite/gas/mips/mips16-tls-hilo-match.d     |   31 +++++++++
 7 files changed, 317 insertions(+), 4 deletions(-)

binutils-mips-gas-tls-hilo16.diff
Index: binutils-gdb/gas/config/tc-mips.c
===================================================================
--- binutils-gdb.orig/gas/config/tc-mips.c
+++ binutils-gdb/gas/config/tc-mips.c
@@ -4353,6 +4353,28 @@ lo16_reloc_p (bfd_reloc_code_real_type r
 }
 
 static inline bool
+tls_hi16_reloc_p (bfd_reloc_code_real_type reloc)
+{
+  return (reloc == BFD_RELOC_MIPS_TLS_DTPREL_HI16
+	  || reloc == BFD_RELOC_MIPS_TLS_TPREL_HI16
+	  || reloc == BFD_RELOC_MIPS16_TLS_DTPREL_HI16
+	  || reloc == BFD_RELOC_MIPS16_TLS_TPREL_HI16
+	  || reloc == BFD_RELOC_MICROMIPS_TLS_DTPREL_HI16
+	  || reloc == BFD_RELOC_MICROMIPS_TLS_TPREL_HI16);
+}
+
+static inline bool
+tls_lo16_reloc_p (bfd_reloc_code_real_type reloc)
+{
+  return (reloc == BFD_RELOC_MIPS_TLS_DTPREL_LO16
+	  || reloc == BFD_RELOC_MIPS_TLS_TPREL_LO16
+	  || reloc == BFD_RELOC_MIPS16_TLS_DTPREL_LO16
+	  || reloc == BFD_RELOC_MIPS16_TLS_TPREL_LO16
+	  || reloc == BFD_RELOC_MICROMIPS_TLS_DTPREL_LO16
+	  || reloc == BFD_RELOC_MICROMIPS_TLS_TPREL_LO16);
+}
+
+static inline bool
 jalr_reloc_p (bfd_reloc_code_real_type reloc)
 {
   return reloc == BFD_RELOC_MIPS_JALR || reloc == BFD_RELOC_MICROMIPS_JALR;
@@ -4403,6 +4425,7 @@ reloc_needs_lo_p (bfd_reloc_code_real_ty
 {
   return (HAVE_IN_PLACE_ADDENDS
 	  && (hi16_reloc_p (reloc)
+	      || tls_hi16_reloc_p (reloc)
 	      /* VxWorks R_MIPS_GOT16 relocs never need a matching %lo();
 		 all GOT16 relocations evaluate to "G".  */
 	      || (got16_reloc_p (reloc) && mips_pic != VXWORKS_PIC)));
@@ -4414,10 +4437,34 @@ reloc_needs_lo_p (bfd_reloc_code_real_ty
 static inline bfd_reloc_code_real_type
 matching_lo_reloc (bfd_reloc_code_real_type reloc)
 {
-  return (mips16_reloc_p (reloc) ? BFD_RELOC_MIPS16_LO16
-	  : micromips_reloc_p (reloc) ? BFD_RELOC_MICROMIPS_LO16
-	  : reloc == BFD_RELOC_HI16_S_PCREL ? BFD_RELOC_LO16_PCREL
-	  : BFD_RELOC_LO16);
+  switch (reloc)
+    {
+    case BFD_RELOC_HI16_S:
+    case BFD_RELOC_MIPS_GOT16:
+      return BFD_RELOC_LO16;
+    case BFD_RELOC_HI16_S_PCREL:
+      return BFD_RELOC_LO16_PCREL;
+    case BFD_RELOC_MIPS_TLS_DTPREL_HI16:
+      return BFD_RELOC_MIPS_TLS_DTPREL_LO16;
+    case BFD_RELOC_MIPS_TLS_TPREL_HI16:
+      return BFD_RELOC_MIPS_TLS_TPREL_LO16;
+    case BFD_RELOC_MIPS16_HI16_S:
+    case BFD_RELOC_MIPS16_GOT16:
+      return BFD_RELOC_MIPS16_LO16;
+    case BFD_RELOC_MIPS16_TLS_DTPREL_HI16:
+      return BFD_RELOC_MIPS16_TLS_DTPREL_LO16;
+    case BFD_RELOC_MIPS16_TLS_TPREL_HI16:
+      return BFD_RELOC_MIPS16_TLS_TPREL_LO16;
+    case BFD_RELOC_MICROMIPS_HI16_S:
+    case BFD_RELOC_MICROMIPS_GOT16:
+      return BFD_RELOC_MICROMIPS_LO16;
+    case BFD_RELOC_MICROMIPS_TLS_DTPREL_HI16:
+      return BFD_RELOC_MICROMIPS_TLS_DTPREL_LO16;
+    case BFD_RELOC_MICROMIPS_TLS_TPREL_HI16:
+      return BFD_RELOC_MICROMIPS_TLS_TPREL_LO16;
+    default:
+      abort ();
+    }
 }
 
 /* Return true if the given fixup is followed by a matching R_MIPS_LO16
@@ -7942,6 +7989,8 @@ append_insn (struct mips_cl_insn *ip, ex
 	      || reloc_type[0] == BFD_RELOC_MIPS_16
 	      || reloc_type[0] == BFD_RELOC_MIPS_RELGOT
 	      || reloc_type[0] == BFD_RELOC_MIPS16_GPREL
+	      || tls_hi16_reloc_p (reloc_type[0])
+	      || tls_lo16_reloc_p (reloc_type[0])
 	      || hi16_reloc_p (reloc_type[0])
 	      || lo16_reloc_p (reloc_type[0])))
 	ip->fixp[0]->fx_no_overflow = 1;
@@ -18304,6 +18353,7 @@ mips_fix_adjustable (fixS *fixp)
      this, it seems better not to force the issue, and instead keep the
      original symbol.  This will work with either linker behavior.  */
   if ((lo16_reloc_p (fixp->fx_r_type)
+       || tls_lo16_reloc_p (fixp->fx_r_type)
        || reloc_needs_lo_p (fixp->fx_r_type))
       && HAVE_IN_PLACE_ADDENDS
       && (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE) != 0)
Index: binutils-gdb/gas/testsuite/gas/mips/micromips-tls-hilo-addend.d
===================================================================
--- /dev/null
+++ binutils-gdb/gas/testsuite/gas/mips/micromips-tls-hilo-addend.d
@@ -0,0 +1,62 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#as: -mabi=32 -march=mips1 -mno-pdr --defsym micromips=1
+#name: MIPS and microMIPS TLS HI/LO REL relocation addends
+#source: mips-tls-hilo-match.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+00000000 <[^>]*> 24025678 	li	v0,22136
+			0: R_MIPS_LO16	var1
+00000004 <[^>]*> 24039384 	li	v1,-27772
+			4: R_MIPS_LO16	var1
+00000008 <[^>]*> 24045678 	li	a0,22136
+			8: R_MIPS_TLS_DTPREL_LO16	var2
+0000000c <[^>]*> 24059384 	li	a1,-27772
+			c: R_MIPS_TLS_DTPREL_LO16	var2
+00000010 <[^>]*> 24065678 	li	a2,22136
+			10: R_MIPS_TLS_TPREL_LO16	var3
+00000014 <[^>]*> 03e00008 	jr	ra
+00000018 <[^>]*> 24079384 	li	a3,-27772
+			18: R_MIPS_TLS_TPREL_LO16	var3
+0000001c <[^>]*> 3040 5678 	li	v0,22136
+			1c: R_MICROMIPS_LO16	var1
+00000020 <[^>]*> 3060 9384 	li	v1,-27772
+			20: R_MICROMIPS_LO16	var1
+00000024 <[^>]*> 3080 5678 	li	a0,22136
+			24: R_MICROMIPS_TLS_DTPREL_LO16	var2
+00000028 <[^>]*> 30a0 9384 	li	a1,-27772
+			28: R_MICROMIPS_TLS_DTPREL_LO16	var2
+0000002c <[^>]*> 30c0 5678 	li	a2,22136
+			2c: R_MICROMIPS_TLS_TPREL_LO16	var3
+00000030 <[^>]*> 459f      	jr	ra
+00000032 <[^>]*> 30e0 9384 	li	a3,-27772
+			32: R_MICROMIPS_TLS_TPREL_LO16	var3
+	\.\.\.
+00000038 <[^>]*> 2407b1a3 	li	a3,-20061
+			38: R_MIPS_TLS_TPREL_HI16	var3
+0000003c <[^>]*> 24061234 	li	a2,4660
+			3c: R_MIPS_TLS_TPREL_HI16	var3
+00000040 <[^>]*> 2405b1a3 	li	a1,-20061
+			40: R_MIPS_TLS_DTPREL_HI16	var2
+00000044 <[^>]*> 24041234 	li	a0,4660
+			44: R_MIPS_TLS_DTPREL_HI16	var2
+00000048 <[^>]*> 2403b1a3 	li	v1,-20061
+			48: R_MIPS_HI16	var1
+0000004c <[^>]*> 03e00008 	jr	ra
+00000050 <[^>]*> 24021234 	li	v0,4660
+			50: R_MIPS_HI16	var1
+00000054 <[^>]*> 30e0 b1a3 	li	a3,-20061
+			54: R_MICROMIPS_TLS_TPREL_HI16	var3
+00000058 <[^>]*> 30c0 1234 	li	a2,4660
+			58: R_MICROMIPS_TLS_TPREL_HI16	var3
+0000005c <[^>]*> 30a0 b1a3 	li	a1,-20061
+			5c: R_MICROMIPS_TLS_DTPREL_HI16	var2
+00000060 <[^>]*> 3080 1234 	li	a0,4660
+			60: R_MICROMIPS_TLS_DTPREL_HI16	var2
+00000064 <[^>]*> 3060 b1a3 	li	v1,-20061
+			64: R_MICROMIPS_HI16	var1
+00000068 <[^>]*> 459f      	jr	ra
+0000006a <[^>]*> 3040 1234 	li	v0,4660
+			6a: R_MICROMIPS_HI16	var1
+	\.\.\.
Index: binutils-gdb/gas/testsuite/gas/mips/micromips-tls-hilo-match.d
===================================================================
--- /dev/null
+++ binutils-gdb/gas/testsuite/gas/mips/micromips-tls-hilo-match.d
@@ -0,0 +1,31 @@
+#readelf: -Wr
+#as: -mabi=32 -march=mips1 -mno-pdr --defsym micromips=1
+#name: MIPS and microMIPS TLS HI/LO REL relocation matching
+#source: mips-tls-hilo-match.s
+
+Relocation section '\.rel\.text' at offset .* contains 24 entries:
+ Offset     Info    Type                Sym\. Value  Symbol's Name
+00000050  00000905 R_MIPS_HI16            00000000   var1
+00000000  00000906 R_MIPS_LO16            00000000   var1
+00000048  00000905 R_MIPS_HI16            00000000   var1
+00000004  00000906 R_MIPS_LO16            00000000   var1
+00000044  00000a2c R_MIPS_TLS_DTPREL_HI16 00000000   var2
+00000008  00000a2d R_MIPS_TLS_DTPREL_LO16 00000000   var2
+00000040  00000a2c R_MIPS_TLS_DTPREL_HI16 00000000   var2
+0000000c  00000a2d R_MIPS_TLS_DTPREL_LO16 00000000   var2
+0000003c  00000b31 R_MIPS_TLS_TPREL_HI16  00000000   var3
+00000010  00000b32 R_MIPS_TLS_TPREL_LO16  00000000   var3
+00000038  00000b31 R_MIPS_TLS_TPREL_HI16  00000000   var3
+00000018  00000b32 R_MIPS_TLS_TPREL_LO16  00000000   var3
+0000006a  00000986 R_MICROMIPS_HI16       00000000   var1
+0000001c  00000987 R_MICROMIPS_LO16       00000000   var1
+00000064  00000986 R_MICROMIPS_HI16       00000000   var1
+00000020  00000987 R_MICROMIPS_LO16       00000000   var1
+00000060  00000aa4 R_MICROMIPS_TLS_DTPREL_HI16 00000000   var2
+00000024  00000aa5 R_MICROMIPS_TLS_DTPREL_LO16 00000000   var2
+0000005c  00000aa4 R_MICROMIPS_TLS_DTPREL_HI16 00000000   var2
+00000028  00000aa5 R_MICROMIPS_TLS_DTPREL_LO16 00000000   var2
+00000058  00000ba9 R_MICROMIPS_TLS_TPREL_HI16 00000000   var3
+0000002c  00000baa R_MICROMIPS_TLS_TPREL_LO16 00000000   var3
+00000054  00000ba9 R_MICROMIPS_TLS_TPREL_HI16 00000000   var3
+00000032  00000baa R_MICROMIPS_TLS_TPREL_LO16 00000000   var3
Index: binutils-gdb/gas/testsuite/gas/mips/mips-tls-hilo-match.s
===================================================================
--- /dev/null
+++ binutils-gdb/gas/testsuite/gas/mips/mips-tls-hilo-match.s
@@ -0,0 +1,72 @@
+	.text
+	.globl	fun1
+	.ent	fun1
+fun1:
+	li	$2, %lo(var1 + 0x12345678)
+	li	$3, %lo(var1 + 0xb1a29384)
+	li	$4, %dtprel_lo(var2 + 0x12345678)
+	li	$5, %dtprel_lo(var2 + 0xb1a29384)
+	li	$6, %tprel_lo(var3 + 0x12345678)
+	li	$7, %tprel_lo(var3 + 0xb1a29384)
+	jr	$31
+	.end	fun1
+
+	.set	push
+	.ifdef	micromips
+	.set	micromips
+	.else
+	.set	mips16
+	.endif
+
+	.globl	fun2
+	.ent	fun2
+fun2:
+	li	$2, %lo(var1 + 0x12345678)
+	li	$3, %lo(var1 + 0xb1a29384)
+	li	$4, %dtprel_lo(var2 + 0x12345678)
+	li	$5, %dtprel_lo(var2 + 0xb1a29384)
+	li	$6, %tprel_lo(var3 + 0x12345678)
+	li	$7, %tprel_lo(var3 + 0xb1a29384)
+	jr	$31
+	.end	fun2
+
+	.set	pop
+	.align	2
+
+	.globl	fun3
+	.ent	fun3
+fun3:
+	li	$7, %tprel_hi(var3 + 0xb1a29384)
+	li	$6, %tprel_hi(var3 + 0x12345678)
+	li	$5, %dtprel_hi(var2 + 0xb1a29384)
+	li	$4, %dtprel_hi(var2 + 0x12345678)
+	li	$3, %hi(var1 + 0xb1a29384)
+	li	$2, %hi(var1 + 0x12345678)
+	jr	$31
+	.end	fun3
+
+	.set	push
+	.ifdef	micromips
+	.set	micromips
+	.else
+	.set	mips16
+	.endif
+
+	.globl	fun4
+	.ent	fun4
+fun4:
+	li	$7, %tprel_hi(var3 + 0xb1a29384)
+	li	$6, %tprel_hi(var3 + 0x12345678)
+	li	$5, %dtprel_hi(var2 + 0xb1a29384)
+	li	$4, %dtprel_hi(var2 + 0x12345678)
+	li	$3, %hi(var1 + 0xb1a29384)
+	li	$2, %hi(var1 + 0x12345678)
+	jr	$31
+	.end	fun4
+
+	.set	pop
+	.align	2
+
+# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+	.space	16
+	.align	4, 0
Index: binutils-gdb/gas/testsuite/gas/mips/mips.exp
===================================================================
--- binutils-gdb.orig/gas/testsuite/gas/mips/mips.exp
+++ binutils-gdb/gas/testsuite/gas/mips/mips.exp
@@ -1057,6 +1057,8 @@ if { [istarget mips*-*-vxworks*] } {
 	run_dump_test "mips16e2-hilo-n32"
     }
     run_dump_test "mips16-hilo-match"
+    run_dump_test "mips16-tls-hilo-match"
+    run_dump_test "mips16-tls-hilo-addend"
     run_dump_test "mips16-reloc-error"
     run_dump_test "mips16e2-reloc-error"
     run_dump_test "mips16-reg-error"
@@ -1655,6 +1657,8 @@ if { [istarget mips*-*-vxworks*] } {
 	run_dump_test "micromips-hilo-n64"
     }
     run_dump_test "micromips-hilo-match"
+    run_dump_test "micromips-tls-hilo-match"
+    run_dump_test "micromips-tls-hilo-addend"
 
     run_dump_test_arches "mcu"		[mips_arch_list_matching mips32r2 \
 					    !octeon]
Index: binutils-gdb/gas/testsuite/gas/mips/mips16-tls-hilo-addend.d
===================================================================
--- /dev/null
+++ binutils-gdb/gas/testsuite/gas/mips/mips16-tls-hilo-addend.d
@@ -0,0 +1,63 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#as: -mabi=32 -march=mips1 -mno-pdr
+#name: MIPS and MIPS16 TLS HI/LO REL relocation addends
+#source: mips-tls-hilo-match.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+00000000 <[^>]*> 24025678 	li	v0,22136
+			0: R_MIPS_LO16	var1
+00000004 <[^>]*> 24039384 	li	v1,-27772
+			4: R_MIPS_LO16	var1
+00000008 <[^>]*> 24045678 	li	a0,22136
+			8: R_MIPS_TLS_DTPREL_LO16	var2
+0000000c <[^>]*> 24059384 	li	a1,-27772
+			c: R_MIPS_TLS_DTPREL_LO16	var2
+00000010 <[^>]*> 24065678 	li	a2,22136
+			10: R_MIPS_TLS_TPREL_LO16	var3
+00000014 <[^>]*> 03e00008 	jr	ra
+00000018 <[^>]*> 24079384 	li	a3,-27772
+			18: R_MIPS_TLS_TPREL_LO16	var3
+0000001c <[^>]*> f66a 6a18 	li	v0,22136
+			1c: R_MIPS16_LO16	var1
+00000020 <[^>]*> f392 6b04 	li	v1,37764
+			20: R_MIPS16_LO16	var1
+00000024 <[^>]*> f66a 6c18 	li	a0,22136
+			24: R_MIPS16_TLS_DTPREL_LO16	var2
+00000028 <[^>]*> f392 6d04 	li	a1,37764
+			28: R_MIPS16_TLS_DTPREL_LO16	var2
+0000002c <[^>]*> f66a 6e18 	li	a2,22136
+			2c: R_MIPS16_TLS_TPREL_LO16	var3
+00000030 <[^>]*> f392 6f04 	li	a3,37764
+			30: R_MIPS16_TLS_TPREL_LO16	var3
+00000034 <[^>]*> e820      	jr	ra
+00000036 <[^>]*> 6500      	nop
+00000038 <[^>]*> 2407b1a3 	li	a3,-20061
+			38: R_MIPS_TLS_TPREL_HI16	var3
+0000003c <[^>]*> 24061234 	li	a2,4660
+			3c: R_MIPS_TLS_TPREL_HI16	var3
+00000040 <[^>]*> 2405b1a3 	li	a1,-20061
+			40: R_MIPS_TLS_DTPREL_HI16	var2
+00000044 <[^>]*> 24041234 	li	a0,4660
+			44: R_MIPS_TLS_DTPREL_HI16	var2
+00000048 <[^>]*> 2403b1a3 	li	v1,-20061
+			48: R_MIPS_HI16	var1
+0000004c <[^>]*> 03e00008 	jr	ra
+00000050 <[^>]*> 24021234 	li	v0,4660
+			50: R_MIPS_HI16	var1
+00000054 <[^>]*> f1b6 6f03 	li	a3,45475
+			54: R_MIPS16_TLS_TPREL_HI16	var3
+00000058 <[^>]*> f222 6e14 	li	a2,4660
+			58: R_MIPS16_TLS_TPREL_HI16	var3
+0000005c <[^>]*> f1b6 6d03 	li	a1,45475
+			5c: R_MIPS16_TLS_DTPREL_HI16	var2
+00000060 <[^>]*> f222 6c14 	li	a0,4660
+			60: R_MIPS16_TLS_DTPREL_HI16	var2
+00000064 <[^>]*> f1b6 6b03 	li	v1,45475
+			64: R_MIPS16_HI16	var1
+00000068 <[^>]*> f222 6a14 	li	v0,4660
+			68: R_MIPS16_HI16	var1
+0000006c <[^>]*> e820      	jr	ra
+0000006e <[^>]*> 6500      	nop
+	\.\.\.
Index: binutils-gdb/gas/testsuite/gas/mips/mips16-tls-hilo-match.d
===================================================================
--- /dev/null
+++ binutils-gdb/gas/testsuite/gas/mips/mips16-tls-hilo-match.d
@@ -0,0 +1,31 @@
+#readelf: -Wr
+#as: -mabi=32 -march=mips1 -mno-pdr
+#name: MIPS and MIPS16 TLS HI/LO REL relocation matching
+#source: mips-tls-hilo-match.s
+
+Relocation section '\.rel\.text' at offset .* contains 24 entries:
+ Offset     Info    Type                Sym\. Value  Symbol's Name
+00000050  00000805 R_MIPS_HI16            00000000   var1
+00000000  00000806 R_MIPS_LO16            00000000   var1
+00000048  00000805 R_MIPS_HI16            00000000   var1
+00000004  00000806 R_MIPS_LO16            00000000   var1
+00000044  0000092c R_MIPS_TLS_DTPREL_HI16 00000000   var2
+00000008  0000092d R_MIPS_TLS_DTPREL_LO16 00000000   var2
+00000040  0000092c R_MIPS_TLS_DTPREL_HI16 00000000   var2
+0000000c  0000092d R_MIPS_TLS_DTPREL_LO16 00000000   var2
+0000003c  00000a31 R_MIPS_TLS_TPREL_HI16  00000000   var3
+00000010  00000a32 R_MIPS_TLS_TPREL_LO16  00000000   var3
+00000038  00000a31 R_MIPS_TLS_TPREL_HI16  00000000   var3
+00000018  00000a32 R_MIPS_TLS_TPREL_LO16  00000000   var3
+00000068  00000868 R_MIPS16_HI16          00000000   var1
+0000001c  00000869 R_MIPS16_LO16          00000000   var1
+00000064  00000868 R_MIPS16_HI16          00000000   var1
+00000020  00000869 R_MIPS16_LO16          00000000   var1
+00000060  0000096c R_MIPS16_TLS_DTPREL_HI16 00000000   var2
+00000024  0000096d R_MIPS16_TLS_DTPREL_LO16 00000000   var2
+0000005c  0000096c R_MIPS16_TLS_DTPREL_HI16 00000000   var2
+00000028  0000096d R_MIPS16_TLS_DTPREL_LO16 00000000   var2
+00000058  00000a6f R_MIPS16_TLS_TPREL_HI16 00000000   var3
+0000002c  00000a70 R_MIPS16_TLS_TPREL_LO16 00000000   var3
+00000054  00000a6f R_MIPS16_TLS_TPREL_HI16 00000000   var3
+00000030  00000a70 R_MIPS16_TLS_TPREL_LO16 00000000   var3


More information about the Binutils mailing list