public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: "Tsimbalist, Igor V" <igor.v.tsimbalist@intel.com>
To: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Cc: "richard.guenther@gmail.com" <richard.guenther@gmail.com>,
	"Tsimbalist, Igor V" <igor.v.tsimbalist@intel.com>
Subject: RE: 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling
Date: Tue, 19 Sep 2017 13:39:00 -0000	[thread overview]
Message-ID: <D511F25789BA7F4EBA64C8A63891A0028ADB5EF6@irsmsx105.ger.corp.intel.com> (raw)
In-Reply-To: <CAFiYyc20pZ7=8dN8KAS=q8GF0AGS1+rWLn_1D4X8WwAH5_t+kg@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 6387 bytes --]

Here is an updated patch (version #2). The main differences are:

- Change attribute and option names;
- Add additional parameter to gimple_build_call_from_tree by adding a type parameter and
  use it 'nocf_check' attribute propagation;
- Reimplement fixes in expand_call_stmt to propagate 'nocf_check' attribute;
- Consider 'nocf_check' attribute in Identical Code Folding (ICF) optimization;
- Add warning for type inconsistency regarding 'nocf_check' attribute;
- Many small fixes;

gcc/c-family/
	* c-attribs.c (handle_nocf_check_attribute): New function.
	(c_common_attribute_table): Add 'nocf_check' handling.
	* c-common.c (check_missing_format_attribute): New function.
	* c-common.h: Likewise.

gcc/c/
	* c-typeck.c (convert_for_assignment): Add check for nocf_check
	attribute.
	* gimple-parser.c: Add second argument NULL to
	gimple_build_call_from_tree.

gcc/cp/
	* typeck.c (convert_for_assignment): Add check for nocf_check
	attribute.

gcc/
	* cfgexpand.c (expand_call_stmt): Set REG_CALL_NOCF_CHECK for
	call insn.
	* combine.c (distribute_notes): Add REG_CALL_NOCF_CHECK handling.
	* common.opt: Add fcf-protection flag.
	* emit-rtl.c (try_split): Add REG_CALL_NOCF_CHECK handling.
	* flag-types.h: Add enum cf_protection_level.
	* gimple.c (gimple_build_call_from_tree): Add second parameter.
	Add 'nocf_check' attribute propagation to gimple call.
	* gimple.h (gf_mask): Add GF_CALL_NOCF_CHECK.
	(gimple_call_nocf_check_p): New function.
	(gimple_call_set_nocf_check): Likewise.
	* gimplify.c: Add second argument to gimple_build_call_from_tree.
	* ipa-icf.c: Add nocf_check attribute in statement hash.
	* recog.c (peep2_attempt): Add REG_CALL_NOCF_CHECK handling.
	* reg-notes.def: Add REG_NOTE (CALL_NOCF_CHECK).
	* toplev.c (process_options): Add flag_cf_protection handling.

Is it ok for trunk?

Thanks,
Igor


> -----Original Message-----
> From: Richard Biener [mailto:richard.guenther@gmail.com]
> Sent: Friday, September 15, 2017 2:14 PM
> To: Tsimbalist, Igor V <igor.v.tsimbalist@intel.com>
> Cc: gcc-patches@gcc.gnu.org
> Subject: Re: 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling
> 
> On Fri, Sep 15, 2017 at 1:12 PM, Tsimbalist, Igor V
> <igor.v.tsimbalist@intel.com> wrote:
> >> -----Original Message-----
> >> From: Tsimbalist, Igor V
> >> Sent: Tuesday, September 12, 2017 5:35 PM
> >> To: 'Richard Biener' <richard.guenther@gmail.com>
> >> Cc: 'gcc-patches@gcc.gnu.org' <gcc-patches@gcc.gnu.org>; Tsimbalist,
> >> Igor V <igor.v.tsimbalist@intel.com>
> >> Subject: RE: 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling
> >>
> >> > -----Original Message-----
> >> > From: Tsimbalist, Igor V
> >> > Sent: Friday, August 18, 2017 4:43 PM
> >> > To: 'Richard Biener' <richard.guenther@gmail.com>
> >> > Cc: gcc-patches@gcc.gnu.org; Tsimbalist, Igor V
> >> > <igor.v.tsimbalist@intel.com>
> >> > Subject: RE: 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling
> >> >
> >> > > -----Original Message-----
> >> > > From: Richard Biener [mailto:richard.guenther@gmail.com]
> >> > > Sent: Friday, August 18, 2017 3:53 PM
> >> > > To: Tsimbalist, Igor V <igor.v.tsimbalist@intel.com>
> >> > > Cc: gcc-patches@gcc.gnu.org
> >> > > Subject: Re: 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling
> >> > >
> >> > > On Fri, Aug 18, 2017 at 3:11 PM, Tsimbalist, Igor V
> >> > > <igor.v.tsimbalist@intel.com> wrote:
> >> > > >> -----Original Message-----
> >> > > >> From: Richard Biener [mailto:richard.guenther@gmail.com]
> >> > > >> Sent: Tuesday, August 15, 2017 3:43 PM
> >> > > >> To: Tsimbalist, Igor V <igor.v.tsimbalist@intel.com>
> >> > > >> Cc: gcc-patches@gcc.gnu.org
> >> > > >> Subject: Re:
> >> > > >> 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling
> >> > > >>
> >> > > >> On Tue, Aug 1, 2017 at 10:56 AM, Tsimbalist, Igor V
> >> > > >> <igor.v.tsimbalist@intel.com> wrote:
> >> > > >> > Part#1. Add generic part for Intel CET enabling.
> >> > > >> >
> >> > > >> > The spec is available at
> >> > > >> >
> >> > > >> > https://software.intel.com/sites/default/files/managed/4d/2a
> >> > > >> > /co nt ro l-f low-enforcement-technology-preview.pdf
> >
> > <..skipped..>
> >
> >> > > >> I think 'notrack' is somewhat unspecific of a name, what
> >> > > >> prevented you to use 'nocet'?
> >> > > >
> >> > > > Actually it's specific. The HW will have a prefix with exactly
> >> > > > this name and
> >> > > the same meaning. And I think, what is more important,
> 'track/notrack'
> >> > > gives better semantic for a user. CET is a name bound with Intel
> >> > > specific technology.
> >> > >
> >> > > But 'tracking' something is quite unspecific.  Tracking for what?
> >> > > 'no_verify_cf' (aka do not verify control flow) maybe?
> >> >
> >> > The name just  has to suggest the right semantic. 'no_verify_cf' is
> >> > good, let's use it unless different name appears.
> >> I have renamed all newly introduced function and macro names to use
> >> 'noverify_cf'. But I still keep the attribute name as 'notrack'.
> >> Historically the attribute name follows the public CET specification,
> >> which uses 'no-track prefix' wording. Is it ok to keep such attribute name?
> >
> > Here is an updated proposal about option name and attribute name.
> >
> > The new option has values to let a user to choose what control-flow
> protection to activate.
> >
> > -fcf-protection=[full|branch|return|none]
> >   branch - do control-flow protection for indirect jumps and calls
> >   return - do control-flow protection for function returns
> >   full - alias to specify both branch + return
> >   none - turn off protection. This value is needed when/if
> > cf-protection is turned on by default by driver in future
> >
> > Attribute name is the most tough one. Here are several names to evaluate:
> 'nocf_verify' or 'nocf_check', or to be more specific and to mimic option
> name 'nocf_branch_verify' or 'nocf_branch_check'. I would prefer
> 'nocf_check' as it applies to functions and function pointers so it's definitely
> related to a branch and it's a smaller one.
> >
> > If you ok with the new proposal I'll implement it in a general parts (code,
> documentation and tests) and resend these patches for review.
> 
> nocf_check sounds fine to me.
> 
> Richard.
> 
> > Thanks,
> > Igor
> >

