From patchwork Mon Nov 12 16:20:46 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 198416 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 C47E52C0080 for ; Tue, 13 Nov 2012 03:21:18 +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=1353342080; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Cc:Subject:Message-ID:Reply-To: References:MIME-Version:Content-Type:Content-Disposition: In-Reply-To:User-Agent:Mailing-List:Precedence:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=F+QDbajQTISPDErd9wz6jG7uhSU=; b=qkqlnQvPVnt3ltK /el6187ZgjZ2RgVapUt6ju6+RaowNrUN1dX2xTeg0jB+pqy3weAwTvxfs0ibgTqi b62v44Kw686jxt/QYSfru/euAbCaJJ6CaQ5Qu21c7e2vriIPx1URZFTUOg/BoogK n1X/ciVoydU1HIVMjwGJ/018RSu4= 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:Received:Received:Date:From:To:Cc:Subject:Message-ID:Reply-To:References:MIME-Version:Content-Type:Content-Disposition:In-Reply-To:User-Agent:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=vEl4sk93vXo4AOfpjLQMdVmGVJkDqg8QU1EveIgrhCk/3jue9FgDirQKnfDmWP W9Yb7JoiCUEh/c2XAj1ZNXvpyy+joVm2PCsyiuXKrJoF6OMInE2GSAbZkm8flsxs MYRg9dUzmt8OOf9+7d3MMAlolLhZBwBCdDk37wNAAOupU=; Received: (qmail 7484 invoked by alias); 12 Nov 2012 16:21:10 -0000 Received: (qmail 7469 invoked by uid 22791); 12 Nov 2012 16:21:08 -0000 X-SWARE-Spam-Status: No, hits=-6.3 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_CF, TW_TM X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 12 Nov 2012 16:20:57 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id qACGKtxn003844 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 12 Nov 2012 11:20:56 -0500 Received: from zalov.redhat.com (vpn1-4-50.ams2.redhat.com [10.36.4.50]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id qACGKprn031125 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 12 Nov 2012 11:20:54 -0500 Received: from zalov.cz (localhost [127.0.0.1]) by zalov.redhat.com (8.14.5/8.14.5) with ESMTP id qACGKo2S006729; Mon, 12 Nov 2012 17:20:50 +0100 Received: (from jakub@localhost) by zalov.cz (8.14.5/8.14.5/Submit) id qACGKkFe006727; Mon, 12 Nov 2012 17:20:46 +0100 Date: Mon, 12 Nov 2012 17:20:46 +0100 From: Jakub Jelinek To: Dodji Seketeli Cc: gcc-patches@gcc.gnu.org Subject: Re: [PATCH 00/13] Request to merge Address Sanitizer in Message-ID: <20121112162046.GO1886@tucnak.redhat.com> Reply-To: Jakub Jelinek References: <1351799566-31447-1-git-send-email-dodji@redhat.com> <87pq3v8vmi.fsf@redhat.com> <87d2zidctt.fsf@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <87d2zidctt.fsf@redhat.com> User-Agent: Mutt/1.5.21 (2010-09-15) 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 On Mon, Nov 12, 2012 at 05:07:42PM +0100, Dodji Seketeli wrote: > Following a request from Jakub, and given the fact that the patch set > have been reviewed by Diego, I have committed the last set of patches I > have posted to trunk. Thanks, I've committed as obvious the following formatting cleanup. Mostly whitespace changes, otherwise just removed two more occurrences of FFFFFFFF that shouldn't be there. Jakub --- ChangeLog (revision 193441) +++ ChangeLog (working copy) @@ -1,4 +1,8 @@ -2012-11-12 Wei Mi +2012-11-12 Jakub Jelinek + + * asan.c: Formatting cleanups. + +2012-11-12 Wei Mi * gcc.c (LINK_COMMAND_SPEC): Add -lasan to link command if -faddress-sanitizer is on. @@ -28,7 +32,6 @@ * asan.c (create_cond_insert_point_before_iter): Factorize out of ... (build_check_stmt): ... here. - 2012-11-12 Dodji Seketeli * asan.c (create_cond_insert_point_before_iter): Factorize out of ... @@ -40,7 +43,7 @@ represented by an SSA_NAME. 2012-11-12 Jakub Jelinek - Wei Mi + Wei Mi * varasm.c: Include asan.h. (assemble_noswitch_variable): Grow size by asan_red_zone_size @@ -111,7 +114,7 @@ 2012-11-12 Jakub Jelinek Xinliang David Li - Dodji Seketeli + Dodji Seketeli * Makefile.in (GTFILES): Add $(srcdir)/asan.c. (asan.o): Update the dependencies of asan.o. @@ -155,9 +158,9 @@ * config/i386/i386.c (ix86_asan_shadow_offset): New function. (TARGET_ASAN_SHADOW_OFFSET): Define. -2012-11-12 Wei Mi - Diego Novillo - Dodji Seketeli +2012-11-12 Wei Mi + Diego Novillo + Dodji Seketeli * Makefile.in: Add asan.c and its dependencies. * common.opt: Add -faddress-sanitizer option. --- asan.c (revision 193441) +++ asan.c (working copy) @@ -33,42 +33,41 @@ along with GCC; see the file COPYING3. #include "optabs.h" #include "output.h" -/* - AddressSanitizer finds out-of-bounds and use-after-free bugs - with <2x slowdown on average. - - The tool consists of two parts: - instrumentation module (this file) and a run-time library. - The instrumentation module adds a run-time check before every memory insn. - For a 8- or 16- byte load accessing address X: - ShadowAddr = (X >> 3) + Offset - ShadowValue = *(char*)ShadowAddr; // *(short*) for 16-byte access. - if (ShadowValue) - __asan_report_load8(X); - For a load of N bytes (N=1, 2 or 4) from address X: - ShadowAddr = (X >> 3) + Offset - ShadowValue = *(char*)ShadowAddr; - if (ShadowValue) - if ((X & 7) + N - 1 > ShadowValue) - __asan_report_loadN(X); - Stores are instrumented similarly, but using __asan_report_storeN functions. - A call too __asan_init() is inserted to the list of module CTORs. - - The run-time library redefines malloc (so that redzone are inserted around - the allocated memory) and free (so that reuse of free-ed memory is delayed), - provides __asan_report* and __asan_init functions. - - Read more: - http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm - - The current implementation supports detection of out-of-bounds and - use-after-free in the heap, on the stack and for global variables. - - [Protection of stack variables] - - To understand how detection of out-of-bounds and use-after-free works - for stack variables, lets look at this example on x86_64 where the - stack grows downward: +/* AddressSanitizer finds out-of-bounds and use-after-free bugs + with <2x slowdown on average. + + The tool consists of two parts: + instrumentation module (this file) and a run-time library. + The instrumentation module adds a run-time check before every memory insn. + For a 8- or 16- byte load accessing address X: + ShadowAddr = (X >> 3) + Offset + ShadowValue = *(char*)ShadowAddr; // *(short*) for 16-byte access. + if (ShadowValue) + __asan_report_load8(X); + For a load of N bytes (N=1, 2 or 4) from address X: + ShadowAddr = (X >> 3) + Offset + ShadowValue = *(char*)ShadowAddr; + if (ShadowValue) + if ((X & 7) + N - 1 > ShadowValue) + __asan_report_loadN(X); + Stores are instrumented similarly, but using __asan_report_storeN functions. + A call too __asan_init() is inserted to the list of module CTORs. + + The run-time library redefines malloc (so that redzone are inserted around + the allocated memory) and free (so that reuse of free-ed memory is delayed), + provides __asan_report* and __asan_init functions. + + Read more: + http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm + + The current implementation supports detection of out-of-bounds and + use-after-free in the heap, on the stack and for global variables. + + [Protection of stack variables] + + To understand how detection of out-of-bounds and use-after-free works + for stack variables, lets look at this example on x86_64 where the + stack grows downward: int foo () @@ -82,28 +81,28 @@ along with GCC; see the file COPYING3. return a[5] + b[1]; } - For this function, the stack protected by asan will be organized as - follows, from the top of the stack to the bottom: + For this function, the stack protected by asan will be organized as + follows, from the top of the stack to the bottom: - Slot 1/ [red zone of 32 bytes called 'RIGHT RedZone'] + Slot 1/ [red zone of 32 bytes called 'RIGHT RedZone'] - Slot 2/ [8 bytes of red zone, that adds up to the space of 'a' to make - the next slot be 32 bytes aligned; this one is called Partial - Redzone; this 32 bytes alignment is an asan constraint] + Slot 2/ [8 bytes of red zone, that adds up to the space of 'a' to make + the next slot be 32 bytes aligned; this one is called Partial + Redzone; this 32 bytes alignment is an asan constraint] - Slot 3/ [24 bytes for variable 'a'] + Slot 3/ [24 bytes for variable 'a'] - Slot 4/ [red zone of 32 bytes called 'Middle RedZone'] + Slot 4/ [red zone of 32 bytes called 'Middle RedZone'] - Slot 5/ [24 bytes of Partial Red Zone (similar to slot 2] + Slot 5/ [24 bytes of Partial Red Zone (similar to slot 2] - Slot 6/ [8 bytes for variable 'b'] + Slot 6/ [8 bytes for variable 'b'] - Slot 7/ [32 bytes of Red Zone at the bottom of the stack, called 'LEFT - RedZone'] + Slot 7/ [32 bytes of Red Zone at the bottom of the stack, called + 'LEFT RedZone'] - The 32 bytes of LEFT red zone at the bottom of the stack can be - decomposed as such: + The 32 bytes of LEFT red zone at the bottom of the stack can be + decomposed as such: 1/ The first 8 bytes contain a magical asan number that is always 0x41B58AB3. @@ -122,7 +121,7 @@ along with GCC; see the file COPYING3. 3/ The following 16 bytes of the red zone have no particular format. - The shadow memory for that stack layout is going to look like this: + The shadow memory for that stack layout is going to look like this: - content of shadow memory 8 bytes for slot 7: 0xF1F1F1F1. The F1 byte pattern is a magic number called @@ -149,39 +148,39 @@ along with GCC; see the file COPYING3. seat between two 32 aligned slots of {variable,padding}. - content of shadow memory 8 bytes for slot 3 and 2: - 0xFFFFFFFFF4000000. This represents is the concatenation of + 0xF4000000. This represents is the concatenation of variable 'a' and the partial red zone following it, like what we had for variable 'b'. The least significant 3 bytes being 00 means that the 3 bytes of variable 'a' are addressable. - - content of shadow memory 8 bytes for slot 1: 0xFFFFFFFFF3F3F3F3. + - content of shadow memory 8 bytes for slot 1: 0xF3F3F3F3. The F3 byte pattern is a magic number called ASAN_STACK_MAGIC_RIGHT. It flags the fact that the memory region for this shadow byte is a RIGHT red zone intended to seat at the top of the variables of the stack. - Note that the real variable layout is done in expand_used_vars in - cfgexpand.c. As far as Address Sanitizer is concerned, it lays out - stack variables as well as the different red zones, emits some - prologue code to populate the shadow memory as to poison (mark as - non-accessible) the regions of the red zones and mark the regions of - stack variables as accessible, and emit some epilogue code to - un-poison (mark as accessible) the regions of red zones right before - the function exits. - - [Protection of global variables] - - The basic idea is to insert a red zone between two global variables - and install a constructor function that calls the asan runtime to do - the populating of the relevant shadow memory regions at load time. - - So the global variables are laid out as to insert a red zone between - them. The size of the red zones is so that each variable starts on a - 32 bytes boundary. - - Then a constructor function is installed so that, for each global - variable, it calls the runtime asan library function - __asan_register_globals_with an instance of this type: + Note that the real variable layout is done in expand_used_vars in + cfgexpand.c. As far as Address Sanitizer is concerned, it lays out + stack variables as well as the different red zones, emits some + prologue code to populate the shadow memory as to poison (mark as + non-accessible) the regions of the red zones and mark the regions of + stack variables as accessible, and emit some epilogue code to + un-poison (mark as accessible) the regions of red zones right before + the function exits. + + [Protection of global variables] + + The basic idea is to insert a red zone between two global variables + and install a constructor function that calls the asan runtime to do + the populating of the relevant shadow memory regions at load time. + + So the global variables are laid out as to insert a red zone between + them. The size of the red zones is so that each variable starts on a + 32 bytes boundary. + + Then a constructor function is installed so that, for each global + variable, it calls the runtime asan library function + __asan_register_globals_with an instance of this type: struct __asan_global { @@ -202,8 +201,8 @@ along with GCC; see the file COPYING3. uptr __has_dynamic_init; } - A destructor function that calls the runtime asan library function - _asan_unregister_globals is also installed. */ + A destructor function that calls the runtime asan library function + _asan_unregister_globals is also installed. */ alias_set_type asan_shadow_set = -1; @@ -475,7 +474,7 @@ asan_protect_global (tree decl) return false; #endif - return true; + return true; } /* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16}. @@ -490,13 +489,13 @@ report_error_func (bool is_store, int si char name[100]; sprintf (name, "__asan_report_%s%d", - is_store ? "store" : "load", size_in_bytes); + 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); TREE_NOTHROW (def) = 1; TREE_THIS_VOLATILE (def) = 1; /* Attribute noreturn. Surprise! */ - DECL_ATTRIBUTES (def) = tree_cons (get_identifier ("leaf"), - NULL, DECL_ATTRIBUTES (def)); + DECL_ATTRIBUTES (def) = tree_cons (get_identifier ("leaf"), + NULL, DECL_ATTRIBUTES (def)); DECL_ASSEMBLER_NAME (def); return def; } @@ -598,7 +597,7 @@ create_cond_insert_point (gimple_stmt_it outcoming edge of the 'then block' -- starts with the statement pointed to by ITER. - COND is the condition of the if. + COND is the condition of the if. If THEN_MORE_LIKELY_P is true, the probability of the edge to the 'then block' is higher than the probability of the edge to the @@ -796,7 +795,7 @@ build_check_stmt (location_t location, t static void instrument_derefs (gimple_stmt_iterator *iter, tree t, - location_t location, bool is_store) + location_t location, bool is_store) { tree type, base; HOST_WIDE_INT size_in_bytes; @@ -864,7 +863,7 @@ instrument_mem_region_access (tree base, if (len != 0) { //asan instrumentation code goes here. - } + } // falltrough instructions, starting with *ITER. */ gimple g = gimple_build_cond (NE_EXPR, @@ -930,7 +929,7 @@ instrument_mem_region_access (tree base, region_end = gimple_build_assign_with_ops (POINTER_PLUS_EXPR, make_ssa_name (TREE_TYPE (base), NULL), - gimple_assign_lhs (region_end), + gimple_assign_lhs (region_end), gimple_assign_lhs (offset)); gimple_set_location (region_end, location); gsi_insert_after (&gsi, region_end, GSI_NEW_STMT); @@ -1378,7 +1377,7 @@ transform_statements (void) { if (bb->index >= saved_last_basic_block) continue; for (i = gsi_start_bb (bb); !gsi_end_p (i);) - { + { gimple s = gsi_stmt (i); if (gimple_assign_single_p (s)) @@ -1391,7 +1390,7 @@ transform_statements (void) continue; } gsi_next (&i); - } + } } } @@ -1594,18 +1593,18 @@ struct gimple_opt_pass pass_asan = { { GIMPLE_PASS, - "asan", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - gate_asan, /* gate */ - asan_instrument, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ + "asan", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + gate_asan, /* gate */ + asan_instrument, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_NONE, /* tv_id */ PROP_ssa | PROP_cfg | PROP_gimple_leh,/* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ TODO_verify_flow | TODO_verify_stmts | TODO_update_ssa /* todo_flags_finish */ } @@ -1622,7 +1621,7 @@ struct gimple_opt_pass pass_asan_O0 = { GIMPLE_PASS, "asan0", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ + OPTGROUP_NONE, /* optinfo_flags */ gate_asan_O0, /* gate */ asan_instrument, /* execute */ NULL, /* sub */