From patchwork Mon Nov 12 11:09:07 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 198362 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 0A2D02C0086 for ; Mon, 12 Nov 2012 22:09:20 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1353323362; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: From:To:Cc:Subject:References:Date:In-Reply-To:Message-ID: User-Agent:MIME-Version:Content-Type:Mailing-List:Precedence: List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=niVOaFnxlpXmIwLT3HFko9onHXc=; b=U/4/n3hNps/sASQ 5sHBsXP0G+FWR/JKsESEvrVg5xXPgmqtrH6kUCSi9TQpuDS5edYNHLHVACV2QHzJ h1DMbOIwMqtTWbQPcFB0b85QvNoRvEMKZbq2GjSm3EE5OnUoBQlNQFKLdO3sOM1s qzBbGxIT6HRabu7cJUZBoKHPKjoQ= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:From:To:Cc:Subject:References:X-URL:Date:In-Reply-To:Message-ID:User-Agent:MIME-Version:Content-Type:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=VCS0LJSMpZKbZKfsnE1k9gz1E6IhYDn3KvxB4hanoW0EkLd3k9j2nzWMLWjAlF VeKo3kWprkctP6BD5QxutGdxsc7UobeOIaJpTGa6Z2M9gNcRuNmFBjM8mu8VTYhm eMXIIq8FNZGXl2sTYL/iqj2TXMo02snBHTFFgZzemUS+o=; Received: (qmail 23519 invoked by alias); 12 Nov 2012 11:09:17 -0000 Received: (qmail 23510 invoked by uid 22791); 12 Nov 2012 11:09:17 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL,BAYES_00,TW_TM X-Spam-Check-By: sourceware.org Received: from seketeli.net (HELO ms.seketeli.net) (91.121.166.71) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 12 Nov 2012 11:09:10 +0000 Received: from localhost (torimasen.com [82.237.12.13]) by ms.seketeli.net (Postfix) with ESMTP id DF86FEA042; Mon, 12 Nov 2012 12:33:40 +0100 (CET) Received: by localhost (Postfix, from userid 1000) id 9967D2C0104; Mon, 12 Nov 2012 12:09:07 +0100 (CET) From: Dodji Seketeli To: Tobias Burnus Cc: gcc-patches@gcc.gnu.org, dnovillo@google.com, jakub@redhat.com, wmi@google.com, davidxl@google.com Subject: Re: [PATCH 03/11] Emit GIMPLE directly instead of gimplifying GENERIC. References: <1351799566-31447-1-git-send-email-dodji@redhat.com> <87pq3v8vmi.fsf@redhat.com> <87ip9n8vi2.fsf_-_@redhat.com> <509D019C.7020505@net-b.de> X-URL: http://www.redhat.com Date: Mon, 12 Nov 2012 12:09:07 +0100 In-Reply-To: <509D019C.7020505@net-b.de> (Tobias Burnus's message of "Fri, 09 Nov 2012 14:14:04 +0100") Message-ID: <874nkv5b8s.fsf_-_@redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.1 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org [I am replying to several emails at once as I believe they are logically connected] Tobias Burnus writes: > I tried the 01/10 to 10/10 patch series but it doesn't trigger for the > following test case: > > #include > #include > > int > main() { > int *i; > i = malloc(10*sizeof(*i)); > free(i); /* <<< Free memory. */ > i[10] = 5; /* <<< out of boundary even if not freed. */ > printf("%d\n", i[11]); /* <<< out of boundary even if not freed. */ > return 0; > } > > (All of them are reported by Clang.) If I look at the dump (or > assembler), I see the call to __asan_init, __asan_report_store4 and > __asan_report_load4. However, when running the program ltrace only > shows the calls to: __libc_start_main, __asan_init, malloc, free and > printf. I haven't debugged why the condition is false [see attachment > for the dump]. Right. As David Xinliang says ... Xinliang David Li writes: > It seems that my one line fix in asan branch (r192605) is not included > in Dodji's patch set. That's right. ... I meant to 'squash' this patch into ... From 72ed51c18dd269ee10fa1b70a919d77de498fc06 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 2 Nov 2012 23:29:30 +0100 Subject: [PATCH 03/11] Emit GIMPLE directly instead of gimplifying GENERIC. This patch cleanups the instrumentation code generation by emitting GIMPLE directly, as opposed to emitting GENERIC tree and then gimplifying them. It also does some cleanups here and there * Makefile.in (GTFILES): Add $(srcdir)/asan.c. (asan.o): Update the dependencies of asan.o. * asan.c (tm.h, tree.h, tm_p.h, basic-block.h, flags.h function.h, tree-inline.h, tree-dump.h, diagnostic.h, demangle.h, langhooks.h, ggc.h, cgraph.h, gimple.h): Remove these unused but included headers. (shadow_ptr_types): New variable. (report_error_func): Change is_store argument to bool, don't append newline to function name. (PROB_VERY_UNLIKELY, PROB_ALWAYS): Define. (build_check_stmt): Change is_store argument to bool. Emit GIMPLE directly instead of creating trees and gimplifying them. Mark the error reporting function as very unlikely. (instrument_derefs): Change is_store argument to bool. Use int_size_in_bytes to compute size_in_bytes, simplify size check. Use build_fold_addr_expr instead of build_addr. (transform_statements): Adjust instrument_derefs caller. Use gimple_assign_single_p as stmt test. Don't look at MEM refs in rhs2. (asan_init_shadow_ptr_types): New function. (asan_instrument): Don't push/pop gimplify context. Call asan_init_shadow_ptr_types if not yet initialized. * asan.h (ASAN_SHADOW_SHIFT): Adjust comment. ... this one, to comply with Joseph's comment (in another sub-thread) which was requesting to avoid sending patches that are knowingly broken for the sake of sending them chronologically; but I obviously forgot to do so. It's now fixed and here is the updated patch that combines both commits: * Makefile.in (GTFILES): Add $(srcdir)/asan.c. (asan.o): Update the dependencies of asan.o. * asan.c (tm.h, tree.h, tm_p.h, basic-block.h, flags.h function.h, tree-inline.h, tree-dump.h, diagnostic.h, demangle.h, langhooks.h, ggc.h, cgraph.h, gimple.h): Remove these unused but included headers. (shadow_ptr_types): New variable. (report_error_func): Change is_store argument to bool, don't append newline to function name. (PROB_VERY_UNLIKELY, PROB_ALWAYS): Define. (build_check_stmt): Change is_store argument to bool. Emit GIMPLE directly instead of creating trees and gimplifying them. Mark the error reporting function as very unlikely. (instrument_derefs): Change is_store argument to bool. Use int_size_in_bytes to compute size_in_bytes, simplify size check. Use build_fold_addr_expr instead of build_addr. (transform_statements): Adjust instrument_derefs caller. Use gimple_assign_single_p as stmt test. Don't look at MEM refs in rhs2. (asan_init_shadow_ptr_types): New function. (asan_instrument): Don't push/pop gimplify context. Call asan_init_shadow_ptr_types if not yet initialized. * asan.h (ASAN_SHADOW_SHIFT): Adjust comment. --- gcc/ChangeLog.asan | 28 ++++++ gcc/Makefile.in | 9 +- gcc/asan.c | 284 +++++++++++++++++++++++++++++++---------------------- gcc/asan.h | 2 +- 4 files changed, 200 insertions(+), 123 deletions(-) diff --git a/gcc/ChangeLog.asan b/gcc/ChangeLog.asan index d13a584..0345ac7 100644 --- a/gcc/ChangeLog.asan +++ b/gcc/ChangeLog.asan @@ -1,4 +1,32 @@ 2012-10-11 Jakub Jelinek + Xinliang David Li + Dodji Seketeli + + * Makefile.in (GTFILES): Add $(srcdir)/asan.c. + (asan.o): Update the dependencies of asan.o. + * asan.c (tm.h, tree.h, tm_p.h, basic-block.h, flags.h + function.h, tree-inline.h, tree-dump.h, diagnostic.h, demangle.h, + langhooks.h, ggc.h, cgraph.h, gimple.h): Remove these unused but + included headers. + (shadow_ptr_types): New variable. + (report_error_func): Change is_store argument to bool, don't append + newline to function name. + (PROB_VERY_UNLIKELY, PROB_ALWAYS): Define. + (build_check_stmt): Change is_store argument to bool. Emit GIMPLE + directly instead of creating trees and gimplifying them. Mark + the error reporting function as very unlikely. + (instrument_derefs): Change is_store argument to bool. Use + int_size_in_bytes to compute size_in_bytes, simplify size check. + Use build_fold_addr_expr instead of build_addr. + (transform_statements): Adjust instrument_derefs caller. + Use gimple_assign_single_p as stmt test. Don't look at MEM refs + in rhs2. + (asan_init_shadow_ptr_types): New function. + (asan_instrument): Don't push/pop gimplify context. + Call asan_init_shadow_ptr_types if not yet initialized. + * asan.h (ASAN_SHADOW_SHIFT): Adjust comment. + +2012-10-11 Jakub Jelinek * toplev.c (process_options): Warn and turn off -faddress-sanitizer if not supported by target. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 469c72f..b9a1e74 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2208,10 +2208,10 @@ stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(PARAMS_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) $(RTL_H) \ $(GGC_H) $(TM_P_H) $(TARGET_H) langhooks.h $(REGS_H) gt-stor-layout.h \ $(DIAGNOSTIC_CORE_H) $(CGRAPH_H) $(TREE_INLINE_H) $(TREE_DUMP_H) $(GIMPLE_H) -asan.o : asan.c asan.h $(CONFIG_H) pointer-set.h \ - $(SYSTEM_H) $(TREE_H) $(GIMPLE_H) \ - output.h $(DIAGNOSTIC_H) coretypes.h $(TREE_DUMP_H) $(FLAGS_H) \ - tree-pretty-print.h $(TARGET_H) +asan.o : asan.c asan.h $(CONFIG_H) $(SYSTEM_H) $(GIMPLE_H) \ + output.h coretypes.h $(GIMPLE_PRETTY_PRINT_H) \ + tree-iterator.h $(TREE_FLOW_H) $(TREE_PASS_H) \ + $(TARGET_H) tree-ssa-tail-merge.o: tree-ssa-tail-merge.c \ $(SYSTEM_H) $(CONFIG_H) coretypes.h $(TM_H) $(BITMAP_H) \ $(FLAGS_H) $(TM_P_H) $(BASIC_BLOCK_H) \ @@ -3725,6 +3725,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/lto-streamer.h \ $(srcdir)/target-globals.h \ $(srcdir)/ipa-inline.h \ + $(srcdir)/asan.c \ @all_gtfiles@ # Compute the list of GT header files from the corresponding C sources, diff --git a/gcc/asan.c b/gcc/asan.c index 9655b11..04b11e5 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -22,24 +22,10 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" -#include "tm.h" -#include "tree.h" -#include "tm_p.h" -#include "basic-block.h" -#include "flags.h" -#include "function.h" -#include "tree-inline.h" #include "gimple.h" #include "tree-iterator.h" #include "tree-flow.h" -#include "tree-dump.h" #include "tree-pass.h" -#include "diagnostic.h" -#include "demangle.h" -#include "langhooks.h" -#include "ggc.h" -#include "cgraph.h" -#include "gimple.h" #include "asan.h" #include "gimple-pretty-print.h" #include "target.h" @@ -79,18 +65,22 @@ along with GCC; see the file COPYING3. If not see to create redzones for stack and global object and poison them. */ +/* Pointer types to 1 resp. 2 byte integers in shadow memory. A separate + alias set is used for all shadow memory accesses. */ +static GTY(()) tree shadow_ptr_types[2]; + /* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16}. IS_STORE is either 1 (for a store) or 0 (for a load). SIZE_IN_BYTES is one of 1, 2, 4, 8, 16. */ static tree -report_error_func (int is_store, int size_in_bytes) +report_error_func (bool is_store, int size_in_bytes) { tree fn_type; tree def; char name[100]; - sprintf (name, "__asan_report_%s%d\n", + sprintf (name, "__asan_report_%s%d", is_store ? "store" : "load", size_in_bytes); fn_type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); def = build_fn_decl (name, fn_type); @@ -118,6 +108,9 @@ asan_init_func (void) } +#define PROB_VERY_UNLIKELY (REG_BR_PROB_BASE / 2000 - 1) +#define PROB_ALWAYS (REG_BR_PROB_BASE) + /* Instrument the memory access instruction BASE. Insert new statements before ITER. LOCATION is source code location. @@ -127,21 +120,17 @@ asan_init_func (void) static void build_check_stmt (tree base, gimple_stmt_iterator *iter, - location_t location, int is_store, int size_in_bytes) + location_t location, bool is_store, int size_in_bytes) { gimple_stmt_iterator gsi; basic_block cond_bb, then_bb, join_bb; edge e; - tree cond, t, u; - tree base_addr; - tree shadow_value; + tree t, base_addr, shadow; gimple g; - gimple_seq seq, stmts; - tree shadow_type = size_in_bytes == 16 ? - short_integer_type_node : char_type_node; - tree shadow_ptr_type = build_pointer_type (shadow_type); - tree uintptr_type = lang_hooks.types.type_for_mode (ptr_mode, - /*unsignedp=*/true); + tree shadow_ptr_type = shadow_ptr_types[size_in_bytes == 16 ? 1 : 0]; + tree shadow_type = TREE_TYPE (shadow_ptr_type); + tree uintptr_type + = build_nonstandard_integer_type (TYPE_PRECISION (TREE_TYPE (base)), 1); /* We first need to split the current basic block, and start altering the CFG. This allows us to insert the statements we're about to @@ -166,14 +155,15 @@ build_check_stmt (tree base, /* Create the bb that contains the crash block. */ then_bb = create_empty_bb (cond_bb); - make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE); + e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE); + e->probability = PROB_VERY_UNLIKELY; make_single_succ_edge (then_bb, join_bb, EDGE_FALLTHRU); /* Mark the pseudo-fallthrough edge from cond_bb to join_bb. */ e = find_edge (cond_bb, join_bb); e->flags = EDGE_FALSE_VALUE; e->count = cond_bb->count; - e->probability = REG_BR_PROB_BASE; + e->probability = PROB_ALWAYS - PROB_VERY_UNLIKELY; /* Update dominance info. Note that bb_join's data was updated by split_block. */ @@ -183,75 +173,125 @@ build_check_stmt (tree base, set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb); } - base_addr = create_tmp_reg (uintptr_type, "__asan_base_addr"); + base = unshare_expr (base); - seq = NULL; - t = fold_convert_loc (location, uintptr_type, - unshare_expr (base)); - t = force_gimple_operand (t, &stmts, false, NULL_TREE); - gimple_seq_add_seq (&seq, stmts); - g = gimple_build_assign (base_addr, t); + gsi = gsi_last_bb (cond_bb); + g = gimple_build_assign_with_ops (TREE_CODE (base), + make_ssa_name (TREE_TYPE (base), NULL), + base, NULL_TREE); gimple_set_location (g, location); - gimple_seq_add_stmt (&seq, g); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); - /* Build - (base_addr >> ASAN_SHADOW_SHIFT) | targetm.asan_shadow_offset (). */ - - t = build2 (RSHIFT_EXPR, uintptr_type, base_addr, - build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT)); - t = build2 (PLUS_EXPR, uintptr_type, t, - build_int_cst (uintptr_type, targetm.asan_shadow_offset ())); - t = build1 (INDIRECT_REF, shadow_type, - build1 (VIEW_CONVERT_EXPR, shadow_ptr_type, t)); - t = force_gimple_operand (t, &stmts, false, NULL_TREE); - gimple_seq_add_seq (&seq, stmts); - shadow_value = create_tmp_reg (shadow_type, "__asan_shadow"); - g = gimple_build_assign (shadow_value, t); + g = gimple_build_assign_with_ops (NOP_EXPR, + make_ssa_name (uintptr_type, NULL), + gimple_assign_lhs (g), NULL_TREE); gimple_set_location (g, location); - gimple_seq_add_stmt (&seq, g); - t = build2 (NE_EXPR, boolean_type_node, shadow_value, - build_int_cst (shadow_type, 0)); - if (size_in_bytes < 8) - { + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + base_addr = gimple_assign_lhs (g); - /* Slow path for 1-, 2- and 4- byte accesses. - Build ((base_addr & 7) + (size_in_bytes - 1)) >= shadow_value. */ + /* Build + (base_addr >> ASAN_SHADOW_SHIFT) + targetm.asan_shadow_offset (). */ - u = build2 (BIT_AND_EXPR, uintptr_type, - base_addr, - build_int_cst (uintptr_type, 7)); - u = build1 (CONVERT_EXPR, shadow_type, u); - u = build2 (PLUS_EXPR, shadow_type, u, - build_int_cst (shadow_type, size_in_bytes - 1)); - u = build2 (GE_EXPR, uintptr_type, u, shadow_value); - } - else - u = build_int_cst (boolean_type_node, 1); - t = build2 (TRUTH_AND_EXPR, boolean_type_node, t, u); - t = force_gimple_operand (t, &stmts, false, NULL_TREE); - gimple_seq_add_seq (&seq, stmts); - cond = create_tmp_reg (boolean_type_node, "__asan_crash_cond"); - g = gimple_build_assign (cond, t); + t = build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT); + g = gimple_build_assign_with_ops (RSHIFT_EXPR, + make_ssa_name (uintptr_type, NULL), + base_addr, t); gimple_set_location (g, location); - gimple_seq_add_stmt (&seq, g); - g = gimple_build_cond (NE_EXPR, cond, boolean_false_node, NULL_TREE, - NULL_TREE); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + + t = build_int_cst (uintptr_type, targetm.asan_shadow_offset ()); + g = gimple_build_assign_with_ops (PLUS_EXPR, + make_ssa_name (uintptr_type, NULL), + gimple_assign_lhs (g), t); gimple_set_location (g, location); - gimple_seq_add_stmt (&seq, g); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); - /* Generate call to the run-time library (e.g. __asan_report_load8). */ + g = gimple_build_assign_with_ops (NOP_EXPR, + make_ssa_name (shadow_ptr_type, NULL), + gimple_assign_lhs (g), NULL_TREE); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); - gsi = gsi_last_bb (cond_bb); - gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); - seq = NULL; - g = gimple_build_call (report_error_func (is_store, size_in_bytes), - 1, base_addr); - gimple_seq_add_stmt (&seq, g); + t = build2 (MEM_REF, shadow_type, gimple_assign_lhs (g), + build_int_cst (shadow_ptr_type, 0)); + g = gimple_build_assign_with_ops (MEM_REF, + make_ssa_name (shadow_type, NULL), + t, NULL_TREE); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + shadow = gimple_assign_lhs (g); + + if (size_in_bytes < 8) + { + /* Slow path for 1, 2 and 4 byte accesses. + Test (shadow != 0) + & ((base_addr & 7) + (size_in_bytes - 1)) >= shadow). */ + g = gimple_build_assign_with_ops (NE_EXPR, + make_ssa_name (boolean_type_node, + NULL), + shadow, + build_int_cst (shadow_type, 0)); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + t = gimple_assign_lhs (g); + + g = gimple_build_assign_with_ops (BIT_AND_EXPR, + make_ssa_name (uintptr_type, + NULL), + base_addr, + build_int_cst (uintptr_type, 7)); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + + g = gimple_build_assign_with_ops (NOP_EXPR, + make_ssa_name (shadow_type, + NULL), + gimple_assign_lhs (g), NULL_TREE); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + + if (size_in_bytes > 1) + { + g = gimple_build_assign_with_ops (PLUS_EXPR, + make_ssa_name (shadow_type, + NULL), + gimple_assign_lhs (g), + build_int_cst (shadow_type, + size_in_bytes - 1)); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + } + + g = gimple_build_assign_with_ops (GE_EXPR, + make_ssa_name (boolean_type_node, + NULL), + gimple_assign_lhs (g), + shadow); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + + g = gimple_build_assign_with_ops (BIT_AND_EXPR, + make_ssa_name (boolean_type_node, + NULL), + t, gimple_assign_lhs (g)); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + t = gimple_assign_lhs (g); + } + else + t = shadow; - /* Insert the check code in the THEN block. */ + g = gimple_build_cond (NE_EXPR, t, build_int_cst (TREE_TYPE (t), 0), + NULL_TREE, NULL_TREE); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + /* Generate call to the run-time library (e.g. __asan_report_load8). */ gsi = gsi_start_bb (then_bb); - gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); + g = gimple_build_call (report_error_func (is_store, size_in_bytes), + 1, base_addr); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); *iter = gsi_start_bb (join_bb); } @@ -262,14 +302,12 @@ build_check_stmt (tree base, static void instrument_derefs (gimple_stmt_iterator *iter, tree t, - location_t location, int is_store) + location_t location, bool is_store) { tree type, base; - int size_in_bytes; + HOST_WIDE_INT size_in_bytes; type = TREE_TYPE (t); - if (type == error_mark_node) - return; switch (TREE_CODE (t)) { case ARRAY_REF: @@ -280,25 +318,25 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t, default: return; } - size_in_bytes = tree_low_cst (TYPE_SIZE (type), 0) / BITS_PER_UNIT; - if (size_in_bytes != 1 && size_in_bytes != 2 && - size_in_bytes != 4 && size_in_bytes != 8 && size_in_bytes != 16) - return; - { - /* For now just avoid instrumenting bit field acceses. + + size_in_bytes = int_size_in_bytes (type); + if ((size_in_bytes & (size_in_bytes - 1)) != 0 + || (unsigned HOST_WIDE_INT) size_in_bytes - 1 >= 16) + return; + + /* For now just avoid instrumenting bit field acceses. Fixing it is doable, but expected to be messy. */ - HOST_WIDE_INT bitsize, bitpos; - tree offset; - enum machine_mode mode; - int volatilep = 0, unsignedp = 0; - get_inner_reference (t, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); - if (bitpos != 0 || bitsize != size_in_bytes * BITS_PER_UNIT) - return; - } - - base = build_addr (t, current_function_decl); + HOST_WIDE_INT bitsize, bitpos; + tree offset; + enum machine_mode mode; + int volatilep = 0, unsignedp = 0; + get_inner_reference (t, &bitsize, &bitpos, &offset, + &mode, &unsignedp, &volatilep, false); + if (bitpos != 0 || bitsize != size_in_bytes * BITS_PER_UNIT) + return; + + base = build_fold_addr_expr (t); build_check_stmt (base, iter, location, is_store, size_in_bytes); } @@ -314,7 +352,6 @@ transform_statements (void) basic_block bb; gimple_stmt_iterator i; int saved_last_basic_block = last_basic_block; - enum gimple_rhs_class grhs_class; FOR_EACH_BB (bb) { @@ -322,16 +359,12 @@ transform_statements (void) for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) { gimple s = gsi_stmt (i); - if (gimple_code (s) != GIMPLE_ASSIGN) - continue; + if (!gimple_assign_single_p (s)) + continue; instrument_derefs (&i, gimple_assign_lhs (s), - gimple_location (s), 1); + gimple_location (s), true); instrument_derefs (&i, gimple_assign_rhs1 (s), - gimple_location (s), 0); - grhs_class = get_gimple_rhs_class (gimple_assign_rhs_code (s)); - if (grhs_class == GIMPLE_BINARY_RHS) - instrument_derefs (&i, gimple_assign_rhs2 (s), - gimple_location (s), 0); + gimple_location (s), false); } } } @@ -351,15 +384,28 @@ asan_finish_file (void) MAX_RESERVED_INIT_PRIORITY - 1); } +/* Initialize shadow_ptr_types array. */ + +static void +asan_init_shadow_ptr_types (void) +{ + alias_set_type set = new_alias_set (); + shadow_ptr_types[0] = build_distinct_type_copy (signed_char_type_node); + TYPE_ALIAS_SET (shadow_ptr_types[0]) = 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]) = set; + shadow_ptr_types[1] = build_pointer_type (shadow_ptr_types[1]); +} + /* Instrument the current function. */ static unsigned int asan_instrument (void) { - struct gimplify_ctx gctx; - push_gimplify_context (&gctx); + if (shadow_ptr_types[0] == NULL_TREE) + asan_init_shadow_ptr_types (); transform_statements (); - pop_gimplify_context (NULL); return 0; } @@ -386,6 +432,8 @@ struct gimple_opt_pass pass_asan = 0, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_verify_flow | TODO_verify_stmts - | TODO_update_ssa /* todo_flags_finish */ + | TODO_update_ssa /* todo_flags_finish */ } }; + +#include "gt-asan.h" diff --git a/gcc/asan.h b/gcc/asan.h index 699820b..0d9ab8b 100644 --- a/gcc/asan.h +++ b/gcc/asan.h @@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. If not see extern void asan_finish_file(void); /* Shadow memory is found at - (address >> ASAN_SHADOW_SHIFT) | targetm.asan_shadow_offset (). */ + (address >> ASAN_SHADOW_SHIFT) + targetm.asan_shadow_offset (). */ #define ASAN_SHADOW_SHIFT 3 #endif /* TREE_ASAN */