[-- Attachment #2: 0001-Add-generic-part-for-Intel-CET-enabling-fcf-protecti.patch --]
[-- Type: application/octet-stream, Size: 22338 bytes --]

From 96237d5fad76ee60c4a7b188979bea3b47c44d9a Mon Sep 17 00:00:00 2001
From: Igor Tsimbalist <igor.v.tsimbalist@intel.com>
Date: Mon, 3 Jul 2017 17:11:58 +0300
Subject: [PATCH 1/3] Add generic part for Intel CET enabling: fcf-protection,
 nocf_check

The spec is available at

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

High-level design.
------------------

A proposal is to introduce a target independent flag
-fcf-protection=[none|branch|return|full] with a semantic to
instrument a code to control validness or integrity of control-flow
transfers using jump and call instructions. The main goal is to detect
and block a possible malware execution through transfer the execution
to unknown target address. Implementation could be either software or
target based. Any target platforms can provide their implementation
for instrumentation under this option.

When the -fcf-protection flag is set each implementation has
to check if a support exists for a target platform and report an error
if no support is found.

The compiler should instrument any control-flow transfer points in a
program (ex. call/jmp/ret) as well as any landing pads, which are
targets of control-flow transfers.

A new 'nocf_check' attribute is introduced to provide hand tuning
support. The attribute directs the compiler to skip a call to a
function and a function's landing pad from instrumentation. The
attribute can be used for function and pointer to function types,
otherwise it will be ignored. The attribute is saved in a type and
propagated to a GIMPLE call statement and later to a call instruction.

Currently all platforms except i386 will report the error and do no
instrumentation. i386 will provide the implementation based on a
specification published by Intel for a new technology called
Control-flow Enforcement Technology (CET).

gcc/c-family/

	* c-attribs.c (handle_nocf_check_attribute): New function.
	(c_common_attribute_table): Add 'nocf_check' handling.
	* c-common.c (check_missing_format_attribute): New function.
	* c-common.h: Likewise.

gcc/c/
	* c-typeck.c (convert_for_assignment): Add check for nocf_check
	attribute.
	* gimple-parser.c: Add second argument NULL to
	gimple_build_call_from_tree.

gcc/cp/
	* typeck.c (convert_for_assignment): Add check for nocf_check
        attribute.

gcc/

	* cfgexpand.c (expand_call_stmt): Set REG_CALL_NOCF_CHECK for
	call insn.
	* combine.c (distribute_notes): Add REG_CALL_NOCF_CHECK handling.
	* common.opt: Add fcf-protection flag.
	* emit-rtl.c (try_split): Add REG_CALL_NOCF_CHECK handling.
	* flag-types.h: Add enum cf_protection_level.
	* gimple.c (gimple_build_call_from_tree): Add second parameter.
	Add 'nocf_check' attribute propagation to gimple call.
	* gimple.h (gf_mask): Add GF_CALL_NOCF_CHECK.
	(gimple_call_nocf_check_p): New function.
	(gimple_call_set_nocf_check): Likewise.
	* gimplify.c: Add second argument to gimple_build_call_from_tree.
	* ipa-icf.c: Add nocf_check attribute in statement hash.
	* recog.c (peep2_attempt): Add REG_CALL_NOCF_CHECK handling.
	* reg-notes.def: Add REG_NOTE (CALL_NOCF_CHECK).
	* toplev.c (process_options): Add flag_cf_protection handling.
---
 gcc/c-family/c-attribs.c | 23 +++++++++++++++++++++++
 gcc/c-family/c-common.c  | 20 ++++++++++++++++++++
 gcc/c-family/c-common.h  |  1 +
 gcc/c/c-typeck.c         | 37 +++++++++++++++++++++++++++++++++++++
 gcc/c/gimple-parser.c    |  4 ++--
 gcc/cfgexpand.c          | 16 ++++++++++++++++
 gcc/combine.c            |  1 +
 gcc/common.opt           | 23 +++++++++++++++++++++++
 gcc/cp/typeck.c          | 39 +++++++++++++++++++++++++++++++++++++++
 gcc/emit-rtl.c           |  1 +
 gcc/flag-types.h         |  9 +++++++++
 gcc/gimple.c             | 18 +++++++++++++++++-
 gcc/gimple.h             | 22 +++++++++++++++++++++-
 gcc/gimplify.c           |  6 ++----
 gcc/ipa-icf.c            |  6 ++++++
 gcc/recog.c              |  1 +
 gcc/reg-notes.def        |  7 +++++++
 gcc/toplev.c             | 26 ++++++++++++++++++++++++++
 18 files changed, 252 insertions(+), 8 deletions(-)
---
 gcc/c-family/c-attribs.c | 23 +++++++++++++++++++++++
 gcc/c-family/c-common.c  | 20 ++++++++++++++++++++
 gcc/c-family/c-common.h  |  1 +
 gcc/c/c-typeck.c         | 37 +++++++++++++++++++++++++++++++++++++
 gcc/c/gimple-parser.c    |  4 ++--
 gcc/cfgexpand.c          | 16 ++++++++++++++++
 gcc/combine.c            |  1 +
 gcc/common.opt           | 23 +++++++++++++++++++++++
 gcc/cp/typeck.c          | 39 +++++++++++++++++++++++++++++++++++++++
 gcc/emit-rtl.c           |  1 +
 gcc/flag-types.h         |  9 +++++++++
 gcc/gimple.c             | 18 +++++++++++++++++-
 gcc/gimple.h             | 22 +++++++++++++++++++++-
 gcc/gimplify.c           |  6 ++----
 gcc/ipa-icf.c            |  6 ++++++
 gcc/recog.c              |  1 +
 gcc/reg-notes.def        |  7 +++++++
 gcc/toplev.c             | 26 ++++++++++++++++++++++++++
 18 files changed, 252 insertions(+), 8 deletions(-)

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 0337537..77d1909 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -65,6 +65,7 @@ static tree handle_asan_odr_indicator_attribute (tree *, tree, tree, int,
 static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
 static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
 static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nocf_check_attribute (tree *, tree, tree, int, bool *);
 static tree handle_noicf_attribute (tree *, tree, tree, int, bool *);
 static tree handle_noipa_attribute (tree *, tree, tree, int, bool *);
 static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
@@ -367,6 +368,8 @@ const struct attribute_spec c_common_attribute_table[] =
   { "patchable_function_entry",	1, 2, true, false, false,
 			      handle_patchable_function_entry_attribute,
 			      false },
+  { "nocf_check",		      0, 0, false, true, true,
+			      handle_nocf_check_attribute, false },
   { NULL,                     0, 0, false, false, false, NULL, false }
 };
 
@@ -783,6 +786,26 @@ handle_noclone_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
+/* Handle a "nocf_check" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_nocf_check_attribute (tree *node, tree name,
+			  tree ARG_UNUSED (args),
+			  int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_TYPE
+      && TREE_CODE (*node) != METHOD_TYPE
+      && TREE_CODE (*node) != FIELD_DECL
+      && TREE_CODE (*node) != TYPE_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "no_icf" attribute; arguments as in
    struct attribute_spec.handler.  */
 
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index b3ec3a0..78a730e 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -7253,6 +7253,26 @@ check_missing_format_attribute (tree ltype, tree rtype)
     return false;
 }
 
