diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-22 20:04:45 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-22 20:04:45 +0000 |
commit | 085f6ebf2c482e7e734c5abc54597ecc99c18c1f (patch) | |
tree | d11dfc57c47e4f7387f7f22a57a8e10b78aab3e1 /gcc/asan.c | |
parent | c6b269028fd63423938c2092cef24a92b08a4f39 (diff) | |
download | gcc-085f6ebf2c482e7e734c5abc54597ecc99c18c1f.tar.gz |
* sanitizer.def (BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT,
BUILT_IN_ASAN_AFTER_DYNAMIC_INIT): New.
* asan.c (instrument_derefs): Handle also VAR_DECL loads/stores.
Don't instrument accesses to VAR_DECLs which are known to fit
into their bounds and the vars are known to have shadow bytes
indicating allowed access.
(asan_dynamic_init_call): New function.
(asan_add_global): If vnode->dynamically_initialized,
set __has_dynamic_init to 1 instead of 0.
(initialize_sanitizer_builtins): Add BT_FN_VOID_CONST_PTR var.
* asan.h (asan_dynamic_init_call): New prototype.
* cgraph.h (varpool_node): Add dynamically_initialized bitfield.
cp/
* decl2.c: Include asan.h.
(one_static_initialization_or_destruction): If -fsanitize=address,
init is non-NULL and guard is NULL, set
vnode->dynamically_initialized.
(do_static_initialization_or_destruction): Call
__asan_{before,after}_dynamic_init around the static initialization.
testsuite/
* c-c++-common/asan/no-redundant-instrumentation-1.c: Tweak to avoid
optimizing away some __asan_report* calls.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@205282 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/asan.c')
-rw-r--r-- | gcc/asan.c | 71 |
1 files changed, 67 insertions, 4 deletions
diff --git a/gcc/asan.c b/gcc/asan.c index f68b17302bd..677435e05ae 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -224,7 +224,7 @@ along with GCC; see the file COPYING3. If not see // Name of the module where the global variable is declared. const void *__module_name; - // This is always set to NULL for now. + // 1 if it has dynamic initialization, 0 otherwise. uptr __has_dynamic_init; } @@ -1471,7 +1471,9 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t, case COMPONENT_REF: case INDIRECT_REF: case MEM_REF: + case VAR_DECL: break; + /* FALLTHRU */ default: return; } @@ -1485,8 +1487,8 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t, tree offset; enum machine_mode mode; int volatilep = 0, unsignedp = 0; - get_inner_reference (t, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, + &mode, &unsignedp, &volatilep, false); if (bitpos % (size_in_bytes * BITS_PER_UNIT) || bitsize != size_in_bytes * BITS_PER_UNIT) { @@ -1501,6 +1503,34 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t, return; } + if (TREE_CODE (inner) == VAR_DECL + && offset == NULL_TREE + && bitpos >= 0 + && DECL_SIZE (inner) + && tree_fits_shwi_p (DECL_SIZE (inner)) + && bitpos + bitsize <= tree_to_shwi (DECL_SIZE (inner))) + { + if (DECL_THREAD_LOCAL_P (inner)) + return; + if (!TREE_STATIC (inner)) + { + /* Automatic vars in the current function will be always + accessible. */ + if (decl_function_context (inner) == current_function_decl) + return; + } + /* Always instrument external vars, they might be dynamically + initialized. */ + else if (!DECL_EXTERNAL (inner)) + { + /* For static vars if they are known not to be dynamically + initialized, they will be always accessible. */ + struct varpool_node *vnode = varpool_get_node (inner); + if (vnode && !vnode->dynamically_initialized) + return; + } + } + base = build_fold_addr_expr (t); if (!has_mem_ref_been_instrumented (base, size_in_bytes)) { @@ -1959,6 +1989,34 @@ transform_statements (void) } /* Build + __asan_before_dynamic_init (module_name) + or + __asan_after_dynamic_init () + call. */ + +tree +asan_dynamic_init_call (bool after_p) +{ + tree fn = builtin_decl_implicit (after_p + ? BUILT_IN_ASAN_AFTER_DYNAMIC_INIT + : BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT); + tree module_name_cst = NULL_TREE; + if (!after_p) + { + pretty_printer module_name_pp; + pp_string (&module_name_pp, main_input_filename); + + if (shadow_ptr_types[0] == NULL_TREE) + asan_init_shadow_ptr_types (); + module_name_cst = asan_pp_string (&module_name_pp); + module_name_cst = fold_convert (const_ptr_type_node, + module_name_cst); + } + + return build_call_expr (fn, after_p ? 0 : 1, module_name_cst); +} + +/* Build struct __asan_global { const void *__beg; @@ -2047,7 +2105,10 @@ asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v) fold_convert (const_ptr_type_node, str_cst)); CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, fold_convert (const_ptr_type_node, module_name_cst)); - CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, 0)); + struct varpool_node *vnode = varpool_get_node (decl); + int has_dynamic_init = vnode ? vnode->dynamically_initialized : 0; + CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, + build_int_cst (uptr, has_dynamic_init)); init = build_constructor (type, vinner); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init); } @@ -2064,6 +2125,8 @@ initialize_sanitizer_builtins (void) tree BT_FN_VOID = build_function_type_list (void_type_node, NULL_TREE); tree BT_FN_VOID_PTR = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); + tree BT_FN_VOID_CONST_PTR + = build_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE); tree BT_FN_VOID_PTR_PTR = build_function_type_list (void_type_node, ptr_type_node, ptr_type_node, NULL_TREE); |