diff options
author | qing zhao <qing.zhao@oracle.com> | 2021-09-09 15:44:49 -0700 |
---|---|---|
committer | qing zhao <qing.zhao@oracle.com> | 2021-09-09 15:44:49 -0700 |
commit | a25e0b5e6ac8a77a71c229e0a7b744603365b0e9 (patch) | |
tree | e46dad7fa274dc376be2ccf4735b5333c5d34315 /gcc/tree-sra.c | |
parent | 5fe0865ab788bdc387b284a3ad57e5a95a767b18 (diff) | |
download | gcc-a25e0b5e6ac8a77a71c229e0a7b744603365b0e9.zip gcc-a25e0b5e6ac8a77a71c229e0a7b744603365b0e9.tar.gz gcc-a25e0b5e6ac8a77a71c229e0a7b744603365b0e9.tar.bz2 |
Add -ftrivial-auto-var-init option and uninitialized variable attribute.
Initialize automatic variables with either a pattern or with zeroes to increase
the security and predictability of a program by preventing uninitialized memory
disclosure and use.
GCC still considers an automatic variable that doesn't have an explicit
initializer as uninitialized, -Wuninitialized will still report warning messages
on such automatic variables.
With this option, GCC will also initialize any padding of automatic variables
that have structure or union types to zeroes.
You can control this behavior for a specific variable by using the variable
attribute "uninitialized" to control runtime overhead.
gcc/ChangeLog:
2021-09-09 qing zhao <qing.zhao@oracle.com>
* builtins.c (expand_builtin_memset): Make external visible.
* builtins.h (expand_builtin_memset): Declare extern.
* common.opt (ftrivial-auto-var-init=): New option.
* doc/extend.texi: Document the uninitialized attribute.
* doc/invoke.texi: Document -ftrivial-auto-var-init.
* flag-types.h (enum auto_init_type): New enumerated type
auto_init_type.
* gimple-fold.c (clear_padding_type): Add one new parameter.
(clear_padding_union): Likewise.
(clear_padding_emit_loop): Likewise.
(clear_type_padding_in_mask): Likewise.
(gimple_fold_builtin_clear_padding): Handle this new parameter.
* gimplify.c (gimple_add_init_for_auto_var): New function.
(gimple_add_padding_init_for_auto_var): New function.
(is_var_need_auto_init): New function.
(gimplify_decl_expr): Add initialization to automatic variables per
users' requests.
(gimplify_call_expr): Add one new parameter for call to
__builtin_clear_padding.
(gimplify_init_constructor): Add padding initialization in the end.
* internal-fn.c (INIT_PATTERN_VALUE): New macro.
(expand_DEFERRED_INIT): New function.
* internal-fn.def (DEFERRED_INIT): New internal function.
* tree-cfg.c (verify_gimple_call): Verify calls to .DEFERRED_INIT.
* tree-sra.c (generate_subtree_deferred_init): New function.
(scan_function): Avoid setting cannot_scalarize_away_bitmap for
calls to .DEFERRED_INIT.
(sra_modify_deferred_init): New function.
(sra_modify_function_body): Handle calls to DEFERRED_INIT specially.
* tree-ssa-structalias.c (find_func_aliases_for_call): Likewise.
* tree-ssa-uninit.c (warn_uninit): Handle calls to DEFERRED_INIT
specially.
(check_defs): Likewise.
(warn_uninitialized_vars): Likewise.
* tree-ssa.c (ssa_undefined_value_p): Likewise.
* tree.c (build_common_builtin_nodes): Build tree node for
BUILT_IN_CLEAR_PADDING when needed.
gcc/c-family/ChangeLog:
2021-09-09 qing zhao <qing.zhao@oracle.com>
* c-attribs.c (handle_uninitialized_attribute): New function.
(c_common_attribute_table): Add "uninitialized" attribute.
gcc/testsuite/ChangeLog:
2021-09-09 qing zhao <qing.zhao@oracle.com>
* c-c++-common/auto-init-1.c: New test.
* c-c++-common/auto-init-10.c: New test.
* c-c++-common/auto-init-11.c: New test.
* c-c++-common/auto-init-12.c: New test.
* c-c++-common/auto-init-13.c: New test.
* c-c++-common/auto-init-14.c: New test.
* c-c++-common/auto-init-15.c: New test.
* c-c++-common/auto-init-16.c: New test.
* c-c++-common/auto-init-2.c: New test.
* c-c++-common/auto-init-3.c: New test.
* c-c++-common/auto-init-4.c: New test.
* c-c++-common/auto-init-5.c: New test.
* c-c++-common/auto-init-6.c: New test.
* c-c++-common/auto-init-7.c: New test.
* c-c++-common/auto-init-8.c: New test.
* c-c++-common/auto-init-9.c: New test.
* c-c++-common/auto-init-esra.c: New test.
* c-c++-common/auto-init-padding-1.c: New test.
* c-c++-common/auto-init-padding-2.c: New test.
* c-c++-common/auto-init-padding-3.c: New test.
* g++.dg/auto-init-uninit-pred-1_a.C: New test.
* g++.dg/auto-init-uninit-pred-2_a.C: New test.
* g++.dg/auto-init-uninit-pred-3_a.C: New test.
* g++.dg/auto-init-uninit-pred-4.C: New test.
* gcc.dg/auto-init-sra-1.c: New test.
* gcc.dg/auto-init-sra-2.c: New test.
* gcc.dg/auto-init-uninit-1.c: New test.
* gcc.dg/auto-init-uninit-12.c: New test.
* gcc.dg/auto-init-uninit-13.c: New test.
* gcc.dg/auto-init-uninit-14.c: New test.
* gcc.dg/auto-init-uninit-15.c: New test.
* gcc.dg/auto-init-uninit-16.c: New test.
* gcc.dg/auto-init-uninit-17.c: New test.
* gcc.dg/auto-init-uninit-18.c: New test.
* gcc.dg/auto-init-uninit-19.c: New test.
* gcc.dg/auto-init-uninit-2.c: New test.
* gcc.dg/auto-init-uninit-20.c: New test.
* gcc.dg/auto-init-uninit-21.c: New test.
* gcc.dg/auto-init-uninit-22.c: New test.
* gcc.dg/auto-init-uninit-23.c: New test.
* gcc.dg/auto-init-uninit-24.c: New test.
* gcc.dg/auto-init-uninit-25.c: New test.
* gcc.dg/auto-init-uninit-26.c: New test.
* gcc.dg/auto-init-uninit-3.c: New test.
* gcc.dg/auto-init-uninit-34.c: New test.
* gcc.dg/auto-init-uninit-36.c: New test.
* gcc.dg/auto-init-uninit-37.c: New test.
* gcc.dg/auto-init-uninit-4.c: New test.
* gcc.dg/auto-init-uninit-5.c: New test.
* gcc.dg/auto-init-uninit-6.c: New test.
* gcc.dg/auto-init-uninit-8.c: New test.
* gcc.dg/auto-init-uninit-9.c: New test.
* gcc.dg/auto-init-uninit-A.c: New test.
* gcc.dg/auto-init-uninit-B.c: New test.
* gcc.dg/auto-init-uninit-C.c: New test.
* gcc.dg/auto-init-uninit-H.c: New test.
* gcc.dg/auto-init-uninit-I.c: New test.
* gcc.target/aarch64/auto-init-1.c: New test.
* gcc.target/aarch64/auto-init-2.c: New test.
* gcc.target/aarch64/auto-init-3.c: New test.
* gcc.target/aarch64/auto-init-4.c: New test.
* gcc.target/aarch64/auto-init-5.c: New test.
* gcc.target/aarch64/auto-init-6.c: New test.
* gcc.target/aarch64/auto-init-7.c: New test.
* gcc.target/aarch64/auto-init-8.c: New test.
* gcc.target/aarch64/auto-init-padding-1.c: New test.
* gcc.target/aarch64/auto-init-padding-10.c: New test.
* gcc.target/aarch64/auto-init-padding-11.c: New test.
* gcc.target/aarch64/auto-init-padding-12.c: New test.
* gcc.target/aarch64/auto-init-padding-2.c: New test.
* gcc.target/aarch64/auto-init-padding-3.c: New test.
* gcc.target/aarch64/auto-init-padding-4.c: New test.
* gcc.target/aarch64/auto-init-padding-5.c: New test.
* gcc.target/aarch64/auto-init-padding-6.c: New test.
* gcc.target/aarch64/auto-init-padding-7.c: New test.
* gcc.target/aarch64/auto-init-padding-8.c: New test.
* gcc.target/aarch64/auto-init-padding-9.c: New test.
* gcc.target/i386/auto-init-1.c: New test.
* gcc.target/i386/auto-init-2.c: New test.
* gcc.target/i386/auto-init-21.c: New test.
* gcc.target/i386/auto-init-22.c: New test.
* gcc.target/i386/auto-init-23.c: New test.
* gcc.target/i386/auto-init-24.c: New test.
* gcc.target/i386/auto-init-3.c: New test.
* gcc.target/i386/auto-init-4.c: New test.
* gcc.target/i386/auto-init-5.c: New test.
* gcc.target/i386/auto-init-6.c: New test.
* gcc.target/i386/auto-init-7.c: New test.
* gcc.target/i386/auto-init-8.c: New test.
* gcc.target/i386/auto-init-padding-1.c: New test.
* gcc.target/i386/auto-init-padding-10.c: New test.
* gcc.target/i386/auto-init-padding-11.c: New test.
* gcc.target/i386/auto-init-padding-12.c: New test.
* gcc.target/i386/auto-init-padding-2.c: New test.
* gcc.target/i386/auto-init-padding-3.c: New test.
* gcc.target/i386/auto-init-padding-4.c: New test.
* gcc.target/i386/auto-init-padding-5.c: New test.
* gcc.target/i386/auto-init-padding-6.c: New test.
* gcc.target/i386/auto-init-padding-7.c: New test.
* gcc.target/i386/auto-init-padding-8.c: New test.
* gcc.target/i386/auto-init-padding-9.c: New test.
Diffstat (limited to 'gcc/tree-sra.c')
-rw-r--r-- | gcc/tree-sra.c | 124 |
1 files changed, 115 insertions, 9 deletions
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 3a9e14f..0363c5e 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -384,6 +384,13 @@ static struct /* Numbber of components created when splitting aggregate parameters. */ int param_reductions_created; + + /* Number of deferred_init calls that are modified. */ + int deferred_init; + + /* Number of deferred_init calls that are created by + generate_subtree_deferred_init. */ + int subtree_deferred_init; } sra_stats; static void @@ -1388,7 +1395,14 @@ scan_function (void) t = gimple_call_lhs (stmt); if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL)) - ret |= build_access_from_expr (t, stmt, true); + { + /* If the STMT is a call to DEFERRED_INIT, avoid setting + cannot_scalarize_away_bitmap. */ + if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT)) + ret |= !!build_access_from_expr_1 (t, stmt, true); + else + ret |= build_access_from_expr (t, stmt, true); + } break; case GIMPLE_ASM: @@ -4099,6 +4113,88 @@ get_repl_default_def_ssa_name (struct access *racc, tree reg_type) return get_or_create_ssa_default_def (cfun, racc->replacement_decl); } + +/* Generate statements to call .DEFERRED_INIT to initialize scalar replacements + of accesses within a subtree ACCESS; all its children, siblings and their + children are to be processed. + GSI is a statement iterator used to place the new statements. */ +static void +generate_subtree_deferred_init (struct access *access, + tree init_type, + tree is_vla, + gimple_stmt_iterator *gsi, + location_t loc) +{ + do + { + if (access->grp_to_be_replaced) + { + tree repl = get_access_replacement (access); + gimple *call + = gimple_build_call_internal (IFN_DEFERRED_INIT, 3, + TYPE_SIZE_UNIT (TREE_TYPE (repl)), + init_type, is_vla); + gimple_call_set_lhs (call, repl); + gsi_insert_before (gsi, call, GSI_SAME_STMT); + update_stmt (call); + gimple_set_location (call, loc); + sra_stats.subtree_deferred_init++; + } + if (access->first_child) + generate_subtree_deferred_init (access->first_child, init_type, + is_vla, gsi, loc); + + access = access ->next_sibling; + } + while (access); +} + +/* For a call to .DEFERRED_INIT: + var = .DEFERRED_INIT (size_of_var, init_type, is_vla); + examine the LHS variable VAR and replace it with a scalar replacement if + there is one, also replace the RHS call to a call to .DEFERRED_INIT of + the corresponding scalar relacement variable. Examine the subtree and + do the scalar replacements in the subtree too. STMT is the call, GSI is + the statment iterator to place newly created statement. */ + +static enum assignment_mod_result +sra_modify_deferred_init (gimple *stmt, gimple_stmt_iterator *gsi) +{ + tree lhs = gimple_call_lhs (stmt); + tree init_type = gimple_call_arg (stmt, 1); + tree is_vla = gimple_call_arg (stmt, 2); + + struct access *lhs_access = get_access_for_expr (lhs); + if (!lhs_access) + return SRA_AM_NONE; + + location_t loc = gimple_location (stmt); + + if (lhs_access->grp_to_be_replaced) + { + tree lhs_repl = get_access_replacement (lhs_access); + gimple_call_set_lhs (stmt, lhs_repl); + tree arg0_repl = TYPE_SIZE_UNIT (TREE_TYPE (lhs_repl)); + gimple_call_set_arg (stmt, 0, arg0_repl); + sra_stats.deferred_init++; + gcc_assert (!lhs_access->first_child); + return SRA_AM_MODIFIED; + } + + if (lhs_access->first_child) + generate_subtree_deferred_init (lhs_access->first_child, + init_type, is_vla, gsi, loc); + if (lhs_access->grp_covered) + { + unlink_stmt_vdef (stmt); + gsi_remove (gsi, true); + release_defs (stmt); + return SRA_AM_REMOVED; + } + + return SRA_AM_MODIFIED; +} + /* Examine both sides of the assignment statement pointed to by STMT, replace them with a scalare replacement if there is one and generate copying of replacements if scalarized aggregates have been used in the assignment. GSI @@ -4463,17 +4559,27 @@ sra_modify_function_body (void) break; case GIMPLE_CALL: - /* Operands must be processed before the lhs. */ - for (i = 0; i < gimple_call_num_args (stmt); i++) + /* Handle calls to .DEFERRED_INIT specially. */ + if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT)) { - t = gimple_call_arg_ptr (stmt, i); - modified |= sra_modify_expr (t, &gsi, false); + assign_result = sra_modify_deferred_init (stmt, &gsi); + modified |= assign_result == SRA_AM_MODIFIED; + deleted = assign_result == SRA_AM_REMOVED; } - - if (gimple_call_lhs (stmt)) + else { - t = gimple_call_lhs_ptr (stmt); - modified |= sra_modify_expr (t, &gsi, true); + /* Operands must be processed before the lhs. */ + for (i = 0; i < gimple_call_num_args (stmt); i++) + { + t = gimple_call_arg_ptr (stmt, i); + modified |= sra_modify_expr (t, &gsi, false); + } + + if (gimple_call_lhs (stmt)) + { + t = gimple_call_lhs_ptr (stmt); + modified |= sra_modify_expr (t, &gsi, true); + } } break; |