aboutsummaryrefslogtreecommitdiff
path: root/gcc/asan.c
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2017-01-23 13:02:13 +0100
committerMartin Liska <marxin@gcc.gnu.org>2017-01-23 12:02:13 +0000
commitc7775327e8cf214872b3d179bfaa1b441759ab5a (patch)
tree1ab9205a738735b127304a898b222670154c0f01 /gcc/asan.c
parent913e4b3617fe7f46fbdbb72b010cf6cf7201d329 (diff)
downloadgcc-c7775327e8cf214872b3d179bfaa1b441759ab5a.zip
gcc-c7775327e8cf214872b3d179bfaa1b441759ab5a.tar.gz
gcc-c7775327e8cf214872b3d179bfaa1b441759ab5a.tar.bz2
Speed up use-after-scope (v2): rewrite into SSA
2017-01-23 Martin Liska <mliska@suse.cz> * asan.c (create_asan_shadow_var): New function. (asan_expand_poison_ifn): Likewise. * asan.h (asan_expand_poison_ifn): New declaration. * internal-fn.c (expand_ASAN_POISON): Likewise. * internal-fn.def (ASAN_POISON): New builtin. * sanopt.c (pass_sanopt::execute): Expand asan_expand_poison_ifn. * tree-inline.c (copy_decl_for_dup_finish): Make function external. * tree-inline.h (copy_decl_for_dup_finish): Likewise. * tree-ssa.c (is_asan_mark_p): New function. (execute_update_addresses_taken): Rewrite local variables (identified just by use-after-scope as addressable) into SSA. 2017-01-23 Martin Liska <mliska@suse.cz> * gcc.dg/asan/use-after-scope-3.c: Add additional flags. * gcc.dg/asan/use-after-scope-9.c: Likewise and grep for sanopt optimization for ASAN_POISON. From-SVN: r244791
Diffstat (limited to 'gcc/asan.c')
-rw-r--r--gcc/asan.c109
1 files changed, 108 insertions, 1 deletions
diff --git a/gcc/asan.c b/gcc/asan.c
index 7450044..fe117a6 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -32,8 +32,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "memmodel.h"
#include "tm_p.h"
+#include "ssa.h"
#include "stringpool.h"
-#include "tree-vrp.h"
#include "tree-ssanames.h"
#include "optabs.h"
#include "emit-rtl.h"
@@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "builtins.h"
#include "fnmatch.h"
+#include "tree-inline.h"
/* AddressSanitizer finds out-of-bounds and use-after-free bugs
with <2x slowdown on average.
@@ -3064,6 +3065,112 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
return true;
}
+/* Create ASAN shadow variable for a VAR_DECL which has been rewritten
+ into SSA. Already seen VAR_DECLs are stored in SHADOW_VARS_MAPPING. */
+
+static tree
+create_asan_shadow_var (tree var_decl,
+ hash_map<tree, tree> &shadow_vars_mapping)
+{
+ tree *slot = shadow_vars_mapping.get (var_decl);
+ if (slot == NULL)
+ {
+ tree shadow_var = copy_node (var_decl);
+
+ copy_body_data id;
+ memset (&id, 0, sizeof (copy_body_data));
+ id.src_fn = id.dst_fn = current_function_decl;
+ copy_decl_for_dup_finish (&id, var_decl, shadow_var);
+
+ DECL_ARTIFICIAL (shadow_var) = 1;
+ DECL_IGNORED_P (shadow_var) = 1;
+ DECL_SEEN_IN_BIND_EXPR_P (shadow_var) = 0;
+ gimple_add_tmp_var (shadow_var);
+
+ shadow_vars_mapping.put (var_decl, shadow_var);
+ return shadow_var;
+ }
+ else
+ return *slot;
+}
+
+bool
+asan_expand_poison_ifn (gimple_stmt_iterator *iter,
+ bool *need_commit_edge_insert,
+ hash_map<tree, tree> &shadow_vars_mapping)
+{
+ gimple *g = gsi_stmt (*iter);
+ tree poisoned_var = gimple_call_lhs (g);
+ if (!poisoned_var)
+ {
+ gsi_remove (iter, true);
+ return true;
+ }
+
+ tree shadow_var = create_asan_shadow_var (SSA_NAME_VAR (poisoned_var),
+ shadow_vars_mapping);
+
+ bool recover_p;
+ if (flag_sanitize & SANITIZE_USER_ADDRESS)
+ recover_p = (flag_sanitize_recover & SANITIZE_USER_ADDRESS) != 0;
+ else
+ recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
+ tree size = DECL_SIZE_UNIT (shadow_var);
+ gimple *poison_call
+ = gimple_build_call_internal (IFN_ASAN_MARK, 3,
+ build_int_cst (integer_type_node,
+ ASAN_MARK_POISON),
+ build_fold_addr_expr (shadow_var), size);
+
+ use_operand_p use_p;
+ imm_use_iterator imm_iter;
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, poisoned_var)
+ {
+ gimple *use = USE_STMT (use_p);
+ if (is_gimple_debug (use))
+ continue;
+
+ int nargs;
+ tree fun = report_error_func (false, recover_p, tree_to_uhwi (size),
+ &nargs);
+
+ gcall *call = gimple_build_call (fun, 1,
+ build_fold_addr_expr (shadow_var));
+ gimple_set_location (call, gimple_location (use));
+ gimple *call_to_insert = call;
+
+ /* The USE can be a gimple PHI node. If so, insert the call on
+ all edges leading to the PHI node. */
+ if (is_a <gphi *> (use))
+ {
+ gphi *phi = dyn_cast<gphi *> (use);
+ for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
+ if (gimple_phi_arg_def (phi, i) == poisoned_var)
+ {
+ edge e = gimple_phi_arg_edge (phi, i);
+
+ if (call_to_insert == NULL)
+ call_to_insert = gimple_copy (call);
+
+ gsi_insert_seq_on_edge (e, call_to_insert);
+ *need_commit_edge_insert = true;
+ call_to_insert = NULL;
+ }
+ }
+ else
+ {
+ gimple_stmt_iterator gsi = gsi_for_stmt (use);
+ gsi_insert_before (&gsi, call, GSI_NEW_STMT);
+ }
+ }
+
+ SSA_NAME_IS_DEFAULT_DEF (poisoned_var) = true;
+ SSA_NAME_DEF_STMT (poisoned_var) = gimple_build_nop ();
+ gsi_replace (iter, poison_call, false);
+
+ return true;
+}
+
/* Instrument the current function. */
static unsigned int