common.opt: New option -fstack-protector-explicit.
authorMarcos Diaz <marcos.diaz@tallertechnologies.com>
Thu, 15 Jan 2015 05:29:12 +0000 (05:29 +0000)
committerJeff Law <law@gcc.gnu.org>
Thu, 15 Jan 2015 05:29:12 +0000 (22:29 -0700)
2015-01-14  Marcos Diaz <marcos.diaz@tallertechnologies.com>

* common.opt: New option -fstack-protector-explicit.
* cfgexpand.c (SPCT_FLAG_EXPLICIT): New enum.
(stack_protect_decl_phase): Handle stack_protect attribute for
explicit stack protection requests.
(expand_used_vars): Similarly.
* doc/cpp.texi (__SSP_EXPLICIT__): Document predefined macro.
* doc/extend.texi: Add documentation for "stack_protect" attribute.
* doc/invoke.texi: Add documentation for -fstack-protector-explicit.

* c-cppbuiltin.c (c_cpp_builtins): New cpp define __SSP_EXPLICIT__
for the new option fstack-protector_explicit.
* c-common.c (c_common_attribute_table): Add stack_protect attribute.
(handle_stack_protect_attribute): New function.

* gcc.dg/stackprotectexplicit1.c: New test.
* g++.dg/stackprotectexplicit2.c: New test.

From-SVN: r219633

12 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-cppbuiltin.c
gcc/cfgexpand.c
gcc/common.opt
gcc/doc/cpp.texi
gcc/doc/extend.texi
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/stackprotectexplicit2.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/stackprotectexplicit1.c [new file with mode: 0644]

index 5e959c20f984ff9d4251757d1d986a6dda81934b..701c6c6734af139d452952a71730dc943e9f8d5e 100644 (file)
@@ -1,3 +1,14 @@
+2015-01-14  Marcos Diaz <marcos.diaz@tallertechnologies.com>
+
+       * common.opt: New option -fstack-protector-explicit.
+       * cfgexpand.c (SPCT_FLAG_EXPLICIT): New enum.
+       (stack_protect_decl_phase): Handle stack_protect attribute for
+       explicit stack protection requests.
+       (expand_used_vars): Similarly.
+       * doc/cpp.texi (__SSP_EXPLICIT__): Document predefined macro.
+       * doc/extend.texi: Add documentation for "stack_protect" attribute.
+       * doc/invoke.texi: Add documentation for -fstack-protector-explicit.
+
 2015-01-14  Oleg Endo  <olegendo@gcc.gnu.org>
 
        PR target/53988
index 1efb75ac13cb747007a32635f05cb27352f767c1..976404579d2f8b92207b2d16cee9d068b01303b2 100644 (file)
@@ -1,3 +1,10 @@
+2015-01-14  Marcos Diaz <marcos.diaz@tallertechnologies.com>
+
+       * c-cppbuiltin.c (c_cpp_builtins): New cpp define __SSP_EXPLICIT__
+       for the new option fstack-protector_explicit.
+       * c-common.c (c_common_attribute_table): Add stack_protect attribute.
+       (handle_stack_protect_attribute): New function.
+
 2015-01-13  Martin Uecker <uecker@eecs.berkeley.edu>
 
        * c.opt: New option -Warray-bounds=.
index 29cab015a1e05b6212bf3f7c02c979ab18329ce4..054f5a0e94af58fac7e56257a898e77b1562d876 100644 (file)
@@ -327,6 +327,7 @@ static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
                                                         int, bool *);
 static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int,
                                                    bool *);
+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_leaf_attribute (tree *, tree, tree, int, bool *);
@@ -657,6 +658,8 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_noreturn_attribute, false },
   { "volatile",               0, 0, true,  false, false,
                              handle_noreturn_attribute, false },
