[PATCH v2] aarch64: Add support for %dtprel(var) and R_AARCH64_TLS_DTPREL64

Alice Carlotti alice.carlotti@arm.com
Tue Apr 7 17:14:44 GMT 2026


On Fri, Apr 03, 2026 at 11:47:03PM +0530, Shivam Gupta wrote:
> 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

I think you forgot to include the commit message in this version.

This is looking close to ready - I have just a few more comments below.  I
presume you'll need someone to commit the patch for you once it's approved?

> 
> ---
>  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 == '%')
> +	{

Can we simplify these lines...
> +	  char *p = ++input_line_pointer; /* skip '%' */
> +
> +	  /* Look for "dtprel" */
> +	  if (strncmp (p, "dtprel", 6) == 0 && p[6] == '(')
> +	    {
> +	      input_line_pointer = p + 7; /* Skip "dtprel(" */
to
	  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
> +	    {
> +	      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);

Having looked again, I think the original error message was actually better,
whereas the new error message is less accurate in some cases.  We could also
avoid printing any user input (we don't bother in other similar cases), since
it ought to be fairly clear from the printed error location.  So I suggest either:

	      as_bad (_("unknown relocation operator"));

or:

	      as_bad (_("unknown relocation operator -- %s"),
			input_line_pointer);

(note that there's no space after the underscore).

> +	      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)

Can you include a test that uses multiple %dtprel relocations in a single line?
(Adjusting your input files to combine the two lines into one looks sufficient
to me.)

Alice

> -- 
> 2.34.1
> 


More information about the Binutils mailing list