[PATCH V5] x86: Add tls check in gas

Jan Beulich jbeulich@suse.com
Tue Sep 24 15:48:58 GMT 2024


I've grabbed the newest tls.pdf I could find (still over 10 years old,
from Ulrich Drepper's site as referenced by the Thread-Local Storage
section in gcc14 doc), and that raises questions:

On 19.09.2024 08:38, Cui, Lili wrote:
> @@ -6357,6 +6387,356 @@ static INLINE bool may_need_pass2 (const insn_template *t)
>  	       && (t->base_opcode | 8) == 0x2c);
>  }
>  
> +static enum x86_tls_error_type
> +x86_check_tls_relocation (enum bfd_reloc_code_real r_type)
> +{
> +  switch (r_type)
> +    {
> +    case BFD_RELOC_386_TLS_GOTDESC:
> +      /* Check GDesc access model:

What's "GDesc access model"? I can't find anything named like this, nor
mention of ...

> +	 leal x@tlsdesc(%ebx), %reg32 --> Memory reg must be %ebx and
> +					  SIB is not supported.
> +       */

... @tlsdesc.

> +      if (i.tm.mnem_off != MN_lea)
> +	return x86_tls_error_insn;
> +      if (i.index_reg)
> +	return x86_tls_error_sib;
> +      if (!i.base_reg)
> +	return x86_tls_error_no_base_reg;
> +      if (i.base_reg->reg_type.bitfield.instance != RegB)
> +	return x86_tls_error_ebx;
> +      if (!i.op[1].regs->reg_type.bitfield.dword)
> +	return x86_tls_error_dest_32bit_reg_size;
> +      break;
> +
> +    case BFD_RELOC_386_TLS_GD:
> +      /* Check GD access model:
> +
> +	 leal foo@tlsgd(,%ebx,1), %eax   --> Only this fixed format is supported.
> +	 leal foo@tlsgd(%reg32), %eax    --> Dest reg must be '%eax'
> +					     Memory reg can't be %eax.
> +       */

Where's this 2nd form coming from? The doc says the SIB form must be
used, and the converted-to code sequence would require one more byte
than the non-SIB form provides space for.

The doc doesn't say that the index reg has to be %ebx, it merely
mentions that in the example, for being the commonly used GOT reg.
This is the same ...

> +      if (i.tm.mnem_off != MN_lea)
> +	return x86_tls_error_insn;
> +      if (i.op[1].regs->reg_type.bitfield.instance != Accum)
> +	return x86_tls_error_dest_eax;
> +      if (!i.op[1].regs->reg_type.bitfield.dword)
> +	return x86_tls_error_dest_32bit_reg_size;
> +      if (i.index_reg)
> +	{
> +	  if (i.base_reg)
> +	    return x86_tls_error_base_reg;
> +	  if (i.index_reg->reg_type.bitfield.instance != RegB)
> +	    return x86_tls_error_index_ebx;
> +	  if (i.log2_scale_factor)
> +	    return x86_tls_error_scale_factor;
> +	}
> +      else
> +	{
> +	  if (!i.base_reg)
> +	    return x86_tls_error_no_base_reg;
> +	  if (i.base_reg->reg_type.bitfield.instance == Accum)
> +	    return x86_tls_error_eax;
> +	}
> +      break;
> +
> +    case BFD_RELOC_386_TLS_LDM:
> +      /*  Check LDM access model:
> +
> +	  leal foo@tlsldm(%reg32), %eax --> Dest reg must be '%eax'
> +				            Memory reg can't be %eax and SIB
> +					    is not supported.
> +       */

... for this case, and surprisingly any register is permitted here.

I'll stop here for now, as this is all unclear enough already. I'm
getting the impression that gas is being made match ld without
regard to whether ld is actually correct. Checks in gas - if we
already have any - should be tied to what the spec demands, not
how a particular linker is implemented. As said before - people may
be using different linkers.

Jan


More information about the Binutils mailing list