+  { "stack_protect",          0, 0, true,  false, false,
+                             handle_stack_protect_attribute, false },
   { "noinline",               0, 0, true,  false, false,
                              handle_noinline_attribute, false },
   { "noclone",                0, 0, true,  false, false,
@@ -6769,6 +6772,25 @@ handle_no_sanitize_undefined_attribute (tree *node, tree name, tree, int,
   return NULL_TREE;
 }
 
+/* Handle a "stack_protect" attribute; arguments as in
+   struct attribute_spec.handler.  */
+static tree
+handle_stack_protect_attribute (tree *node, tree name, tree, int,
+                               bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+  else
+    DECL_ATTRIBUTES (*node) 
+      = tree_cons (get_identifier ("stack_protect"),
+                  NULL_TREE, DECL_ATTRIBUTES (*node));
+
+  return NULL_TREE;
+}
+
 /* Handle a "noinline" attribute; arguments as in
    struct attribute_spec.handler.  */
 
index 229a316a886e8421678003aa2e8aadf6a29d81a6..0b00d59fd36e19d141f99a8504b6bc43291a44b7 100644 (file)
@@ -1212,6 +1212,8 @@ c_cpp_builtins (cpp_reader *pfile)
   /* Make the choice of the stack protector runtime visible to source code.
      The macro names and values here were chosen for compatibility with an
      earlier implementation, i.e. ProPolice.  */
+  if (flag_stack_protect == 4)
+    cpp_define (pfile, "__SSP_EXPLICIT__=4");
   if (flag_stack_protect == 3)
     cpp_define (pfile, "__SSP_STRONG__=3");
   if (flag_stack_protect == 2)
index 8926e8f64c9b47602c9de8380f04de23a9163b63..c92c786ea388576b31022ce6f9b74eb9cde66cf0 100644 (file)
@@ -1411,7 +1411,8 @@ clear_tree_used (tree block)
 enum {
   SPCT_FLAG_DEFAULT = 1,
   SPCT_FLAG_ALL = 2,
-  SPCT_FLAG_STRONG = 3
+  SPCT_FLAG_STRONG = 3,
+  SPCT_FLAG_EXPLICIT = 4
 };
 
 /* Examine TYPE and determine a bit mask of the following features.  */
@@ -1484,7 +1485,10 @@ stack_protect_decl_phase (tree decl)
     has_short_buffer = true;
 
   if (flag_stack_protect == SPCT_FLAG_ALL
-      || flag_stack_protect == SPCT_FLAG_STRONG)
+      || flag_stack_protect == SPCT_FLAG_STRONG
+      || (flag_stack_protect == SPCT_FLAG_EXPLICIT
+         && lookup_attribute ("stack_protect",
+                              DECL_ATTRIBUTES (current_function_decl))))
     {
       if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY))
          && !(bits & SPCT_HAS_AGGREGATE))
@@ -1859,7 +1863,11 @@ expand_used_vars (void)
 
       /* If stack protection is enabled, we don't share space between
         vulnerable data and non-vulnerable data.  */
-      if (flag_stack_protect)
+      if (flag_stack_protect != 0
+         && (flag_stack_protect != SPCT_FLAG_EXPLICIT
+             || (flag_stack_protect == SPCT_FLAG_EXPLICIT
+                 && lookup_attribute ("stack_protect",
+                                      DECL_ATTRIBUTES (current_function_decl)))))
        add_stack_protection_conflicts ();
 
       /* Now that we have collected all stack variables, and have computed a
@@ -1877,15 +1885,24 @@ expand_used_vars (void)
 
     case SPCT_FLAG_STRONG:
       if (gen_stack_protect_signal
-         || cfun->calls_alloca || has_protected_decls)
+         || cfun->calls_alloca || has_protected_decls
+         || lookup_attribute ("stack_protect",
+                              DECL_ATTRIBUTES (current_function_decl)))
        create_stack_guard ();
       break;
 
     case SPCT_FLAG_DEFAULT:
-      if (cfun->calls_alloca || has_protected_decls)
+      if (cfun->calls_alloca || has_protected_decls
+         || lookup_attribute ("stack_protect",
+                              DECL_ATTRIBUTES (current_function_decl)))
        create_stack_guard ();
       break;
 
+    case SPCT_FLAG_EXPLICIT:
+      if (lookup_attribute ("stack_protect",
+                           DECL_ATTRIBUTES (current_function_decl)))
+       create_stack_guard ();
+      break;
     default:
       ;
     }
@@ -1911,7 +1928,11 @@ expand_used_vars (void)
          expand_stack_vars (stack_protect_decl_phase_1, &data);
 
          /* Phase 2 contains other kinds of arrays.  */
-         if (flag_stack_protect == 2)
+         if (flag_stack_protect == SPCT_FLAG_ALL
+             || flag_stack_protect == SPCT_FLAG_STRONG
+             || (flag_stack_protect == SPCT_FLAG_EXPLICIT
+                 && lookup_attribute ("stack_protect",
+                                      DECL_ATTRIBUTES (current_function_decl))))
            expand_stack_vars (stack_protect_decl_phase_2, &data);
        }
 
index 3d1987559a881d42443989839a412fe051dc75dd..c3219604836d468a6389c1070118b394d2c192af 100644 (file)
@@ -2093,6 +2093,10 @@ fstack-protector-strong
 Common Report RejectNegative Var(flag_stack_protect, 3)
 Use a smart stack protection method for certain functions
 
+fstack-protector-explicit
+Common Report RejectNegative Var(flag_stack_protect, 4)
+Use stack protection method only for functions with the stack_protect attribute
+
 fstack-usage
 Common RejectNegative Var(flag_stack_usage)
 Output stack usage information on a per-function basis
index e94bdf74e112456b5d1d138eecf27759fc59c0f3..10b72e7e61b07138e5c72f79f258d4d7d07184a7 100644 (file)
@@ -2351,6 +2351,10 @@ in use.
 This macro is defined, with value 3, when @option{-fstack-protector-strong} is
 in use.
 
