Commit 2a25448c by Igor Tsimbalist Committed by Igor Tsimbalist

Update x86 backend to enable Intel CET.

All platforms except i386 will report the error and do no
instrumentation with -finstrument-control-flow option. i386
will provide the implementation based on a specification
published by Intel for a new technology called Control-flow
Enforcement Technology (CET). The spec is available at

https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf

The implementation in this patch:
1) enables Control-flow Enforcement Technology (CET), published by
Intel. This part introduces i386 specific options -mcet, -mibt and
-mshstk, new instructions and intrinsics;

2) provides support for -fcf-protection option and 'nocf_check'
attribute by doing needed code instrumentation, which is based on
CET features.

gcc/

	* common/config/i386/i386-common.c (OPTION_MASK_ISA_IBT_SET): New.
	(OPTION_MASK_ISA_SHSTK_SET): Likewise.
	(OPTION_MASK_ISA_IBT_UNSET): Likewise.
	(OPTION_MASK_ISA_SHSTK_UNSET): Likewise.
	(ix86_handle_option): Add -mibt, -mshstk, -mcet handling.
	* config.gcc (extra_headers): Add cetintrin.h for x86 targets.
	(extra_objs): Add cet.o for Linux/x86 targets.
	(tmake_file): Add i386/t-cet for Linux/x86 targets.
	* config/i386/cet.c: New file.
	* config/i386/cetintrin.h: Likewise.
	* config/i386/t-cet: Likewise.
	* config/i386/cpuid.h (bit_SHSTK): New.
	(bit_IBT): Likewise.
	* config/i386/driver-i386.c (host_detect_local_cpu): Detect and
	pass IBT and SHSTK bits.
	* config/i386/i386-builtin-types.def
	(VOID_FTYPE_UNSIGNED_PVOID): New.
	(VOID_FTYPE_UINT64_PVOID): Likewise.
	* config/i386/i386-builtin.def: Add CET intrinsics.
	* config/i386/i386-c.c (ix86_target_macros_internal): Add
	OPTION_MASK_ISA_IBT, OPTION_MASK_ISA_SHSTK handling.
	* config/i386/i386-passes.def: Add pass_insert_endbranch pass.
	* config/i386/i386-protos.h (make_pass_insert_endbranch): New
	prototype.
	* config/i386/i386.c (rest_of_insert_endbranch): New.
	(pass_data_insert_endbranch): Likewise.
	(pass_insert_endbranch): Likewise.
	(make_pass_insert_endbranch): Likewise.
	(ix86_notrack_prefixed_insn_p): Likewise.
	(ix86_target_string): Add -mibt, -mshstk flags.
	(ix86_option_override_internal): Add flag_cf_protection
	processing.
	(ix86_valid_target_attribute_inner_p): Set OPT_mibt, OPT_mshstk.
	(ix86_print_operand): Add 'notrack' prefix output.
	(ix86_init_mmx_sse_builtins): Add CET intrinsics.
	(ix86_expand_builtin): Expand CET intrinsics.
	(x86_output_mi_thunk): Add 'endbranch' instruction.
	* config/i386/i386.h (TARGET_IBT): New.
	(TARGET_IBT_P): Likewise.
	(TARGET_SHSTK): Likewise.
	(TARGET_SHSTK_P): Likewise.
	   * config/i386/i386.md (unspecv): Add UNSPECV_NOP_RDSSP,
	UNSPECV_INCSSP, UNSPECV_SAVEPREVSSP, UNSPECV_RSTORSSP,
	UNSPECV_WRSS, UNSPECV_WRUSS, UNSPECV_SETSSBSY, UNSPECV_CLRSSBSY.
	(builtin_setjmp_setup): New pattern.
	(builtin_longjmp): Likewise.
	(rdssp<mode>): Likewise.
	(incssp<mode>): Likewise.
	(saveprevssp): Likewise.
	(rstorssp): Likewise.
	(wrss<mode>): Likewise.
	(wruss<mode>): Likewise.
	(setssbsy): Likewise.
	(clrssbsy): Likewise.
	(nop_endbr): Likewise.
	* config/i386/i386.opt: Add -mcet, -mibt, -mshstk and -mcet-switch
	options.
	* config/i386/immintrin.h: Include <cetintrin.h>.
	* config/i386/linux-common.h
	(file_end_indicate_exec_stack_and_cet): New prototype.
	(TARGET_ASM_FILE_END): New.

