]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
MIPS/GAS: Add HI16/LO16 pairing for REL TLS relocs
authorMaciej W. Rozycki <macro@orcam.me.uk>
Thu, 30 Oct 2025 14:24:23 +0000 (14:24 +0000)
committerMaciej W. Rozycki <macro@orcam.me.uk>
Thu, 30 Oct 2025 14:24:23 +0000 (14:24 +0000)
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
gas/testsuite/gas/mips/micromips-tls-hilo-addend.d [new file with mode: 0644]
gas/testsuite/gas/mips/micromips-tls-hilo-match.d [new file with mode: 0644]
gas/testsuite/gas/mips/mips-tls-hilo-match.s [new file with mode: 0644]
gas/testsuite/gas/mips/mips.exp
gas/testsuite/gas/mips/mips16-tls-hilo-addend.d [new file with mode: 0644]
gas/testsuite/gas/mips/mips16-tls-hilo-match.d [new file with mode: 0644]

index f7ee46c68f237386f8429e7e2a65c343f7acc6ce..42d2cb5e4355db42c22152108560062fdea9c535 100644 (file)
@@ -4352,6 +4352,28 @@ lo16_reloc_p (bfd_reloc_code_real_type reloc)
          || reloc == BFD_RELOC_MICROMIPS_LO16);
 }
 
+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)
 {
@@ -4403,6 +4425,7 @@ reloc_needs_lo_p (bfd_reloc_code_real_type reloc)
 {
   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_type reloc)
 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, expressionS *address_expr,
              || 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)
diff --git a/gas/testsuite/gas/mips/micromips-tls-hilo-addend.d b/gas/testsuite/gas/mips/micromips-tls-hilo-addend.d
new file mode 100644 (file)
index 0000000..8c69499
--- /dev/null
@@ -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
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/micromips-tls-hilo-match.d b/gas/testsuite/gas/mips/micromips-tls-hilo-match.d
new file mode 100644 (file)
index 0000000..f4e4a56
--- /dev/null
@@ -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
diff --git a/gas/testsuite/gas/mips/mips-tls-hilo-match.s b/gas/testsuite/gas/mips/mips-tls-hilo-match.s
new file mode 100644 (file)
index 0000000..112caa8
--- /dev/null
@@ -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 48b1fe7bf46ec40d413127bafeac5ee611181ca5..be02e7f3d59b53defd5773bf46e7c1104b5d3db2 100644 (file)
@@ -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]
diff --git a/gas/testsuite/gas/mips/mips16-tls-hilo-addend.d b/gas/testsuite/gas/mips/mips16-tls-hilo-addend.d
new file mode 100644 (file)
index 0000000..90b8550
--- /dev/null
@@ -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
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/mips16-tls-hilo-match.d b/gas/testsuite/gas/mips/mips16-tls-hilo-match.d
new file mode 100644 (file)
index 0000000..9e1b30a
--- /dev/null
@@ -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