+/* Check for missing nocf_check attributes on function pointers.  LTYPE is
+   the new type or left-hand side type.  RTYPE is the old type or
+   right-hand side type.  Returns TRUE if LTYPE is missing the desired
+   attribute.  */
+
+bool
+check_missing_nocf_check_attribute (tree ltype, tree rtype)
+{
+  tree const ttr = TREE_TYPE (rtype), ttl = TREE_TYPE (ltype);
+  tree ra, la;
+
+  for (ra = TYPE_ATTRIBUTES (ttr); ra; ra = TREE_CHAIN (ra))
+    if (is_attribute_p ("nocf_check", TREE_PURPOSE (ra)))
+      break;
+  for (la = TYPE_ATTRIBUTES (ttl); la; la = TREE_CHAIN (la))
+    if (is_attribute_p ("nocf_check", TREE_PURPOSE (la)))
+      break;
+  return la != ra;
+}
+
 /* Setup a TYPE_DECL node as a typedef representation.
 
    X is a TYPE_DECL for a typedef statement.  Create a brand new
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 0de549d..829ea8e 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1123,6 +1123,7 @@ extern void preprocess_file (cpp_reader *);
 extern void pp_file_change (const line_map_ordinary *);
 extern void pp_dir_change (cpp_reader *, const char *);
 extern bool check_missing_format_attribute (tree, tree);
+extern bool check_missing_nocf_check_attribute (tree, tree);
 
 /* In c-omp.c  */
 struct omp_clause_mask
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index f45fd3c..59ae833 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6826,6 +6826,43 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 				        G_("return makes %q#v qualified function "
 					   "pointer from unqualified"),
 				        TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
