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
>

Reply via email to