--- gcc/cfgexpand.c.orig +++ gcc/cfgexpand.c @@ -1291,6 +1291,12 @@ 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 @@ 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 @@ 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 @@ 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. */ { @@ -1575,6 +1604,24 @@ } } 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,32 @@ 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 (); + /* Create stack guard, if + a) "-fstack-protector-all" - always; + b) "-fstack-protector-strong" - if there are arrays, memory + references to local variables, alloca used, or protected decls present; + c) "-fstack-protector" - if alloca used, or protected decls present */ + + 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) @@ -1688,7 +1755,7 @@ 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) expand_stack_vars (stack_protect_decl_phase_2, &data); } --- gcc/common.opt.orig +++ gcc/common.opt @@ -1942,6 +1942,10 @@ fstack-protector-all Common Report RejectNegative Var(flag_stack_protect, 2) Use a stack protection method for every function +fstack-protector-strong +Common Report RejectNegative Var(flag_stack_protect, 3) +Use a smart stack protection method for certain functions + fstack-usage Common RejectNegative Var(flag_stack_usage) Output stack usage information on a per-function basis --- gcc/gcc.c.orig +++ gcc/gcc.c @@ -655,7 +655,7 @@ proper position among the other output files. */ #ifdef TARGET_LIBC_PROVIDES_SSP #define LINK_SSP_SPEC "%{fstack-protector:}" #else -#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared -lssp}" +#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-strong|fstack-protector-all:-lssp_nonshared -lssp}" #endif #endif