[binutils-gdb] aarch64: Add support for %dtprel(var) and R_AARCH64_TLS_DTPREL64

Alice Carlotti via Binutils-cvs <[email protected]>
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ed71fa9a44511cb8d933073f892ea041c3ff9107

commit ed71fa9a44511cb8d933073f892ea041c3ff9107
Author: Shivam Gupta <[email protected]>
Date:   Wed Apr 8 15:45:38 2026 +0530

    aarch64: Add support for %dtprel(var) and R_AARCH64_TLS_DTPREL64
    
    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 <[email protected]>

Diff:
---
 bfd/elfnn-aarch64.c                     | 11 ++++++++++
 gas/config/tc-aarch64.c                 | 37 +++++++++++++++++++++++++++++++++
 gas/testsuite/gas/aarch64/tls-debug.d   | 10 +++++++++
 gas/testsuite/gas/aarch64/tls-debug.s   |  8 +++++++
 ld/testsuite/ld-aarch64/aarch64-elf.exp |  1 +
 ld/testsuite/ld-aarch64/tls-debug.d     |  9 ++++++++
 ld/testsuite/ld-aarch64/tls-debug.s     |  9 ++++++++
 7 files changed, 85 insertions(+)

diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 66049c81edf..117e149866c 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -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)
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index cd76163488c..73b549a16c9 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -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
index 00000000000..1dd4df17542
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/tls-debug.d
@@ -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
index 00000000000..c45507ed110
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/tls-debug.s
@@ -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)
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index 24c73d530dc..fa80210500e 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -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
index 00000000000..4344b02e794
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-debug.d
@@ -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
index 00000000000..9590ad409f9
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-debug.s
@@ -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)
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.