From-SVN: r253977
parent f6fd8f2b
2017-10-21 Igor Tsimbalist <igor.v.tsimbalist@intel.com>
* common/config/i386/i386-common.c (OPTION_MASK_ISA_IBT_SET): New.
(OPTION_MASK_ISA_SHSTK_SET): Likewise.
(OPTION_MASK_ISA_IBT_UNSET): Likewise.
(OPTION_MASK_ISA_SHSTK_UNSET): Likewise.
(ix86_handle_option): Add -mibt, -mshstk, -mcet handling.
* config.gcc (extra_headers): Add cetintrin.h for x86 targets.
(extra_objs): Add cet.o for Linux/x86 targets.
(tmake_file): Add i386/t-cet for Linux/x86 targets.
* config/i386/cet.c: New file.
* config/i386/cetintrin.h: Likewise.
* config/i386/t-cet: Likewise.
* config/i386/cpuid.h (bit_SHSTK): New.
(bit_IBT): Likewise.
* config/i386/driver-i386.c (host_detect_local_cpu): Detect and
pass IBT and SHSTK bits.
* config/i386/i386-builtin-types.def
(VOID_FTYPE_UNSIGNED_PVOID): New.
(VOID_FTYPE_UINT64_PVOID): Likewise.
* config/i386/i386-builtin.def: Add CET intrinsics.
* config/i386/i386-c.c (ix86_target_macros_internal): Add
OPTION_MASK_ISA_IBT, OPTION_MASK_ISA_SHSTK handling.
* config/i386/i386-passes.def: Add pass_insert_endbranch pass.
* config/i386/i386-protos.h (make_pass_insert_endbranch): New
prototype.
* config/i386/i386.c (rest_of_insert_endbranch): New.
(pass_data_insert_endbranch): Likewise.
(pass_insert_endbranch): Likewise.
(make_pass_insert_endbranch): Likewise.
(ix86_notrack_prefixed_insn_p): Likewise.
(ix86_target_string): Add -mibt, -mshstk flags.
(ix86_option_override_internal): Add flag_cf_protection
processing.
(ix86_valid_target_attribute_inner_p): Set OPT_mibt, OPT_mshstk.
(ix86_print_operand): Add 'notrack' prefix output.
(ix86_init_mmx_sse_builtins): Add CET intrinsics.
(ix86_expand_builtin): Expand CET intrinsics.
(x86_output_mi_thunk): Add 'endbranch' instruction.
* config/i386/i386.h (TARGET_IBT): New.
(TARGET_IBT_P): Likewise.
(TARGET_SHSTK): Likewise.
(TARGET_SHSTK_P): Likewise.
* config/i386/i386.md (unspecv): Add UNSPECV_NOP_RDSSP,
UNSPECV_INCSSP, UNSPECV_SAVEPREVSSP, UNSPECV_RSTORSSP,
UNSPECV_WRSS, UNSPECV_WRUSS, UNSPECV_SETSSBSY, UNSPECV_CLRSSBSY.
(builtin_setjmp_setup): New pattern.
(builtin_longjmp): Likewise.
(rdssp<mode>): Likewise.
(incssp<mode>): Likewise.
(saveprevssp): Likewise.
(rstorssp): Likewise.
(wrss<mode>): Likewise.
(wruss<mode>): Likewise.
(setssbsy): Likewise.
(clrssbsy): Likewise.
(nop_endbr): Likewise.
* config/i386/i386.opt: Add -mcet, -mibt, -mshstk and -mcet-switch
options.
* config/i386/immintrin.h: Include <cetintrin.h>.
* config/i386/linux-common.h
(file_end_indicate_exec_stack_and_cet): New prototype.
(TARGET_ASM_FILE_END): New.
2017-10-20 Jan Hubicka <hubicka@ucw.cz>
* x86-tune-costs.h (intel_cost, generic_cost): Fix move costs.
......@@ -138,6 +138,8 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA_PKU_SET OPTION_MASK_ISA_PKU
#define OPTION_MASK_ISA_RDPID_SET OPTION_MASK_ISA_RDPID
#define OPTION_MASK_ISA_GFNI_SET OPTION_MASK_ISA_GFNI
#define OPTION_MASK_ISA_IBT_SET OPTION_MASK_ISA_IBT
#define OPTION_MASK_ISA_SHSTK_SET OPTION_MASK_ISA_SHSTK
/* Define a set of ISAs which aren't available when a given ISA is
disabled. MMX and SSE ISAs are handled separately. */
......@@ -204,6 +206,8 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA_PKU_UNSET OPTION_MASK_ISA_PKU
#define OPTION_MASK_ISA_RDPID_UNSET OPTION_MASK_ISA_RDPID
#define OPTION_MASK_ISA_GFNI_UNSET OPTION_MASK_ISA_GFNI
#define OPTION_MASK_ISA_IBT_UNSET OPTION_MASK_ISA_IBT
#define OPTION_MASK_ISA_SHSTK_UNSET OPTION_MASK_ISA_SHSTK
/* SSE4 includes both SSE4.1 and SSE4.2. -mno-sse4 should the same
as -mno-sse4.1. */
......@@ -499,6 +503,35 @@ ix86_handle_option (struct gcc_options *opts,
}
return true;
case OPT_mcet:
case OPT_mibt:
if (value)
{
opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_IBT_SET;
opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_IBT_SET;
}
else
{
opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA_IBT_UNSET;
opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_IBT_UNSET;
}
if (code != OPT_mcet)
return true;
/* fall through. */
case OPT_mshstk:
if (value)
{
opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_SHSTK_SET;
opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_SHSTK_SET;
}
else
{
opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA_SHSTK_UNSET;
opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_SHSTK_UNSET;
}
return true;
case OPT_mavx5124fmaps:
if (value)
{
......
......@@ -378,7 +378,7 @@ i[34567]86-*-*)
avx512ifmaintrin.h avx512ifmavlintrin.h avx512vbmiintrin.h
avx512vbmivlintrin.h avx5124fmapsintrin.h avx5124vnniwintrin.h
avx512vpopcntdqintrin.h clwbintrin.h mwaitxintrin.h
clzerointrin.h pkuintrin.h sgxintrin.h"
clzerointrin.h pkuintrin.h sgxintrin.h cetintrin.h"
;;
x86_64-*-*)
cpu_type=i386
......@@ -402,7 +402,7 @@ x86_64-*-*)
avx512ifmaintrin.h avx512ifmavlintrin.h avx512vbmiintrin.h
avx512vbmivlintrin.h avx5124fmapsintrin.h avx5124vnniwintrin.h
avx512vpopcntdqintrin.h clwbintrin.h mwaitxintrin.h
clzerointrin.h pkuintrin.h sgxintrin.h"
clzerointrin.h pkuintrin.h sgxintrin.h cetintrin.h"
;;
ia64-*-*)
extra_headers=ia64intrin.h
......@@ -4551,7 +4551,8 @@ case ${target} in
i[34567]86-*-darwin* | x86_64-*-darwin*)
;;
i[34567]86-*-linux* | x86_64-*-linux*)
tmake_file="$tmake_file i386/t-linux"
extra_objs="${extra_objs} cet.o"
tmake_file="$tmake_file i386/t-linux i386/t-cet"
;;
i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu)
tmake_file="$tmake_file i386/t-kfreebsd"
......
/* Functions for CET/x86.
Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "output.h"
#include "linux-common.h"
void
file_end_indicate_exec_stack_and_cet (void)
{
file_end_indicate_exec_stack ();
if (flag_cf_protection == CF_NONE)
return;
unsigned int feature_1 = 0;
if (TARGET_IBT)
/* GNU_PROPERTY_X86_FEATURE_1_IBT. */
feature_1 |= 0x1;
if (TARGET_SHSTK)
/* GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
feature_1 |= 0x2;
if (feature_1)
{
int p2align = ptr_mode == SImode ? 2 : 3;
/* Generate GNU_PROPERTY_X86_FEATURE_1_XXX. */
switch_to_section (get_section (".note.gnu.property",
SECTION_NOTYPE, NULL));
ASM_OUTPUT_ALIGN (asm_out_file, p2align);
/* name length. */
fprintf (asm_out_file, ASM_LONG " 1f - 0f\n");
/* data length. */
fprintf (asm_out_file, ASM_LONG " 4f - 1f\n");
/* note type: NT_GNU_PROPERTY_TYPE_0. */
fprintf (asm_out_file, ASM_LONG " 5\n");
ASM_OUTPUT_LABEL (asm_out_file, "0");
/* vendor name: "GNU". */
fprintf (asm_out_file, STRING_ASM_OP " \"GNU\"\n");
ASM_OUTPUT_LABEL (asm_out_file, "1");
ASM_OUTPUT_ALIGN (asm_out_file, p2align);
/* pr_type: GNU_PROPERTY_X86_FEATURE_1_AND. */
fprintf (asm_out_file, ASM_LONG " 0xc0000002\n");
/* pr_datasz. */\
fprintf (asm_out_file, ASM_LONG " 3f - 2f\n");
ASM_OUTPUT_LABEL (asm_out_file, "2");
/* GNU_PROPERTY_X86_FEATURE_1_XXX. */
fprintf (asm_out_file, ASM_LONG " 0x%x\n", feature_1);
ASM_OUTPUT_LABEL (asm_out_file, "3");
ASM_OUTPUT_ALIGN (asm_out_file, p2align);
ASM_OUTPUT_LABEL (asm_out_file, "4");
}
}
/* Copyright (C) 2015-2017 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#if !defined _IMMINTRIN_H_INCLUDED
# error "Never use <cetintrin.h> directly; include <x86intrin.h> instead."
#endif
#ifndef _CETINTRIN_H_INCLUDED
#define _CETINTRIN_H_INCLUDED
#ifndef __SHSTK__
#pragma GCC push_options
#pragma GCC target ("shstk")
#define __DISABLE_SHSTK__
#endif /* __SHSTK__ */
extern __inline unsigned int
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_rdsspd (unsigned int __B)
{
return __builtin_ia32_rdsspd (__B);
}
#ifdef __x86_64__
extern __inline unsigned long long
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_rdsspq (unsigned long long __B)
{
return __builtin_ia32_rdsspq (__B);
}
#endif
extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_incsspd (unsigned int __B)
{
__builtin_ia32_incsspd (__B);
}
#ifdef __x86_64__
extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_incsspq (unsigned long long __B)
{
__builtin_ia32_incsspq (__B);
}
#endif
extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_saveprevssp (void)
{
__builtin_ia32_saveprevssp ();
}
extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_rstorssp (void *__B)
{
__builtin_ia32_rstorssp (__B);
}
extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_wrssd (unsigned int __B, void *__C)
{
__builtin_ia32_wrssd (__B, __C);
}
#ifdef __x86_64__
extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_wrssq (unsigned long long __B, void *__C)
{
__builtin_ia32_wrssq (__B, __C);
}
#endif
extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_wrussd (unsigned int __B, void *__C)
{
__builtin_ia32_wrussd (__B, __C);
}
#ifdef __x86_64__
extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_wrussq (unsigned long long __B, void *__C)
{
__builtin_ia32_wrussq (__B, __C);
}
#endif
extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_setssbsy (void)
{
__builtin_ia32_setssbsy ();
}
extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_clrssbsy (void *__B)
{
__builtin_ia32_clrssbsy (__B);
}
#ifdef __DISABLE_SHSTK__
#undef __DISABLE_SHSTK__
#pragma GCC pop_options
#endif /* __DISABLE_SHSTK__ */
#endif /* _CETINTRIN_H_INCLUDED. */
......@@ -97,6 +97,7 @@
#define bit_AVX512VBMI (1 << 1)
#define bit_PKU (1 << 3)
#define bit_OSPKE (1 << 4)
#define bit_SHSTK (1 << 7)
#define bit_GFNI (1 << 8)
#define bit_AVX512VPOPCNTDQ (1 << 14)
#define bit_RDPID (1 << 22)
......@@ -104,6 +105,7 @@
/* %edx */
#define bit_AVX5124VNNIW (1 << 2)
#define bit_AVX5124FMAPS (1 << 3)
#define bit_IBT (1 << 20)
/* XFEATURE_ENABLED_MASK register bits (%eax == 13, %ecx == 0) */
#define bit_BNDREGS (1 << 3)
......
......@@ -416,6 +416,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
unsigned int has_mwaitx = 0, has_clzero = 0, has_pku = 0, has_rdpid = 0;
unsigned int has_avx5124fmaps = 0, has_avx5124vnniw = 0;
unsigned int has_gfni = 0;
unsigned int has_ibt = 0, has_shstk = 0;
bool arch;
......@@ -509,6 +510,9 @@ const char *host_detect_local_cpu (int argc, const char **argv)
has_avx5124vnniw = edx & bit_AVX5124VNNIW;
has_avx5124fmaps = edx & bit_AVX5124FMAPS;
has_shstk = ecx & bit_SHSTK;
has_ibt = edx & bit_IBT;
}
if (max_level >= 13)
......@@ -1051,6 +1055,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
const char *pku = has_pku ? " -mpku" : " -mno-pku";
const char *rdpid = has_rdpid ? " -mrdpid" : " -mno-rdpid";
const char *gfni = has_gfni ? " -mgfni" : " -mno-gfni";
const char *ibt = has_ibt ? " -mibt" : " -mno-ibt";
const char *shstk = has_shstk ? " -mshstk" : " -mno-shstk";
options = concat (options, mmx, mmx3dnow, sse, sse2, sse3, ssse3,
sse4a, cx16, sahf, movbe, aes, sha, pclmul,
popcnt, abm, lwp, fma, fma4, xop, bmi, sgx, bmi2,
......@@ -1060,7 +1066,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
avx512cd, avx512pf, prefetchwt1, clflushopt,
xsavec, xsaves, avx512dq, avx512bw, avx512vl,
avx512ifma, avx512vbmi, avx5124fmaps, avx5124vnniw,
clwb, mwaitx, clzero, pku, rdpid, gfni, NULL);
clwb, mwaitx, clzero, pku, rdpid, gfni, ibt, shstk, NULL);
}
done:
......
......@@ -286,7 +286,9 @@ DEF_FUNCTION_TYPE (V8SI, V8SI)
DEF_FUNCTION_TYPE (VOID, PCVOID)
DEF_FUNCTION_TYPE (VOID, PVOID)
DEF_FUNCTION_TYPE (VOID, UINT64)
DEF_FUNCTION_TYPE (VOID, UINT64, PVOID)
DEF_FUNCTION_TYPE (VOID, UNSIGNED)
DEF_FUNCTION_TYPE (VOID, UNSIGNED, PVOID)
DEF_FUNCTION_TYPE (INT, PUSHORT)
DEF_FUNCTION_TYPE (INT, PUNSIGNED)
DEF_FUNCTION_TYPE (INT, PULONGLONG)
......
......@@ -2779,4 +2779,25 @@ BDESC (OPTION_MASK_ISA_XOP, CODE_FOR_xop_vpermil2v4sf3, "__builtin_ia32_vper
BDESC (OPTION_MASK_ISA_XOP, CODE_FOR_xop_vpermil2v4df3, "__builtin_ia32_vpermil2pd256", IX86_BUILTIN_VPERMIL2PD256, UNKNOWN, (int)MULTI_ARG_4_DF2_DI_I1)
BDESC (OPTION_MASK_ISA_XOP, CODE_FOR_xop_vpermil2v8sf3, "__builtin_ia32_vpermil2ps256", IX86_BUILTIN_VPERMIL2PS256, UNKNOWN, (int)MULTI_ARG_4_SF2_SI_I1)
BDESC_END (MULTI_ARG, MAX)
BDESC_END (MULTI_ARG, CET)
/* CET. */
BDESC_FIRST (cet, CET,
OPTION_MASK_ISA_SHSTK, CODE_FOR_incsspsi, "__builtin_ia32_incsspd", IX86_BUILTIN_INCSSPD, UNKNOWN, (int) VOID_FTYPE_UNSIGNED)
BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_incsspdi, "__builtin_ia32_incsspq", IX86_BUILTIN_INCSSPQ, UNKNOWN, (int) VOID_FTYPE_UINT64)
BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_saveprevssp, "__builtin_ia32_saveprevssp", IX86_BUILTIN_SAVEPREVSSP, UNKNOWN, (int) VOID_FTYPE_VOID)
BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_rstorssp, "__builtin_ia32_rstorssp", IX86_BUILTIN_RSTORSSP, UNKNOWN, (int) VOID_FTYPE_PVOID)
BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_wrsssi, "__builtin_ia32_wrssd", IX86_BUILTIN_WRSSD, UNKNOWN, (int) VOID_FTYPE_UNSIGNED_PVOID)
BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_wrssdi, "__builtin_ia32_wrssq", IX86_BUILTIN_WRSSQ, UNKNOWN, (int) VOID_FTYPE_UINT64_PVOID)
BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_wrusssi, "__builtin_ia32_wrussd", IX86_BUILTIN_WRUSSD, UNKNOWN, (int) VOID_FTYPE_UNSIGNED_PVOID)
BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_wrussdi, "__builtin_ia32_wrussq", IX86_BUILTIN_WRUSSQ, UNKNOWN, (int) VOID_FTYPE_UINT64_PVOID)
BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_setssbsy, "__builtin_ia32_setssbsy", IX86_BUILTIN_SETSSBSY, UNKNOWN, (int) VOID_FTYPE_VOID)
BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_clrssbsy, "__builtin_ia32_clrssbsy", IX86_BUILTIN_CLRSSBSY, UNKNOWN, (int) VOID_FTYPE_PVOID)
BDESC_END (CET, CET_NORMAL)
BDESC_FIRST (cet_rdssp, CET_NORMAL,
OPTION_MASK_ISA_SHSTK, CODE_FOR_rdsspsi, "__builtin_ia32_rdsspd", IX86_BUILTIN_RDSSPD, UNKNOWN, (int) UINT_FTYPE_UINT)
BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_rdsspdi, "__builtin_ia32_rdsspq", IX86_BUILTIN_RDSSPQ, UNKNOWN, (int) UINT64_FTYPE_UINT64)
BDESC_END (CET_NORMAL, MAX)
......@@ -459,6 +459,18 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__RDPID__");
if (isa_flag2 & OPTION_MASK_ISA_GFNI)
def_or_undef (parse_in, "__GFNI__");
if (isa_flag2 & OPTION_MASK_ISA_IBT)
{
def_or_undef (parse_in, "__IBT__");
if (flag_cf_protection != CF_NONE)
def_or_undef (parse_in, "__CET__");
}
if (isa_flag2 & OPTION_MASK_ISA_SHSTK)
{
def_or_undef (parse_in, "__SHSTK__");
if (flag_cf_protection != CF_NONE)
def_or_undef (parse_in, "__CET__");
}
if (TARGET_IAMCU)
{
def_or_undef (parse_in, "__iamcu");
......
......@@ -29,3 +29,5 @@ along with GCC; see the file COPYING3. If not see
/* Run the 64-bit STV pass before the CSE pass so that CONST0_RTX and
CONSTM1_RTX generated by the STV pass can be CSEed. */
INSERT_PASS_BEFORE (pass_cse2, 1, pass_stv, true /* timode_p */);
INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_endbranch);
......@@ -354,3 +354,4 @@ class rtl_opt_pass;
extern rtl_opt_pass *make_pass_insert_vzeroupper (gcc::context *);
extern rtl_opt_pass *make_pass_stv (gcc::context *);
extern rtl_opt_pass *make_pass_insert_endbranch (gcc::context *);
......@@ -169,6 +169,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_MWAITX_P(x) TARGET_ISA_MWAITX_P(x)
#define TARGET_PKU TARGET_ISA_PKU
#define TARGET_PKU_P(x) TARGET_ISA_PKU_P(x)
#define TARGET_IBT TARGET_ISA_IBT
#define TARGET_IBT_P(x) TARGET_ISA_IBT_P(x)
#define TARGET_SHSTK TARGET_ISA_SHSTK
#define TARGET_SHSTK_P(x) TARGET_ISA_SHSTK_P(x)
#define TARGET_LP64 TARGET_ABI_64
#define TARGET_LP64_P(x) TARGET_ABI_64_P(x)
......
......@@ -62,7 +62,7 @@
;; ; -- print a semicolon (after prefixes due to bug in older gas).
;; ~ -- print "i" if TARGET_AVX2, "f" otherwise.
;; ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
;; ! -- print MPX prefix for jxx/call/ret instructions if required.
;; ! -- print MPX or NOTRACK prefix for jxx/call/ret instructions if required.
(define_c_enum "unspec" [
;; Relocation specifiers
......@@ -274,6 +274,17 @@
;; For RDPID support
UNSPECV_RDPID
;; For CET support
UNSPECV_NOP_ENDBR
UNSPECV_NOP_RDSSP
UNSPECV_INCSSP
UNSPECV_SAVEPREVSSP
UNSPECV_RSTORSSP
UNSPECV_WRSS
UNSPECV_WRUSS
UNSPECV_SETSSBSY
UNSPECV_CLRSSBSY
])
;; Constants to represent rounding modes in the ROUND instruction
......@@ -18215,6 +18226,28 @@
"* return output_probe_stack_range (operands[0], operands[2]);"
[(set_attr "type" "multi")])
/* Additional processing for builtin_setjmp. Store the shadow stack pointer
as a forth element in jmpbuf. */
(define_expand "builtin_setjmp_setup"
[(match_operand 0 "address_operand")]
"TARGET_SHSTK"
{
if (flag_cf_protection & CF_RETURN)
{
rtx mem, reg_ssp;
mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
3 * GET_MODE_SIZE (Pmode)));
reg_ssp = gen_reg_rtx (Pmode);
emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
emit_insn ((Pmode == SImode)
? gen_rdsspsi (reg_ssp, reg_ssp)
: gen_rdsspdi (reg_ssp, reg_ssp));
emit_move_insn (mem, reg_ssp);
}
DONE;
})
(define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0))]
"!TARGET_64BIT && flag_pic"
......@@ -18235,6 +18268,83 @@
DONE;
})
(define_expand "builtin_longjmp"
[(match_operand 0 "address_operand")]
"TARGET_SHSTK"
{
rtx fp, lab, stack;
rtx jump, label, reg_adj, reg_ssp, reg_minus, mem_buf, tmp, clob;
machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
/* Adjust the shadow stack pointer (ssp) to the value saved in the
jmp_buf. The saving was done in the builtin_setjmp_setup. */
if (flag_cf_protection & CF_RETURN)
{
/* Get current shadow stack pointer. The code below will check if
SHSTK feature is enabled. If it's not enabled RDSSP instruction
is a NOP. */
reg_ssp = gen_reg_rtx (Pmode);
emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
emit_insn ((Pmode == SImode)
? gen_rdsspsi (reg_ssp, reg_ssp)
: gen_rdsspdi (reg_ssp, reg_ssp));
mem_buf = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
3 * GET_MODE_SIZE (Pmode))),
/* Compare through substraction the saved and the current ssp to decide
if ssp has to be adjusted. */
reg_minus = gen_reg_rtx (Pmode);
tmp = gen_rtx_SET (reg_minus, gen_rtx_MINUS (Pmode, reg_ssp, mem_buf));
clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
emit_insn (tmp);
/* Jump over adjustment code. */
label = gen_label_rtx ();
tmp = gen_rtx_REG (CCmode, FLAGS_REG);
tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
gen_rtx_LABEL_REF (VOIDmode, label),
pc_rtx);
jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
JUMP_LABEL (jump) = label;
/* Adjust the ssp. */
reg_adj = gen_reg_rtx (Pmode);
tmp = gen_rtx_SET (reg_adj,
gen_rtx_LSHIFTRT (Pmode, negate_rtx (Pmode, reg_minus),
GEN_INT (3)));
clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
emit_insn (tmp);
emit_insn ((Pmode == SImode)
? gen_incsspsi (reg_adj)
: gen_incsspdi (reg_adj));
emit_label (label);
LABEL_NUSES (label) = 1;
}
/* This code is the same as in expand_buildin_longjmp. */
fp = gen_rtx_MEM (Pmode, operands[0]);
lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
GET_MODE_SIZE (Pmode)));
stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, operands[0],
2 * GET_MODE_SIZE (Pmode)));
lab = copy_to_reg (lab);
emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
emit_move_insn (hard_frame_pointer_rtx, fp);
emit_stack_restore (SAVE_NONLOCAL, stack);
emit_use (hard_frame_pointer_rtx);
emit_use (stack_pointer_rtx);
emit_indirect_jump (lab);
})
;; Avoid redundant prefixes by splitting HImode arithmetic to SImode.
;; Do not split instructions with mask registers.
(define_split
......@@ -19855,6 +19965,83 @@
[(set_attr "length" "2")
(set_attr "memory" "unknown")])
;; CET instructions
(define_insn "rdssp<mode>"
[(set (match_operand:SWI48x 0 "register_operand" "=r")
(unspec_volatile:SWI48x
[(match_operand:SWI48x 1 "register_operand" "0")]
UNSPECV_NOP_RDSSP))]
"TARGET_SHSTK"
"rdssp<mskmodesuffix>\t%0"
[(set_attr "length" "4")
(set_attr "type" "other")])
(define_insn "incssp<mode>"
[(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")]
UNSPECV_INCSSP)]
"TARGET_SHSTK"
"incssp<mskmodesuffix>\t%0"
[(set_attr "length" "4")
(set_attr "type" "other")])
(define_insn "saveprevssp"
[(unspec_volatile [(const_int 0)] UNSPECV_SAVEPREVSSP)]
"TARGET_SHSTK"
"saveprevssp"
[(set_attr "length" "5")
(set_attr "type" "other")])
(define_insn "rstorssp"
[(unspec_volatile [(match_operand 0 "memory_operand" "m")]
UNSPECV_RSTORSSP)]
"TARGET_SHSTK"
"rstorssp\t%0"
[(set_attr "length" "5")
(set_attr "type" "other")])
(define_insn "wrss<mode>"
[(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")
(match_operand:SWI48x 1 "memory_operand" "m")]
UNSPECV_WRSS)]
"TARGET_SHSTK"
"wrss<mskmodesuffix>\t%0, %1"
[(set_attr "length" "3")
(set_attr "type" "other")])
(define_insn "wruss<mode>"
[(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")
(match_operand:SWI48x 1 "memory_operand" "m")]
UNSPECV_WRUSS)]
"TARGET_SHSTK"
"wruss<mskmodesuffix>\t%0, %1"
[(set_attr "length" "4")
(set_attr "type" "other")])
(define_insn "setssbsy"
[(unspec_volatile [(const_int 0)] UNSPECV_SETSSBSY)]
"TARGET_SHSTK"
"setssbsy"
[(set_attr "length" "4")
(set_attr "type" "other")])
(define_insn "clrssbsy"
[(unspec_volatile [(match_operand 0 "memory_operand" "m")]
UNSPECV_CLRSSBSY)]
"TARGET_SHSTK"
"clrssbsy\t%0"
[(set_attr "length" "4")
(set_attr "type" "other")])
(define_insn "nop_endbr"
[(unspec_volatile [(const_int 0)] UNSPECV_NOP_ENDBR)]
"TARGET_IBT"
"*
{ return (TARGET_64BIT)? \"endbr64\" : \"endbr32\"; }"
[(set_attr "length" "4")
(set_attr "length_immediate" "0")
(set_attr "modrm" "0")])
;; For RTM support
(define_expand "xbegin"
[(set (match_operand:SI 0 "register_operand")
(unspec_volatile:SI [(const_int 0)] UNSPECV_XBEGIN))]
......
......@@ -957,3 +957,23 @@ Attempt to avoid generating instruction sequences containing ret bytes.
mgeneral-regs-only
Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save
Generate code which uses only the general registers.
mcet
Target Report Var(flag_cet) Init(0)
Support Control-flow Enforcment Technology (CET) built-in functions
and code generation.
mibt
Target Report Mask(ISA_IBT) Var(ix86_isa_flags2) Save
Specifically enables an indirect branch tracking feature from Control-flow
Enforcment Technology (CET).
mshstk
Target Report Mask(ISA_SHSTK) Var(ix86_isa_flags2) Save
Specifically enables an shadow stack support feature from Control-flow
Enforcment Technology (CET).
mcet-switch
Target Report Undocumented Var(flag_cet_switch) Init(0)
Turn on CET instrumentation for switch statements, which use jump table and
indirect jump.
......@@ -90,6 +90,8 @@
#include <xtestintrin.h>
#include <cetintrin.h>
#ifndef __RDRND__
#pragma GCC push_options
#pragma GCC target("rdrnd")
......
......@@ -121,3 +121,8 @@ along with GCC; see the file COPYING3. If not see
#define CHKP_SPEC "\
%{!nostdlib:%{!nodefaultlibs:" LIBMPX_SPEC LIBMPXWRAPPERS_SPEC "}}" MPX_SPEC
#endif
extern void file_end_indicate_exec_stack_and_cet (void);
#undef TARGET_ASM_FILE_END
#define TARGET_ASM_FILE_END file_end_indicate_exec_stack_and_cet
# Copyright (C) 2017 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
# GCC is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GCC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
cet.o: $(srcdir)/config/i386/cet.c
$(COMPILE) $<
$(POSTCOMPILE)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment