summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2011-05-08 01:49:32 +0000
committerchristos <christos@NetBSD.org>2011-05-08 01:49:32 +0000
commite39ea9293de9ff5af1cee76acb36416698d19ffa (patch)
treefc5135f754ea19173c5d9d0511016bfb1fd7e0f4 /gnu
parent4ab174eec9fd0f71070099fb60facc54a7d949bd (diff)
Add a no_stack_protector function attribute to localize the effect
of disabling stack protection on a function-by-function level, as opposed to per source file.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/dist/gcc4/gcc/c-common.c30
-rw-r--r--gnu/dist/gcc4/gcc/cfgexpand.c12
-rw-r--r--gnu/dist/gcc4/gcc/tree.h6
3 files changed, 45 insertions, 3 deletions
diff --git a/gnu/dist/gcc4/gcc/c-common.c b/gnu/dist/gcc4/gcc/c-common.c
index 03c855fa0d7..f50a37aab5e 100644
--- a/gnu/dist/gcc4/gcc/c-common.c
+++ b/gnu/dist/gcc4/gcc/c-common.c
@@ -529,6 +529,8 @@ static tree handle_tls_model_attribute (tree *, tree, tree, int,
bool *);
static tree handle_no_instrument_function_attribute (tree *, tree,
tree, int, bool *);
+static tree handle_no_stack_protector_function_attribute (tree *, tree,
+ tree, int, bool *);
static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
@@ -608,6 +610,8 @@ const struct attribute_spec c_common_attribute_table[] =
handle_weakref_attribute },
{ "no_instrument_function", 0, 0, true, false, false,
handle_no_instrument_function_attribute },
+ { "no_stack_protector", 0, 0, true, false, false,
+ handle_no_stack_protector_function_attribute },
{ "malloc", 0, 0, true, false, false,
handle_malloc_attribute },
{ "returns_twice", 0, 0, true, false, false,
@@ -5051,6 +5055,32 @@ handle_no_instrument_function_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Handle a "no_instrument_function" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_no_stack_protector_function_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ tree decl = *node;
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error ("%J%qE attribute applies only to functions", decl, name);
+ *no_add_attrs = true;
+ }
+ else if (DECL_INITIAL (decl))
+ {
+ error ("%Jcan%'t set %qE attribute after definition", decl, name);
+ *no_add_attrs = true;
+ }
+ else
+ DECL_NO_STACK_PROTECTOR_FUNCTION (decl) = 1;
+
+ return NULL_TREE;
+}
/* Handle a "malloc" attribute; arguments as in
struct attribute_spec.handler. */
diff --git a/gnu/dist/gcc4/gcc/cfgexpand.c b/gnu/dist/gcc4/gcc/cfgexpand.c
index 6fde1e36046..be678aba89a 100644
--- a/gnu/dist/gcc4/gcc/cfgexpand.c
+++ b/gnu/dist/gcc4/gcc/cfgexpand.c
@@ -862,6 +862,9 @@ stack_protect_decl_phase (tree decl)
unsigned int bits = stack_protect_classify_type (TREE_TYPE (decl));
int ret = 0;
+ if (DECL_NO_STACK_PROTECTOR_FUNCTION(decl))
+ return ret;
+
if (bits & SPCT_HAS_SMALL_CHAR_ARRAY)
has_short_buffer = true;
@@ -939,6 +942,7 @@ static void
expand_used_vars (void)
{
tree t, outer_block = DECL_INITIAL (current_function_decl);
+ bool stack_protect_func = !DECL_NO_STACK_PROTECTOR_FUNCTION (current_function_decl);
/* Compute the phase of the stack frame for this function. */
{
@@ -1008,7 +1012,7 @@ 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 && stack_protect_func)
add_stack_protection_conflicts ();
/* Now that we have collected all stack variables, and have computed a
@@ -1020,7 +1024,8 @@ expand_used_vars (void)
/* There are several conditions under which we should create a
stack guard: protect-all, alloca used, protected decls present. */
- if (flag_stack_protect == 2
+ if (stack_protect_func)
+ if (flag_stack_protect == 2
|| (flag_stack_protect
&& (current_function_calls_alloca || has_protected_decls)))
create_stack_guard ();
@@ -1595,7 +1600,8 @@ tree_expand_cfg (void)
expand_used_vars ();
/* Honor stack protection warnings. */
- if (warn_stack_protect)
+ if (warn_stack_protect &&
+ !DECL_NO_STACK_PROTECTOR_FUNCTION (current_function_decl))
{
if (current_function_calls_alloca)
warning (0, "not protecting local variables: variable length buffer");
diff --git a/gnu/dist/gcc4/gcc/tree.h b/gnu/dist/gcc4/gcc/tree.h
index 96bbfaffba3..087fac4db04 100644
--- a/gnu/dist/gcc4/gcc/tree.h
+++ b/gnu/dist/gcc4/gcc/tree.h
@@ -2680,6 +2680,11 @@ struct tree_decl_non_common GTY(())
#define DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT(NODE) \
(FUNCTION_DECL_CHECK (NODE)->function_decl.no_instrument_function_entry_exit)
+/* Used in FUNCTION_DECLs to indicate that the function should not be stack
+ protected */
+#define DECL_NO_STACK_PROTECTOR_FUNCTION(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.no_stack_protector_function)
+
/* Used in FUNCTION_DECLs to indicate that limit-stack-* should be
disabled in this function. */
#define DECL_NO_LIMIT_STACK(NODE) \
@@ -2746,6 +2751,7 @@ struct tree_function_decl GTY(())
unsigned regdecl_flag : 1;
unsigned inline_flag : 1;
unsigned no_instrument_function_entry_exit : 1;
+ unsigned no_stack_protector_function : 1;
unsigned no_limit_stack : 1;
ENUM_BITFIELD(built_in_class) built_in_class : 2;