diff options
author | shenhan <shenhan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-05-07 21:33:01 +0000 |
---|---|---|
committer | shenhan <shenhan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-05-07 21:33:01 +0000 |
commit | b156ec373ccf27f4fcce7972de5e043d35acea43 (patch) | |
tree | 6334fbdf8bc242f31e69b43f0b15f26ac842169e /gcc/cfgexpand.c | |
parent | c50ff294f77295d98662af55db383e38dfce5a55 (diff) | |
download | gcc-b156ec373ccf27f4fcce7972de5e043d35acea43.tar.gz |
2013-05-07 Han Shen <shenhan@google.com>
gcc/
* cfgexpand.c (record_or_union_type_has_array_p): New function.
(expand_used_vars): Add logic handling '-fstack-protector-strong'.
* common.opt (fstack-protector-strong): New option.
* doc/cpp.texi (__SSP_STRONG__): New builtin "__SSP_STRONG__".
* doc/invoke.texi (Optimization Options): Document
"-fstack-protector-strong".
* gcc.c (LINK_SSP_SPEC): Add 'fstack-protector-strong'.
gcc/testsuite/
* gcc.dg/fstack-protector-strong.c: New.
* g++.dg/fstack-protector-strong.C: New.
gcc/c-family/
* c-cppbuiltin.c (c_cpp_builtins): Added "__SSP_STRONG__=3".
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@198699 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cfgexpand.c')
-rw-r--r-- | gcc/cfgexpand.c | 75 |
1 files changed, 68 insertions, 7 deletions
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index a651d8c5868..c1872731240 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1291,6 +1291,12 @@ clear_tree_used (tree block) clear_tree_used (t); } +enum { + SPCT_FLAG_DEFAULT = 1, + SPCT_FLAG_ALL = 2, + SPCT_FLAG_STRONG = 3 +}; + /* Examine TYPE and determine a bit mask of the following features. */ #define SPCT_HAS_LARGE_CHAR_ARRAY 1 @@ -1360,7 +1366,8 @@ stack_protect_decl_phase (tree decl) if (bits & SPCT_HAS_SMALL_CHAR_ARRAY) has_short_buffer = true; - if (flag_stack_protect == 2) + if (flag_stack_protect == SPCT_FLAG_ALL + || flag_stack_protect == SPCT_FLAG_STRONG) { if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY)) && !(bits & SPCT_HAS_AGGREGATE)) @@ -1514,6 +1521,27 @@ estimated_stack_frame_size (struct cgraph_node *node) return size; } +/* Helper routine to check if a record or union contains an array field. */ + +static int +record_or_union_type_has_array_p (const_tree tree_type) +{ + tree fields = TYPE_FIELDS (tree_type); + tree f; + + for (f = fields; f; f = DECL_CHAIN (f)) + if (TREE_CODE (f) == FIELD_DECL) + { + tree field_type = TREE_TYPE (f); + if (RECORD_OR_UNION_TYPE_P (field_type) + && record_or_union_type_has_array_p (field_type)) + return 1; + if (TREE_CODE (field_type) == ARRAY_TYPE) + return 1; + } + return 0; +} + /* Expand all variables used in the function. */ static rtx @@ -1525,6 +1553,7 @@ expand_used_vars (void) struct pointer_map_t *ssa_name_decls; unsigned i; unsigned len; + bool gen_stack_protect_signal = false; /* Compute the phase of the stack frame for this function. */ { @@ -1576,6 +1605,24 @@ expand_used_vars (void) } pointer_map_destroy (ssa_name_decls); + if (flag_stack_protect == SPCT_FLAG_STRONG) + FOR_EACH_LOCAL_DECL (cfun, i, var) + if (!is_global_var (var)) + { + tree var_type = TREE_TYPE (var); + /* Examine local referenced variables that have their addresses taken, + contain an array, or are arrays. */ + if (TREE_CODE (var) == VAR_DECL + && (TREE_CODE (var_type) == ARRAY_TYPE + || TREE_ADDRESSABLE (var) + || (RECORD_OR_UNION_TYPE_P (var_type) + && record_or_union_type_has_array_p (var_type)))) + { + gen_stack_protect_signal = true; + break; + } + } + /* At this point all variables on the local_decls with TREE_USED set are not associated with any block scope. Lay them out. */ @@ -1662,12 +1709,26 @@ expand_used_vars (void) dump_stack_var_partition (); } - /* There are several conditions under which we should create a - stack guard: protect-all, alloca used, protected decls present. */ - if (flag_stack_protect == 2 - || (flag_stack_protect - && (cfun->calls_alloca || has_protected_decls))) - create_stack_guard (); + switch (flag_stack_protect) + { + case SPCT_FLAG_ALL: + create_stack_guard (); + break; + + case SPCT_FLAG_STRONG: + if (gen_stack_protect_signal + || cfun->calls_alloca || has_protected_decls) + create_stack_guard (); + break; + + case SPCT_FLAG_DEFAULT: + if (cfun->calls_alloca || has_protected_decls) + create_stack_guard(); + break; + + default: + ; + } /* Assign rtl to each variable based on these partitions. */ if (stack_vars_num > 0) |