+
+	      /* Check if the right-hand side and left-hand side mismatch in a
+		 'nocf_check' attribute.  Both cases could be harmful:
+		 NOCF = CF  Implicit control-flow check from CF
+			    is dropped as a future call is done through NOCF;
+		 CF = NOCF  Control-flow check will be done through the CF but
+			    the check is not expected by NOCF.  */
+	      if (warn_ignored_attributes
+		  && check_missing_nocf_check_attribute (type, rhstype))
+		{
+		  switch (errtype)
+		    {
+		    case ic_argpass:
+		      warning_at (expr_loc, OPT_Wattributes,
+				  "nocf_check attribute mismatch for"
+				  " argument %d of %qE",
+				  parmnum, rname);
+		      break;
+		    case ic_assign:
+		      warning_at (location, OPT_Wattributes,
+				  "nocf_check attribute mismatch for"
+				  "  assignment");
+		      break;
+		    case ic_init:
+		      warning_at (location, OPT_Wattributes,
+				  "nocf_check attribute mismatch for"
+				  " initialization");
+		      break;
+		    case ic_return:
+		      warning_at (location, OPT_Wattributes,
+				  "nocf_check attribute mismatch for"
+				  " return type");
+		      break;
+		    default:
+		      gcc_unreachable ();
+		    }
+		}
 	    }
 	}
       /* Avoid warning about the volatile ObjC EH puts on decls.  */
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 22f58f4..c2e31df 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -276,7 +276,7 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq *seq)
       && TREE_CODE (lhs.value) == CALL_EXPR)
     {
       gimple *call;
-      call = gimple_build_call_from_tree (lhs.value);
+      call = gimple_build_call_from_tree (lhs.value, NULL);
       gimple_seq_add_stmt (seq, call);
       gimple_set_location (call, loc);
       return;
@@ -407,7 +407,7 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq *seq)
       rhs = c_parser_gimple_unary_expression (parser);
       if (rhs.value != error_mark_node)
 	{
-	  gimple *call = gimple_build_call_from_tree (rhs.value);
+	  gimple *call = gimple_build_call_from_tree (rhs.value, NULL);
 	  gimple_call_set_lhs (call, lhs.value);
 	  gimple_seq_add_stmt (seq, call);
 	  gimple_set_location (call, loc);
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 7657a65..3bcaa4c 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2659,12 +2659,28 @@ expand_call_stmt (gcall *stmt)
 	  }
     }
 
