From 55b58027644caba54158d5ee8fa9ddf43fbf7acb Mon Sep 17 00:00:00 2001 From: jakub Date: Mon, 10 Dec 2012 12:14:36 +0000 Subject: [PATCH] * asan.c (asan_init_shadow_ptr_types): Move earlier in the file. Call initialize_sanitizer_builtins at the end. (asan_pp_string): Use TREE_TYPE (shadow_ptr_types[0]) as character type instead of char_type_node. (asan_emit_stack_protection): Call asan_init_shadow_ptr_types if shadow_ptr_types isn't initialized. (asan_protect_global): Return true for STRING_CSTs except those created by asan_pp_string. (count_string_csts, add_string_csts): New functions. (struct asan_add_string_csts_data): New type. (asan_finish_file): Clear flag_asan at the beginning, restore at the end. Traverse constant_pool_htab () to look for protected STRING_CSTs. Don't call initialize_sanitizer_builtins, instead call asan_init_shadow_ptr_types if shadow_ptr_types isn't initialized yet. (asan_instrument): Don't call initialize_sanitizer_builtins. * varasm.c (output_constant_def_contents): If STRING_CST should be asan protected, align it sufficiently and emit padding after it. (categorize_decl_for_section): If flag_asan, don't put STRING_CSTs that should be asan protected into mergeable sections. For -fmerge-all-constants, ignore it for -fmudflap or if decl is asan protected. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@194355 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 25 +++++++++++++ gcc/asan.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++----------- gcc/varasm.c | 19 ++++++++-- 3 files changed, 131 insertions(+), 23 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 249004e..d02c124 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2012-12-10 Jakub Jelinek + + * asan.c (asan_init_shadow_ptr_types): Move earlier in the file. + Call initialize_sanitizer_builtins at the end. + (asan_pp_string): Use TREE_TYPE (shadow_ptr_types[0]) + as character type instead of char_type_node. + (asan_emit_stack_protection): Call asan_init_shadow_ptr_types + if shadow_ptr_types isn't initialized. + (asan_protect_global): Return true for STRING_CSTs except those + created by asan_pp_string. + (count_string_csts, add_string_csts): New functions. + (struct asan_add_string_csts_data): New type. + (asan_finish_file): Clear flag_asan at the beginning, restore at the + end. Traverse constant_pool_htab () to look for protected + STRING_CSTs. Don't call initialize_sanitizer_builtins, + instead call asan_init_shadow_ptr_types if shadow_ptr_types isn't + initialized yet. + (asan_instrument): Don't call initialize_sanitizer_builtins. + * varasm.c (output_constant_def_contents): If STRING_CST should be + asan protected, align it sufficiently and emit padding after it. + (categorize_decl_for_section): If flag_asan, don't put STRING_CSTs + that should be asan protected into mergeable sections. For + -fmerge-all-constants, ignore it for -fmudflap or if decl is + asan protected. + 2012-12-10 Kyrylo Tkachov * config/arm/neon.ml (opcode): Add Vrintn, Vrinta, Vrintp, Vrintm, diff --git a/gcc/asan.c b/gcc/asan.c index b8f36cb..6c8ef18 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -212,6 +212,21 @@ alias_set_type asan_shadow_set = -1; alias set is used for all shadow memory accesses. */ static GTY(()) tree shadow_ptr_types[2]; +/* Initialize shadow_ptr_types array. */ + +static void +asan_init_shadow_ptr_types (void) +{ + asan_shadow_set = new_alias_set (); + shadow_ptr_types[0] = build_distinct_type_copy (signed_char_type_node); + TYPE_ALIAS_SET (shadow_ptr_types[0]) = asan_shadow_set; + shadow_ptr_types[0] = build_pointer_type (shadow_ptr_types[0]); + shadow_ptr_types[1] = build_distinct_type_copy (short_integer_type_node); + TYPE_ALIAS_SET (shadow_ptr_types[1]) = asan_shadow_set; + shadow_ptr_types[1] = build_pointer_type (shadow_ptr_types[1]); + initialize_sanitizer_builtins (); +} + /* Asan pretty-printer, used for buidling of the description STRING_CSTs. */ static pretty_printer asan_pp; static bool asan_pp_initialized; @@ -234,10 +249,11 @@ asan_pp_string (void) size_t len = strlen (buf); tree ret = build_string (len + 1, buf); TREE_TYPE (ret) - = build_array_type (char_type_node, build_index_type (size_int (len))); + = build_array_type (TREE_TYPE (shadow_ptr_types[0]), + build_index_type (size_int (len))); TREE_READONLY (ret) = 1; TREE_STATIC (ret) = 1; - return build1 (ADDR_EXPR, build_pointer_type (char_type_node), ret); + return build1 (ADDR_EXPR, shadow_ptr_types[0], ret); } /* Return a CONST_INT representing 4 subsequent shadow memory bytes. */ @@ -276,6 +292,9 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls, unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT; tree str_cst; + if (shadow_ptr_types[0] == NULL_TREE) + asan_init_shadow_ptr_types (); + /* First of all, prepare the description string. */ if (!asan_pp_initialized) asan_pp_initialize (); @@ -430,6 +449,16 @@ asan_protect_global (tree decl) rtx rtl, symbol; section *sect; + if (TREE_CODE (decl) == STRING_CST) + { + /* Instrument all STRING_CSTs except those created + by asan_pp_string here. */ + if (shadow_ptr_types[0] != NULL_TREE + && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE + && TREE_TYPE (TREE_TYPE (decl)) == TREE_TYPE (shadow_ptr_types[0])) + return false; + return true; + } if (TREE_CODE (decl) != VAR_DECL /* TLS vars aren't statically protectable. */ || DECL_THREAD_LOCAL_P (decl) @@ -1580,6 +1609,50 @@ initialize_sanitizer_builtins (void) #undef DEF_SANITIZER_BUILTIN } +/* Called via htab_traverse. Count number of emitted + STRING_CSTs in the constant hash table. */ + +static int +count_string_csts (void **slot, void *data) +{ + struct constant_descriptor_tree *desc + = (struct constant_descriptor_tree *) *slot; + if (TREE_CODE (desc->value) == STRING_CST + && TREE_ASM_WRITTEN (desc->value) + && asan_protect_global (desc->value)) + ++*((unsigned HOST_WIDE_INT *) data); + return 1; +} + +/* Helper structure to pass two parameters to + add_string_csts. */ + +struct asan_add_string_csts_data +{ + tree type; + vec *v; +}; + +/* Called via htab_traverse. Call asan_add_global + on emitted STRING_CSTs from the constant hash table. */ + +static int +add_string_csts (void **slot, void *data) +{ + struct constant_descriptor_tree *desc + = (struct constant_descriptor_tree *) *slot; + if (TREE_CODE (desc->value) == STRING_CST + && TREE_ASM_WRITTEN (desc->value) + && asan_protect_global (desc->value)) + { + struct asan_add_string_csts_data *aascd + = (struct asan_add_string_csts_data *) data; + asan_add_global (SYMBOL_REF_DECL (XEXP (desc->rtl, 0)), + aascd->type, aascd->v); + } + return 1; +} + /* Needs to be GTY(()), because cgraph_build_static_cdtor may invoke ggc_collect. */ static GTY(()) tree asan_ctor_statements; @@ -1595,13 +1668,20 @@ asan_finish_file (void) struct varpool_node *vnode; unsigned HOST_WIDE_INT gcount = 0; - initialize_sanitizer_builtins (); + if (shadow_ptr_types[0] == NULL_TREE) + asan_init_shadow_ptr_types (); + /* Avoid instrumenting code in the asan ctors/dtors. + We don't need to insert padding after the description strings, + nor after .LASAN* array. */ + flag_asan = 0; tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT); append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements); FOR_EACH_DEFINED_VARIABLE (vnode) if (asan_protect_global (vnode->symbol.decl)) ++gcount; + htab_t const_desc_htab = constant_pool_htab (); + htab_traverse (const_desc_htab, count_string_csts, &gcount); if (gcount) { tree type = asan_global_struct (), var, ctor; @@ -1622,6 +1702,10 @@ asan_finish_file (void) FOR_EACH_DEFINED_VARIABLE (vnode) if (asan_protect_global (vnode->symbol.decl)) asan_add_global (vnode->symbol.decl, TREE_TYPE (type), v); + struct asan_add_string_csts_data aascd; + aascd.type = TREE_TYPE (type); + aascd.v = v; + htab_traverse (const_desc_htab, add_string_csts, &aascd); ctor = build_constructor (type, v); TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; @@ -1644,20 +1728,7 @@ asan_finish_file (void) } cgraph_build_static_cdtor ('I', asan_ctor_statements, MAX_RESERVED_INIT_PRIORITY - 1); -} - -/* Initialize shadow_ptr_types array. */ - -static void -asan_init_shadow_ptr_types (void) -{ - asan_shadow_set = new_alias_set (); - shadow_ptr_types[0] = build_distinct_type_copy (signed_char_type_node); - TYPE_ALIAS_SET (shadow_ptr_types[0]) = asan_shadow_set; - shadow_ptr_types[0] = build_pointer_type (shadow_ptr_types[0]); - shadow_ptr_types[1] = build_distinct_type_copy (short_integer_type_node); - TYPE_ALIAS_SET (shadow_ptr_types[1]) = asan_shadow_set; - shadow_ptr_types[1] = build_pointer_type (shadow_ptr_types[1]); + flag_asan = 1; } /* Instrument the current function. */ @@ -1666,10 +1737,7 @@ static unsigned int asan_instrument (void) { if (shadow_ptr_types[0] == NULL_TREE) - { - asan_init_shadow_ptr_types (); - initialize_sanitizer_builtins (); - } + asan_init_shadow_ptr_types (); transform_statements (); return 0; } diff --git a/gcc/varasm.c b/gcc/varasm.c index ee42afc..3c420c0 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -3249,11 +3249,23 @@ output_constant_def_contents (rtx symbol) place_block_symbol (symbol); else { + bool asan_protected = false; align = DECL_ALIGN (decl); switch_to_section (get_constant_section (exp, align)); + if (flag_asan && TREE_CODE (exp) == STRING_CST + && asan_protect_global (exp)) + { + asan_protected = true; + align = MAX (align, ASAN_RED_ZONE_SIZE * BITS_PER_UNIT); + } if (align > BITS_PER_UNIT) ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); assemble_constant_contents (exp, XSTR (symbol, 0), align); + if (asan_protected) + { + HOST_WIDE_INT size = get_constant_size (exp); + assemble_zeros (asan_red_zone_size (size)); + } } if (flag_mudflap) mudflap_enqueue_constant (exp); @@ -6157,7 +6169,9 @@ categorize_decl_for_section (const_tree decl, int reloc) return SECCAT_TEXT; else if (TREE_CODE (decl) == STRING_CST) { - if (flag_mudflap) /* or !flag_merge_constants */ + if (flag_mudflap + || (flag_asan && asan_protect_global (CONST_CAST_TREE (decl)))) + /* or !flag_merge_constants */ return SECCAT_RODATA; else return SECCAT_RODATA_MERGE_STR; @@ -6181,7 +6195,8 @@ categorize_decl_for_section (const_tree decl, int reloc) } else if (reloc & targetm.asm_out.reloc_rw_mask ()) ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO; - else if (reloc || flag_merge_constants < 2) + else if (reloc || flag_merge_constants < 2 || flag_mudflap + || (flag_asan && asan_protect_global (CONST_CAST_TREE (decl)))) /* C and C++ don't allow different variables to share the same location. -fmerge-all-constants allows even that (at the expense of not conforming). */ -- 2.7.4