]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
aarch64: Add support for %dtprel(var) and R_AARCH64_TLS_DTPREL64
authorShivam Gupta <shivam98.tkg@gmail.com>
Wed, 8 Apr 2026 10:15:38 +0000 (15:45 +0530)
committerAlice Carlotti <alice.carlotti@arm.com>
Thu, 9 Apr 2026 14:34:45 +0000 (15:34 +0100)
This patch allows R_AARCH64_TLS_DTPREL64 relocations in non-allocated
sections, which is required for DWARF debug information when using
Thread Local Storage. This matches the behavior in LLD.

Also a new syntax to parse dtprel operator use to describe tls
location in debug information. Please see the reference 3 below.

References:
  - https://github.com/llvm/llvm-project/pull/146572
    [AArch64] Support TLS variables in debug info
  - https://github.com/llvm/llvm-project/pull/183962
    [LLD][AArch64] Handle R_AARCH64_TLS_DTPREL64 in non-alloc sections
  - https://github.com/ARM-software/abi-aa/pull/330
    [AAELF64] Allow R_AARCH64_TLS_DTPREL to be used statically.

bfd/
        * elfnn-aarch64.c (elfNN_aarch64_final_link_relocate): Handle
        BFD_RELOC_AARCH64_TLS_DTPREL.

gas/
* config/tc-aarch64.c (s_aarch64_cons): Parse %dtprel(var) syntax.
* testsuite/gas/aarch64/tls-debug.s: New test.
* testsuite/gas/aarch64/tls-debug.d: Run the test.

ld/
* testsuite/ld-aarch64/tls-debug.s: New test.
* testsuite/ld-aarch64/tls-debug.d: Run the test.

Bug: https://sourceware.org/PR28351

Signed-off-by: Shivam Gupta <shivam98.tkg@gmail.com>
bfd/elfnn-aarch64.c
gas/config/tc-aarch64.c
gas/testsuite/gas/aarch64/tls-debug.d [new file with mode: 0644]
gas/testsuite/gas/aarch64/tls-debug.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/aarch64-elf.exp
ld/testsuite/ld-aarch64/tls-debug.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/tls-debug.s [new file with mode: 0644]

index 66049c81edf7dcb880a6a8b6d19eabaa492b1ee2..117e149866cf8737b3e742678a57d70d40a9f935 100644 (file)
@@ -6496,6 +6496,17 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
       *unresolved_reloc_p = false;
       break;
 
+    case BFD_RELOC_AARCH64_TLS_DTPREL:
+      if (input_section->flags & SEC_ALLOC)
+       return bfd_reloc_notsupported;
+      value -= dtpoff_base (info);
+      value += rel->r_addend;
+
+      bfd_put_64 (output_bfd, value, contents + rel->r_offset);
+
+      *unresolved_reloc_p = false;
+      break;
+
     case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
     case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
       if (globals->root.sgot == NULL)
index cd76163488c48e45d43c35b2704d637999d51015..73b549a16c9aec2b1a2b74c8cea8d3ef6684151f 100644 (file)
@@ -2229,6 +2229,42 @@ s_aarch64_cons (int nbytes)
     {
       struct reloc_table_entry *reloc;
 
+      /* Check for %dtprel(var) syntax */
+      if (*input_line_pointer == '%')
+       {
+         if (strncmp (input_line_pointer, "%dtprel(", 8) == 0)
+           {
+             input_line_pointer += 8;
+
+             expression (&exp);
+
+             /* Ensure we have a closing parenthesis */
+             if (*input_line_pointer == ')')
+               input_line_pointer++;
+             else
+               {
+                 as_bad (_("missing ')' after %%dtprel"));
+                 ignore_rest_of_line ();
+                 return;
+               }
+
+             addressT where = frag_now_fix ();
+             fix_new_exp (frag_now, where, nbytes, &exp, 0,
+                          BFD_RELOC_AARCH64_TLS_DTPREL);
+
+             char *dest = frag_more (nbytes);
+             memset (dest, 0, nbytes);
+             continue;
+           }
+
+         else
+           {
+             as_bad (_("unknown relocation operator"));
+             ignore_rest_of_line ();
+             return;
+           }
+       }
+
       expression (&exp);
 
       if (exp.X_op != O_symbol)
@@ -10114,6 +10150,7 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg)
     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
+    case BFD_RELOC_AARCH64_TLS_DTPREL:
       S_SET_THREAD_LOCAL (fixP->fx_addsy);
       /* Should always be exported to object file, see
         aarch64_force_relocation().  */
diff --git a/gas/testsuite/gas/aarch64/tls-debug.d b/gas/testsuite/gas/aarch64/tls-debug.d
new file mode 100644 (file)
index 0000000..1dd4df1
--- /dev/null
@@ -0,0 +1,10 @@
+#as:
+#objdump: -r
+#target: aarch64*-*-*
+
+#...
+RELOCATION RECORDS FOR \[\.debug_info\]:
+OFFSET +TYPE +VALUE
+0*0 R_AARCH64_TLS_DTPREL64 +var
+0*8 R_AARCH64_TLS_DTPREL64 +var\+0x0+1
+#...
diff --git a/gas/testsuite/gas/aarch64/tls-debug.s b/gas/testsuite/gas/aarch64/tls-debug.s
new file mode 100644 (file)
index 0000000..c45507e
--- /dev/null
@@ -0,0 +1,8 @@
+.section .tdata,"awT",@progbits
+.skip 8          // Force var to have an offset of 8
+.globl var
+var:
+  .word 0
+
+.section        .debug_info,"",@progbits
+  .xword  %dtprel(var), %dtprel(var+1)
index 24c73d530dce16fbb03e920955f259ccab956514..fa80210500eb2f489b50a9fef9f79c8224fe1810 100644 (file)
@@ -261,6 +261,7 @@ run_dump_test "tls-relax-ld-le-small"
 run_dump_test "tls-relax-ld-le-small-ilp32"
 run_dump_test "tls-relax-ld-le-tiny"
 run_dump_test "tls-relax-ld-le-tiny-ilp32"
+run_dump_test "tls-debug"
 run_dump_test "tls-desc-ie"
 run_dump_test "tls-desc-ie-ilp32"
 run_dump_test "tls-relax-gdesc-le-2"
diff --git a/ld/testsuite/ld-aarch64/tls-debug.d b/ld/testsuite/ld-aarch64/tls-debug.d
new file mode 100644 (file)
index 0000000..4344b02
--- /dev/null
@@ -0,0 +1,9 @@
+#source: tls-debug.s
+#ld: -shared -T relocs.ld -e0
+#objdump: -s -j .debug_info
+
+#...
+Contents of section .debug_info:
+#...
+ [0-9a-f]+ 08000000 00000000 09000000 00000000 .*
+#...
diff --git a/ld/testsuite/ld-aarch64/tls-debug.s b/ld/testsuite/ld-aarch64/tls-debug.s
new file mode 100644 (file)
index 0000000..9590ad4
--- /dev/null
@@ -0,0 +1,9 @@
+.section .tdata,"awT",@progbits
+.skip 8          // Force var to have an offset of 8
+.globl var
+var:
+  .word 0
+
+.section        .debug_info,"",@progbits
+  .xword  %dtprel(var)
+  .xword  %dtprel(var+1)