[PATCH V5] x86: Add tls check in gas

Jan Beulich jbeulich@suse.com
Mon Sep 30 07:05:03 GMT 2024


On 19.09.2024 08:38, Cui, Lili wrote:
> +    case BFD_RELOC_386_TLS_GOTIE:
> +      /* Check GOTIE access model:
> +
> +	 subl foo@gotntpoff(%reg1), %reg2
> +	 movl foo@gotntpoff(%reg1), %reg2
> +	 addl foo@gotntpoff(%reg1), %reg2
> +
> +	 Memory operand: SIB is not supported.
> +       */
> +    case BFD_RELOC_386_TLS_IE_32:
> +      /* Check IE_32 access model:
> +
> +	 subl foo@gottpoff(%reg1), %reg2
> +	 movl foo@gottpoff(%reg1), %reg2
> +	 addl foo@gottpoff(%reg1), %reg2
> +
> +	 Memory operand: SIB is not supported.
> +       */
> +      if (i.tm.mnem_off != MN_sub
> +	  && i.tm.mnem_off != MN_add
> +	  && i.tm.mnem_off != MN_mov)
> +	return x86_tls_error_insn;
> +      if (i.op[1].regs->reg_type.bitfield.class != Reg
> +	  || i.op[0].regs->reg_type.bitfield.class
> +	  || i.imm_operands)

You may not de-reference i.op[0].regs for the intended forms at all. If
anything, i.op[0].disps may be de-referenced there.

You may also not de-reference i.op[1].regs until you've checked that
operand 1 actually is a register. There are insn forms after all where
operand 1 is a memory one.

Which member of the union is valid to de-reference can only be told by
inspecting i.types[] and/or i.tm.operand_types[] (when insns are more
constrained than mov/add/sub are, going from just
i.{reg,imm,mem,disp}_operands may also be possible, just to mention it).

I expect you want to check for operand counts first: No immediate one,
a single disp one, and a single register one. Then check that it's the
destination that's the register one. There may then not be any need to
access any i.op[<n>].reg anymore.

> +	return x86_tls_error_opcode;
> +      if (!i.base_reg)
> +	return x86_tls_error_no_base_reg;
> +      if (i.index_reg)
> +	return x86_tls_error_sib;
> +      if (!i.base_reg->reg_type.bitfield.dword)
> +	return x86_tls_error_base_reg_size;
> +      if (!i.op[1].regs->reg_type.bitfield.dword)
> +	return x86_tls_error_dest_32bit_reg_size;
> +      break;
> +
> +    case BFD_RELOC_386_TLS_IE:
> +      /* Check IE access model:
> +
> +	 movl foo@indntpoff, %reg32 --> Mod == 00 && r/m == 5
> +	 addl foo@indntpoff, %reg32 --> Mod == 00 && r/m == 5
> +       */
> +      if (i.tm.mnem_off != MN_add && i.tm.mnem_off != MN_mov)
> +	return x86_tls_error_insn;
> +      if (i.op[1].regs->reg_type.bitfield.class != Reg
> +	  || i.op[0].regs->reg_type.bitfield.class
> +	  || i.imm_operands)

Similar concerns here and ...

> +	return x86_tls_error_opcode;
> +      if (i.base_reg || i.index_reg)
> +	return x86_tls_error_require_no_base_index_reg;
> +      if (!i.op[1].regs->reg_type.bitfield.dword)
> +	return x86_tls_error_dest_32bit_reg_size;
> +      break;
> +
> +    case BFD_RELOC_X86_64_GOTTPOFF:
> +      /* Check GOTTPOFF access model:
> +
> +	 mov foo@gottpoff(%rip), %reg --> Memory Reg must be %rip.
> +	 add foo@gottpoff(%rip), %reg --> Memory Reg must be %rip.
> +	 add %reg1, foo@gottpoff(%rip), %reg2 --> Memory Reg must be %rip.
> +	 add foo@gottpoff(%rip), %reg1, %reg2 --> Memory Reg must be %rip.
> +       */
> +      if (i.tm.mnem_off != MN_add && i.tm.mnem_off != MN_mov)
> +	return x86_tls_error_insn;
> +      if (i.op[i.operands - 1].regs->reg_type.bitfield.class != Reg
> +	  || (i.op[0].regs->reg_type.bitfield.class
> +	      && i.tm.opcode_modifier.vexvvvv != VexVVVV_DST)
> +	  || i.imm_operands)

... here.

Jan


More information about the Binutils mailing list