+  rtx_insn *before_call = get_last_insn ();
   lhs = gimple_call_lhs (stmt);
   if (lhs)
     expand_assignment (lhs, exp, false);
   else
     expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
 
+  /* If the gimple call is an indirect call and has 'nocf_check'
+     attribute find a generated CALL insn to mark it as no
+     control-flow verification is needed.  */
+  if (gimple_call_nocf_check_p (stmt)
+      && !gimple_call_fndecl (stmt))
+    {
+      rtx_insn *last = get_last_insn ();
+      while (!CALL_P (last)
+	     && last != before_call)
+	last = PREV_INSN (last);
+
+      if (last != before_call)
+	add_reg_note (last, REG_CALL_NOCF_CHECK, const0_rtx);
+    }
+
   mark_transaction_restart_calls (stmt);
 }
 
diff --git a/gcc/combine.c b/gcc/combine.c
index 1832c3c..e0315fd 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -14151,6 +14151,7 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2,
 	case REG_SETJMP:
 	case REG_TM:
 	case REG_CALL_DECL:
+	case REG_CALL_NOCF_CHECK:
 	  /* These notes must remain with the call.  It should not be
 	     possible for both I2 and I3 to be a call.  */
 	  if (CALL_P (i3))
diff --git a/gcc/common.opt b/gcc/common.opt
index 1581ca8..b06bede 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1608,6 +1608,29 @@ finline-atomics
 Common Report Var(flag_inline_atomics) Init(1) Optimization
 Inline __atomic operations when a lock free instruction sequence is available.
 
