On Thu, Sep 01, 2016 at 09:58:44AM +0200, Richard Biener wrote: > Ah, so it expects sth _before_ before-dynamic-init? At least it seems > that globals are not only registered inbetween before/after-dynamic-init.
Here is updated patch, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > Maybe simply always init dynamic_init_globals? I've posted a patch to llvm-commits. 2016-09-02 Jakub Jelinek <ja...@redhat.com> PR sanitizer/77396 * sanopt.c: Include gimple-ssa.h, tree-phinodes.h and ssa-iterators.h. (sanopt_optimize_walker): Optimize away __asan_before_dynamic_init (...) followed by __asan_after_dynamic_init () without intervening memory loads/stores. * ipa-pure-const.c (special_builtin_state): Handle BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT and BUILT_IN_ASAN_AFTER_DYNAMIC_INIT. * decl2.c (do_static_initialization_or_destruction): Only call asan_dynamic_init_call if INITP is true. * g++.dg/asan/pr77396.C: New test. --- gcc/sanopt.c.jj 2016-08-31 20:40:26.224215125 +0200 +++ gcc/sanopt.c 2016-09-02 13:30:09.954070468 +0200 @@ -33,6 +33,9 @@ along with GCC; see the file COPYING3. #include "ubsan.h" #include "params.h" #include "tree-hash-traits.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" /* This is used to carry information about basic blocks. It is @@ -538,6 +541,28 @@ sanopt_optimize_walker (basic_block bb, if (asan_check_optimize && !nonfreeing_call_p (stmt)) info->freeing_call_events++; + /* If __asan_before_dynamic_init ("module"); is followed by + __asan_after_dynamic_init (); without intervening memory loads/stores, + there is nothing to guard, so optimize both away. */ + if (asan_check_optimize + && gimple_call_builtin_p (stmt, BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT)) + { + use_operand_p use; + gimple *use_stmt; + if (single_imm_use (gimple_vdef (stmt), &use, &use_stmt)) + { + if (is_gimple_call (use_stmt) + && gimple_call_builtin_p (use_stmt, + BUILT_IN_ASAN_AFTER_DYNAMIC_INIT)) + { + unlink_stmt_vdef (use_stmt); + gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt); + gsi_remove (&gsi2, true); + remove = true; + } + } + } + if (gimple_call_internal_p (stmt)) switch (gimple_call_internal_fn (stmt)) { --- gcc/ipa-pure-const.c.jj 2016-08-31 20:40:26.631209934 +0200 +++ gcc/ipa-pure-const.c 2016-09-02 13:24:55.173990290 +0200 @@ -508,6 +508,8 @@ special_builtin_state (enum pure_const_s case BUILT_IN_FRAME_ADDRESS: case BUILT_IN_APPLY: case BUILT_IN_APPLY_ARGS: + case BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT: + case BUILT_IN_ASAN_AFTER_DYNAMIC_INIT: *looping = false; *state = IPA_CONST; return true; --- gcc/cp/decl2.c.jj 2016-08-31 20:40:26.577210623 +0200 +++ gcc/cp/decl2.c 2016-09-02 13:24:55.175990265 +0200 @@ -3861,7 +3861,7 @@ do_static_initialization_or_destruction in other compilation units, or at least those that haven't been initialized yet. Variables that need dynamic construction in the current compilation unit are kept accessible. */ - if (flag_sanitize & SANITIZE_ADDRESS) + if (initp && (flag_sanitize & SANITIZE_ADDRESS)) finish_expr_stmt (asan_dynamic_init_call (/*after_p=*/false)); node = vars; @@ -3914,7 +3914,7 @@ do_static_initialization_or_destruction /* Revert what __asan_before_dynamic_init did by calling __asan_after_dynamic_init. */ - if (flag_sanitize & SANITIZE_ADDRESS) + if (initp && (flag_sanitize & SANITIZE_ADDRESS)) finish_expr_stmt (asan_dynamic_init_call (/*after_p=*/true)); /* Finish up the init/destruct if-stmt body. */ --- gcc/testsuite/g++.dg/asan/pr77396.C.jj 2016-09-02 13:24:55.175990265 +0200 +++ gcc/testsuite/g++.dg/asan/pr77396.C 2016-09-02 13:24:55.175990265 +0200 @@ -0,0 +1,12 @@ +// PR sanitizer/77396 +// { dg-do run } +// { dg-set-target-env-var ASAN_OPTIONS "check_initialization_order=true" } + +static int a = 0; +static int b = a; + +int +main () +{ + return 0; +} Jakub