On Fri, Jun 15, 2018 at 2:59 PM H.J. Lu <hongjiu...@intel.com> wrote: > > Currently GCC inserts ENDBR instruction at entries of all non-static > functions, unless LTO compilation is used. Marking all functions, > which are not called indirectly with nocf_check attribute, is not > ideal since 99% of functions in a program may be of this kind. > > This patch adds -mmanual-endbr and cf_check function attribute. They > can be used together with -fcf-protection such that ENDBR instruction > is inserted only at entries of functions with cf_check attribute. It > can limit number of ENDBR instructions to reduce program size. > > OK for trubk?
I wonder if the linker could assist with ENDBR creation by redirecting all non-direct call relocs to a linker-generated stub with ENBR and a direct branch? Richard. > H.J. > ----- > gcc/ > > * config/i386/i386.c (rest_of_insert_endbranch): Insert ENDBR > at the function entry only when -mmanual-endbr isn't used or > there is cf_check function attribute. > (ix86_attribute_table): Add cf_check. > * config/i386/i386.opt: Add -mmanual-endbr. > * doc/extend.texi: Document cf_check attribute. > * doc/invoke.texi: Document -mmanual-endbr. > > gcc/testsuite/ > > * gcc.target/i386/cf_check-1.c: New test. > * gcc.target/i386/cf_check-2.c: Likewise. > * gcc.target/i386/cf_check-3.c: Likewise. > * gcc.target/i386/cf_check-4.c: Likewise. > * gcc.target/i386/cf_check-5.c: Likewise. > --- > gcc/config/i386/i386.c | 5 +++++ > gcc/config/i386/i386.opt | 5 +++++ > gcc/doc/extend.texi | 7 +++++++ > gcc/doc/invoke.texi | 9 ++++++++- > gcc/testsuite/gcc.target/i386/cf_check-1.c | 11 +++++++++++ > gcc/testsuite/gcc.target/i386/cf_check-2.c | 11 +++++++++++ > gcc/testsuite/gcc.target/i386/cf_check-3.c | 11 +++++++++++ > gcc/testsuite/gcc.target/i386/cf_check-4.c | 10 ++++++++++ > gcc/testsuite/gcc.target/i386/cf_check-5.c | 9 +++++++++ > 9 files changed, 77 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/gcc.target/i386/cf_check-1.c > create mode 100644 gcc/testsuite/gcc.target/i386/cf_check-2.c > create mode 100644 gcc/testsuite/gcc.target/i386/cf_check-3.c > create mode 100644 gcc/testsuite/gcc.target/i386/cf_check-4.c > create mode 100644 gcc/testsuite/gcc.target/i386/cf_check-5.c > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > index 95cfa05ce61..d356e0e7acd 100644 > --- a/gcc/config/i386/i386.c > +++ b/gcc/config/i386/i386.c > @@ -2604,6 +2604,9 @@ rest_of_insert_endbranch (void) > > if (!lookup_attribute ("nocf_check", > TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl))) > + && (!flag_manual_endbr > + || lookup_attribute ("cf_check", > + DECL_ATTRIBUTES (cfun->decl))) > && !cgraph_node::get (cfun->decl)->only_called_directly_p ()) > { > cet_eb = gen_nop_endbr (); > @@ -45896,6 +45899,8 @@ static const struct attribute_spec > ix86_attribute_table[] = > ix86_handle_fndecl_attribute, NULL }, > { "function_return", 1, 1, true, false, false, false, > ix86_handle_fndecl_attribute, NULL }, > + { "cf_check", 0, 0, true, false, false, false, > + ix86_handle_fndecl_attribute, NULL }, > > /* End element. */ > { NULL, 0, 0, false, false, false, false, NULL, NULL } > diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt > index a34d4acf1a2..aebc023420b 100644 > --- a/gcc/config/i386/i386.opt > +++ b/gcc/config/i386/i386.opt > @@ -1016,6 +1016,11 @@ Target Report Undocumented Var(flag_cet_switch) Init(0) > Turn on CET instrumentation for switch statements that use a jump table and > an indirect jump. > > +mmanual-endbr > +Target Report Var(flag_manual_endbr) Init(0) > +Insert ENDBR instruction at function entry only via cf_check attribute > +for CET instrumentation. > + > mforce-indirect-call > Target Report Var(flag_force_indirect_call) Init(0) > Make all function calls indirect. > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi > index e0a84b8b3c5..5fd4a1b22b0 100644 > --- a/gcc/doc/extend.texi > +++ b/gcc/doc/extend.texi > @@ -5864,6 +5864,13 @@ foo (void) > @} > @end smallexample > > +@item cf_check > +@cindex @code{cf_check} function attribute, x86 > + > +The @code{cf_check} attribute on a function is used to inform the > +compiler that ENDBR instruction should be placed at the function > +entry when @option{-fcf-protection=branch} is enabled. > + > @end table > > On the x86, the inliner does not inline a > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index 940b84697fa..7ec4267b7b1 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -1250,7 +1250,7 @@ See RS/6000 and PowerPC Options. > -msse4a -m3dnow -m3dnowa -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop @gol > -mlzcnt -mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mlwp @gol > -mmwaitx -mclzero -mpku -mthreads -mgfni -mvaes -mwaitpkg @gol > --mshstk -mforce-indirect-call -mavx512vbmi2 @gol > +-mshstk -mforce-indirect-call -mmanual-endbr -mavx512vbmi2 @gol > -mvpclmulqdq -mavx512bitalg -mmovdiri -mmovdir64b -mavx512vpopcntdq > -mcldemote @gol > -mms-bitfields -mno-align-stringops -minline-all-stringops @gol > @@ -27476,6 +27476,13 @@ Force all calls to functions to be indirect. This is > useful > when using Intel Processor Trace where it generates more precise timing > information for function calls. > > +@item -mmanual-endbr > +@opindex mmanual-endbr > +Insert ENDBR instruction at function entry only via the @code{cf_check} > +function attribute. This is useful when used with the option > +@option{-fcf-protection=branch} to control ENDBR insertion at the > +function entry. > + > @item -mcall-ms2sysv-xlogues > @opindex mcall-ms2sysv-xlogues > @opindex mno-call-ms2sysv-xlogues > diff --git a/gcc/testsuite/gcc.target/i386/cf_check-1.c > b/gcc/testsuite/gcc.target/i386/cf_check-1.c > new file mode 100644 > index 00000000000..c433eab854a > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/cf_check-1.c > @@ -0,0 +1,11 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fcf-protection -mmanual-endbr" } */ > +/* { dg-final { scan-assembler-not {\mendbr} } } */ > + > +extern void bar (void) __attribute__((__cf_check__)); > + > +void > +foo (void) > +{ > + bar (); > +} > diff --git a/gcc/testsuite/gcc.target/i386/cf_check-2.c > b/gcc/testsuite/gcc.target/i386/cf_check-2.c > new file mode 100644 > index 00000000000..e2b9c4dbcb2 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/cf_check-2.c > @@ -0,0 +1,11 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fcf-protection -mno-manual-endbr" } */ > +/* { dg-final { scan-assembler-times {\mendbr} 1 } } */ > + > +extern void bar (void) __attribute__((__cf_check__)); > + > +void > +foo (void) > +{ > + bar (); > +} > diff --git a/gcc/testsuite/gcc.target/i386/cf_check-3.c > b/gcc/testsuite/gcc.target/i386/cf_check-3.c > new file mode 100644 > index 00000000000..d835cc3a21b > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/cf_check-3.c > @@ -0,0 +1,11 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fcf-protection=none" } */ > +/* { dg-final { scan-assembler-not {\mendbr} } } */ > + > +extern void bar (void) __attribute__((__cf_check__)); > + > +void > +foo (void) > +{ > + bar (); > +} > diff --git a/gcc/testsuite/gcc.target/i386/cf_check-4.c > b/gcc/testsuite/gcc.target/i386/cf_check-4.c > new file mode 100644 > index 00000000000..d6cb27cf20b > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/cf_check-4.c > @@ -0,0 +1,10 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fcf-protection -mmanual-endbr" } */ > +/* { dg-final { scan-assembler-times {\mendbr} 1 } } */ > + > +extern void foo (void) __attribute__((__cf_check__)); > + > +void > +foo (void) > +{ > +} > diff --git a/gcc/testsuite/gcc.target/i386/cf_check-5.c > b/gcc/testsuite/gcc.target/i386/cf_check-5.c > new file mode 100644 > index 00000000000..f2c0c5c2c09 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/cf_check-5.c > @@ -0,0 +1,9 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fcf-protection -mmanual-endbr" } */ > +/* { dg-final { scan-assembler-times {\mendbr} 1 } } */ > + > +__attribute__((__cf_check__)) > +void > +foo (void) > +{ > +} > -- > 2.17.1 >