+fcf-protection
+Common RejectNegative Alias(fcf-protection=,full)
+
+fcf-protection=
+Common Report Joined RejectNegative Enum(cf_protection_level) Var(flag_cf_protection) Init(CF_NONE)
+-fcf-protection=[full|branch|return|none]	Instrument functions with checks to verify jump/call/return control-flow transfer
+instructions have valid targets.
+
+Enum
+Name(cf_protection_level) Type(enum cf_protection_level) UnknownError(unknown Cotrol-Flow Protection Level %qs)
+
+EnumValue
+Enum(cf_protection_level) String(full) Value(CF_FULL)
+
+EnumValue
+Enum(cf_protection_level) String(branch) Value(CF_BRANCH)
+
+EnumValue
+Enum(cf_protection_level) String(return) Value(CF_RETURN)
+
+EnumValue
+Enum(cf_protection_level) String(none) Value(CF_NONE)
+
 finstrument-functions
 Common Report Var(flag_instrument_function_entry_exit)
 Instrument function entry and exit with profiling calls.
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 0a09998..3ddb41e 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8689,6 +8689,45 @@ convert_for_assignment (tree type, tree rhs,
 	  }
     }
 
+  /* Check if the right-hand side and left-hand side mismatch in a
+     'nocf_check' attribute.  Both cases could be harmful:
+     NOCF = CF	Implicit control-flow check from CF
+	    is dropped as a future call is done through NOCF;
+     CF = NOCF	Control-flow check will be done through the CF but
+	    the check is not expected by NOCF.  */
+
+  if (warn_ignored_attributes)
+    {
+      const enum tree_code codel = TREE_CODE (type);
+      if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
+	  && coder == codel
+	  && check_missing_nocf_check_attribute (type, rhstype))
+	{
+	  switch (errtype)
+	    {
+	    case ICR_ARGPASS:
+	      warning (OPT_Wattributes,
+		       "nocf_check attribute mismatch for argument %d of %qE",
+		       parmnum, fndecl);
+	      break;
+	    case ICR_ASSIGN:
+	      warning (OPT_Wattributes,
+		       "nocf_check attribute mismatch for assignment");
+	      break;
+	    case ICR_INIT:
+	      warning (OPT_Wattributes,
+		       "nocf_check attribute mismatch for initialization");
+	      break;
+	    case ICR_RETURN:
+	      warning (OPT_Wattributes,
+		       "nocf_check attribute mismatch for return type");
+	      break;
+	    default:
+	      gcc_unreachable ();
+	    }
+	}
+    }
+
   /* If -Wparentheses, warn about a = b = c when a has type bool and b
      does not.  */
   if (warn_parentheses
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index e36a7dd..b68729a 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -3791,6 +3791,7 @@ try_split (rtx pat, rtx_insn *trial, int last)
 	case REG_NORETURN:
 	case REG_SETJMP:
 	case REG_TM:
+	case REG_CALL_NOCF_CHECK:
 	  for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn))
 	    {
 	      if (CALL_P (insn))
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 4938f69..c0db3c9 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -318,4 +318,13 @@ enum gfc_convert
 };
 
 
+/* Control-Flow Protection values.  */
+enum cf_protection_level
+{
+  CF_NONE = 0,
+  CF_BRANCH = 1 << 0,
+  CF_RETURN = 1 << 1,
+  CF_FULL = CF_BRANCH | CF_RETURN,
+  CF_SET = 1 << 2
+};
 #endif /* ! GCC_FLAG_TYPES_H */
diff --git a/gcc/gimple.c b/gcc/gimple.c
index c4e6f81..701cb18 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -346,7 +346,7 @@ gimple_build_call_internal_vec (enum internal_fn fn, vec<tree> args)
    this fact.  */
 
 gcall *