+@item __SSP_EXPLICIT__
+This macro is defined, with value 4, when @option{-fstack-protector-explicit} is
+in use.
+
 @item __SANITIZE_ADDRESS__
 This macro is defined, with value 1, when @option{-fsanitize=address}
 or @option{-fsanitize=kernel-address} are in use.
index 942a6bc8715ceddf577c9f25f40b5649e519cb2d..bf6d7102147deacff3ac0661aa9bba6d44396939 100644 (file)
@@ -2207,7 +2207,7 @@ attributes are currently defined for functions on all targets:
 @code{no_sanitize_address}, @code{no_address_safety_analysis},
 @code{no_sanitize_thread},
 @code{no_sanitize_undefined}, @code{no_reorder}, @code{bnd_legacy},
-@code{bnd_instrument},
+@code{bnd_instrument}, @code{stack_protect},
 @code{error} and @code{warning}.
 Several other attributes are defined for functions on particular
 target systems.  Other attributes, including @code{section} are
@@ -3444,6 +3444,12 @@ prologue which decides whether to split the stack.  Functions with the
 @code{no_split_stack} attribute do not have that prologue, and thus
 may run with only a small amount of stack space available.
 
+@item stack_protect
+@cindex @code{stack_protect} function attribute
+This function attribute make a stack protection of the function if 
+flags @option{fstack-protector} or @option{fstack-protector-strong}
+or @option{fstack-protector-explicit} are set.
+
 @item noinline
 @cindex @code{noinline} function attribute
 This function attribute prevents a function from being considered for
index 748c70a158c5488bb98b68236a1e3c6463615f90..638ed9ac0e1f1d4ee162090bda95da143815dc6a 100644 (file)
@@ -428,8 +428,9 @@ Objective-C and Objective-C++ Dialects}.
 -fsel-sched-pipelining -fsel-sched-pipelining-outer-loops @gol
 -fsemantic-interposition @gol
 -fshrink-wrap -fsignaling-nans -fsingle-precision-constant @gol
--fsplit-ivs-in-unroller -fsplit-wide-types -fssa-phiopt -fstack-protector @gol
--fstack-protector-all -fstack-protector-strong -fstrict-aliasing @gol
+-fsplit-ivs-in-unroller -fsplit-wide-types -fssa-phiopt @gol
+-fstack-protector -fstack-protector-all -fstack-protector-strong @gol
+-fstack-protector-explicit -fstrict-aliasing @gol
 -fstrict-overflow -fthread-jumps -ftracer -ftree-bit-ccp @gol
 -ftree-builtin-call-dce -ftree-ccp -ftree-ch @gol
 -ftree-coalesce-inline-vars -ftree-coalesce-vars -ftree-copy-prop @gol
@@ -9838,6 +9839,11 @@ Like @option{-fstack-protector} but includes additional functions to
 be protected --- those that have local array definitions, or have
 references to local frame addresses.
 
+@item -fstack-protector-explicit
+@opindex fstack-protector-explicit
+Like @option{-fstack-protector} but only protects those functions which
+have the @code{stack_protect} attribute
+
 @item -fsection-anchors
 @opindex fsection-anchors
 Try to reduce the number of symbolic address calculations by using
index 4be48a15f21af8c6d1bfeffcad2fd8b33e7eb027..1c53160960f02118a52a82c4b93e326dc06bae96 100644 (file)
@@ -1,3 +1,8 @@
+2015-01-14  Marcos Diaz <marcos.diaz@tallertechnologies.com>
+
+       * gcc.dg/stackprotectexplicit1.c: New test.
+       * g++.dg/stackprotectexplicit2.c: New test.
+
 2015-01-14  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR target/61933
diff --git a/gcc/testsuite/g++.dg/stackprotectexplicit2.C b/gcc/testsuite/g++.dg/stackprotectexplicit2.C
new file mode 100644 (file)
index 0000000..9cf9ab9
--- /dev/null
@@ -0,0 +1,27 @@
+/* Test that stack protection is done on chosen functions. */
+
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -fstack-protector-explicit" } */
+
+int A()
+{
+       int A[23];
+       char b[22];
+}
+
+int __attribute__((stack_protect)) B()
+{
+       int a;
+       int b;
+       return a+b;
+}
+
+int __attribute__((stack_protect)) c()
+{
+       int a;
+       char b[34];
+       return 0;
+}
+
+
+/* { dg-final { scan-assembler-times "stack_chk_fail" 2 } } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.dg/stackprotectexplicit1.c b/gcc/testsuite/gcc.dg/stackprotectexplicit1.c
new file mode 100644 (file)
index 0000000..658c297
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do run { target native } } */
+/* { dg-options "-fstack-protector-explicit" } */
+/* { dg-require-effective-target fstack_protector } */
+
+#include <stdlib.h>
+
+void
+__stack_chk_fail (void)
+{
+  exit (0); /* pass */
+}
+
+int __attribute__((stack_protect)) main ()
+{
+  int i;
+  char foo[255];
+
+  // smash stack
+  for (i = 0; i <= 400; i++)
+    foo[i] = 42;
+
+  return 1; /* fail */
+}