[PATCH V5] x86: Add tls check in gas
Cui, Lili
lili.cui@intel.com
Wed Sep 25 12:45:11 GMT 2024
> Subject: Re: [PATCH V5] x86: Add tls check in gas
>
> On 25.09.2024 05:32, Cui, Lili wrote:
> >> 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:
> >
> > Jan, you can find the latest TLS in ABI chapter 10
> > (https://gitlab.com/x86-psABIs/x86-64-ABI)
>
> So far all my questions were on the i386 side of things, which isn't covered there.
>
> > and some TLS doc linkers there (e.g.
> > http://www.akkadia.org/drepper/tls.pdf)
>
> This is the doc I was referring to.
>
> As an aside - of course it shouldn't really take two docs to get a complete picture.
>
At least you can find " GDesc access model " in ABI doc.
> >> 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.
> >
> > It is defined in ABI doc.
>
> As per above - where? I can see the 64-bit counterpart of this being described in
> the x86-64 psABI, but that's not covering the case here.
>
> >>> + 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 ...
> >
> > It is mentioned in 4.1 of tls.pdf.
>
> Where? Please quote the sentence. I can't spot anything saying that it has to
> be %ebx. And similarly I can't spot anything indicating the non-SIB form would
> be okay to use; to the contrary it says "Note the form of the first operand of leal
> which forces the use of the SIB form ...". While that leaves open the use of a NOP
> (or address size override on the associated CALL, as per the checking the linker
> does) together with the non-SIB form,
This is the place, tls.pdf is encrypted and cannot be copied. I typed a sentence.
"To signal that this instruction is for the GNU variant of the access model the syntax @tlsgd(%ebx) is used."
It mentioned @tlsgd(%ebx), but I think the details are not clear enough, after all, the documentation has not been updated for 10 years. This place needs to be confirmed with the author.
> - constraints on register use then still ought to be the same between both
> variants,
> - the presence of the NOP then would also need checking (as the linker does,
> or else it might corrupt code).
>
I'll confirm this later.
> >>> + 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.
> >
> > There are two types of sequence listings in linker comments:
> >
> > /* Check transition from LD access model. Only
> > leal foo@tlsldm(%ebx), %eax
> > call ___tls_get_addr@PLT
> > or
> > leal foo@tlsldm(%reg), %eax
> > call *___tls_get_addr@GOT(%reg)
> > which may be converted to
> > addr32 call ___tls_get_addr
> > can transit to different access model. */
> >
> > They may be related to 4.2 of tls.pdf.
>
> They are corresponding to that section, yes, but they don't match it.
>
> Also note how all uses of addr32 in those comments are fishy: We're talking
> about 32-bit mode code there, so the 0x67 prefix is addr16.
>
> The recurring "%eax can't be used as the GOT base register since it is used to pass
> parameter to ___tls_get_addr" in linker comments are also unclear to me: The
> transitions eliminate the calls, and hence no arguments are passed anyway.
> Locally and transiently establishing the GOT pointer in %eax therefore looks
> entirely acceptable to me. It is clear from both the original and the transitioned-
> to code sequences that %eax would no longer hold the GOT pointer after these
> sequences. What instead is the case is that in e.g.
>
> leal foo@tlsldm(%reg), %eax
> call *___tls_get_addr@GOT(%reg)
>
> %reg is used again after the LEA, and hence its clobbering would be a problem.
> Yet that's nowhere near what those comments say.
>
This place needs to be confirmed with the author.
Thanks,
Lili.
> Jan
More information about the Binutils
mailing list