-gimple_build_call_from_tree (tree t)
+gimple_build_call_from_tree (tree t, tree fnptrtype)
 {
   unsigned i, nargs;
   gcall *call;
@@ -380,6 +380,22 @@ gimple_build_call_from_tree (tree t)
   gimple_set_no_warning (call, TREE_NO_WARNING (t));
   gimple_call_set_with_bounds (call, CALL_WITH_BOUNDS_P (t));
 
+  if (fnptrtype)
+    {
+      gimple_call_set_fntype (call, TREE_TYPE (fnptrtype));
+
+      /* Check if a type has the no-track attribute and propagate
+	 it to the indirect CALL insn.  */
+      if (TREE_CODE (fnptrtype) != FUNCTION_DECL)
+	{
+	  gcc_assert (POINTER_TYPE_P (fnptrtype));
+	  tree fntype = TREE_TYPE (fnptrtype);
+
+	  if (lookup_attribute ("nocf_check", TYPE_ATTRIBUTES (fntype)))
+	    gimple_call_set_nocf_check (call, TRUE);
+	}
+    }
+
   return call;
 }
 
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 6213c49..5dcc03d 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -148,6 +148,7 @@ enum gf_mask {
     GF_CALL_WITH_BOUNDS 	= 1 << 8,
     GF_CALL_MUST_TAIL_CALL	= 1 << 9,
     GF_CALL_BY_DESCRIPTOR	= 1 << 10,
+    GF_CALL_NOCF_CHECK		= 1 << 11,
     GF_OMP_PARALLEL_COMBINED	= 1 << 0,
     GF_OMP_PARALLEL_GRID_PHONY = 1 << 1,
     GF_OMP_TASK_TASKLOOP	= 1 << 0,
@@ -1425,7 +1426,7 @@ gcall *gimple_build_call (tree, unsigned, ...);
 gcall *gimple_build_call_valist (tree, unsigned, va_list);
 gcall *gimple_build_call_internal (enum internal_fn, unsigned, ...);
 gcall *gimple_build_call_internal_vec (enum internal_fn, vec<tree> );
-gcall *gimple_build_call_from_tree (tree);
+gcall *gimple_build_call_from_tree (tree, tree);
 gassign *gimple_build_assign (tree, tree CXX_MEM_STAT_INFO);
 gassign *gimple_build_assign (tree, enum tree_code,
 			      tree, tree, tree CXX_MEM_STAT_INFO);
@@ -2893,6 +2894,25 @@ gimple_call_set_with_bounds (gimple *gs, bool with_bounds)
 }
 
 
+/* Return true if call GS is marked as no-track.  */
+
+static inline bool
+gimple_call_nocf_check_p (const gcall *gs)
+{
+  return (gs->subcode & GF_CALL_NOCF_CHECK) != 0;
+}
+
+/* Mark statement GS as no-track call.  */
+
+static inline void
+gimple_call_set_nocf_check (gcall *gs, bool nocf_check)
+{
+  if (nocf_check)
+    gs->subcode |= GF_CALL_NOCF_CHECK;
+  else
+    gs->subcode &= ~GF_CALL_NOCF_CHECK;
+}
+
 /* Return the target of internal call GS.  */
 
 static inline enum internal_fn
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 8b29a71..7d55625 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -3379,8 +3379,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
       /* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
 	 have to do is replicate it as a GIMPLE_CALL tuple.  */
       gimple_stmt_iterator gsi;
-      call = gimple_build_call_from_tree (*expr_p);
-      gimple_call_set_fntype (call, TREE_TYPE (fnptrtype));
+      call = gimple_build_call_from_tree (*expr_p, fnptrtype);
       notice_special_calls (call);
       if (EXPR_CILK_SPAWN (*expr_p))
         gimplify_cilk_detach (pre_p);
@@ -5656,8 +5655,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 						    CALL_EXPR_ARG (*from_p, 2));
 	  else
 	    {
-	      call_stmt = gimple_build_call_from_tree (*from_p);
-	      gimple_call_set_fntype (call_stmt, TREE_TYPE (fnptrtype));
+	      call_stmt = gimple_build_call_from_tree (*from_p, fnptrtype);
 	    }
 	}
       notice_special_calls (call_stmt);
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index 4d152ce..e666d5a 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -1422,6 +1422,7 @@ sem_function::init (void)
 	      }
 	  }
 
+	hstate.commit_flag ();
 	gcode_hash = hstate.end ();
 	bb_sizes.safe_push (nondbg_stmt_count);
 
@@ -1644,6 +1645,11 @@ sem_function::hash_stmt (gimple *stmt, inchash::hash &hstate)
 	  if (gimple_op (stmt, i))
 	    add_type (TREE_TYPE (gimple_op (stmt, i)), hstate);
 	}
