[PATCH v2] aarch64: Add support for %dtprel(var) and R_AARCH64_TLS_DTPREL64
Shivam Gupta
shivam98.tkg@gmail.com
Fri Apr 3 18:17:03 GMT 2026
Hi Alice,
This is v2 of the patch with fixes based on review comments.
Changes in v2:
- Return bfd_reloc_notsupported for SEC_ALLOC sections
- Fix error handling in %dtprel parsing
- Improve diagnostics
- Extract operator name correctly
- Remove incorrect reloc_table entry
- Drop gold changes
- Update test regex
Thanks for the review!
Shivam
---
bfd/elfnn-aarch64.c | 11 ++++++
gas/config/tc-aarch64.c | 49 +++++++++++++++++++++++++
gas/testsuite/gas/aarch64/tls-debug.d | 10 +++++
gas/testsuite/gas/aarch64/tls-debug.s | 9 +++++
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, 98 insertions(+)
create mode 100644 gas/testsuite/gas/aarch64/tls-debug.d
create mode 100644 gas/testsuite/gas/aarch64/tls-debug.s
create mode 100644 ld/testsuite/ld-aarch64/tls-debug.d
create mode 100644 ld/testsuite/ld-aarch64/tls-debug.s
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 66049c81..117e1498 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 cd761634..66fce0be 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -2229,6 +2229,54 @@ s_aarch64_cons (int nbytes)
{
struct reloc_table_entry *reloc;
+ /* Check for %dtprel(var) syntax */
+ if (*input_line_pointer == '%')
+ {
+ char *p = ++input_line_pointer; /* skip '%' */
+
+ /* Look for "dtprel" */
+ if (strncmp (p, "dtprel", 6) == 0 && p[6] == '(')
+ {
+ input_line_pointer = p + 7; /* Skip "dtprel(" */
+
+ 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
+ {
+ char opname[16];
+ char *q = p;
+ char *r = opname;
+
+ while (ISALPHA (*q) && r < opname + sizeof (opname) - 1)
+ *r++ = *q++;
+
+ *r = '\0';
+
+ as_bad (_ ("unknown relocation operator %%%s"), opname);
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+
expression (&exp);
if (exp.X_op != O_symbol)
@@ -10114,6 +10162,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 00000000..1dd4df17
--- /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 00000000..9590ad40
--- /dev/null
+++ b/gas/testsuite/gas/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)
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index 24c73d53..fa802105 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 00000000..4344b02e
--- /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 00000000..9590ad40
--- /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)
--
2.34.1
More information about the Binutils
mailing list