+      /* Consider nocf_check attribute in hash as it affects code
+ 	 generation.  */
+      if (code == GIMPLE_CALL
+	  && flag_cf_protection & CF_BRANCH)
+	hstate.add_flag (gimple_call_nocf_check_p (as_a <gcall *> (stmt)));
     default:
       break;
     }
diff --git a/gcc/recog.c b/gcc/recog.c
index 78c26d6..ec51cd4 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -3382,6 +3382,7 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
 	  case REG_NORETURN:
 	  case REG_SETJMP:
 	  case REG_TM:
+	  case REG_CALL_NOCF_CHECK:
 	    add_reg_note (new_insn, REG_NOTE_KIND (note),
 			  XEXP (note, 0));
 	    break;
diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
index 943eff4..cc456a6 100644
--- a/gcc/reg-notes.def
+++ b/gcc/reg-notes.def
@@ -228,3 +228,10 @@ REG_NOTE (RETURNED)
    The decl might not be available in the call due to splitting of the call
    insn.  This note is a SYMBOL_REF.  */
 REG_NOTE (CALL_DECL)
+
+/* Indicate that a call should not be verified for control-flow consistency.
+   The target address of the call is assumed as a valid address and no check
+   to validate a branch to the target address is needed.  The call is marked
+   when a called function has a 'notrack' attribute.  This note is used by the
+   compiler when the option -fcf-protection=branch is specified.  */
+REG_NOTE (CALL_NOCF_CHECK)
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 7d2b8ff..9293172 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1297,6 +1297,32 @@ process_options (void)
 	   "-floop-parallelize-all)");
 #endif
 
+  if (flag_cf_protection != CF_NONE
+	   && flag_cf_protection != CF_SET)
+    {
+      if (flag_cf_protection == CF_FULL)
+	{
+	  error_at (UNKNOWN_LOCATION,
+		    "%<-fcf-protection=full%> is not supported for this "
+		    "target");
+	  flag_cf_protection = CF_NONE;
+	}
+      if (flag_cf_protection == CF_BRANCH)
+	{
+	  error_at (UNKNOWN_LOCATION,
+		    "%<-fcf-protection=branch%> is not supported for this "
+		    "target");
+	  flag_cf_protection = CF_NONE;
+	}
+      if (flag_cf_protection == CF_RETURN)
+	{
+	  error_at (UNKNOWN_LOCATION,
+		    "%<-fcf-protection=return%> is not supported for this "
+		    "target");
+	  flag_cf_protection = CF_NONE;
+	}
+    }
+
   if (flag_check_pointer_bounds)
     {
       if (targetm.chkp_bound_mode () == VOIDmode)
-- 
1.8.3.1


  reply	other threads:[~2017-09-19 13:39 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-01  8:56 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Tsimbalist, Igor V
2017-08-15 14:08 ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Richard Biener
2017-08-18 14:01   ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Tsimbalist, Igor V
2017-08-18 14:06     ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Richard Biener
2017-08-18 14:58       ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Tsimbalist, Igor V
2017-09-12 15:34       ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Tsimbalist, Igor V
2017-09-15 11:12       ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Tsimbalist, Igor V
2017-09-15 12:14         ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Richard Biener
2017-09-19 13:39           ` Tsimbalist, Igor V [this message]
2017-09-28 22:44             ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Jeff Law
2017-09-29 14:31               ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Tsimbalist, Igor V
2017-09-29 16:04                 ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Tsimbalist, Igor V
2017-10-05 10:20                   ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Tsimbalist, Igor V
2017-10-12  6:26                     ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Jeff Law
2017-10-12  8:33                       ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Tsimbalist, Igor V
2017-10-12 15:15                         ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Jeff Law
2017-08-25 21:03   ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Jeff Law
2017-09-12 15:40     ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Tsimbalist, Igor V
2017-09-13 19:05       ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Jeff Law
2017-08-25 21:05 ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Jeff Law
2017-09-12 15:59   ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Tsimbalist, Igor V
2017-09-13 18:56     ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Jeff Law
2017-09-13 17:08   ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Tsimbalist, Igor V
2017-09-13 19:01     ` 0001-Part-1.-Add-generic-part-for-Intel-CET-enabling Jeff Law

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=D511F25789BA7F4EBA64C8A63891A0028ADB5EF6@irsmsx105.ger.corp.intel.com \
    --to=igor.v.tsimbalist@intel.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=richard.guenther@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).