From patchwork Mon Jun 2 14:51:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilya Enkovich X-Patchwork-Id: 354955 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id D9C991400AB for ; Tue, 3 Jun 2014 00:52:04 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=ZYFKYZ4UShEwPb/GRcR7eJ0eF5A+LIk+ydmfzh77ZzEm81ZpsVEhS WhmAQmEnWb4s5ca/EfgTyiWH0UhIJj7H1BAtsxolq+NLjUSaUYu7AmXgNJVM5XWB iV5EkF0n/ka4fwo7AL0K56+pDCiunEVxNFfHzmCayfW28uXcPoWlhc= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=BKSpCycM0XmwamtteDR5OjZlbnA=; b=VmuywlZ22PfWV1zg+4+v EMLbj0O8l4T33cz8lgIflpEjer/AoJD0svBkodMarfToz4LFqGzpDCKP08HHcuot WblizPqMHSjHGjFuj6iqFwfsCfVEjZ4EoX7o0elzBC2QCyV/jHFFq9dwwQeMWFTp LXmierkMiQxN9o5a0uWchuo= Received: (qmail 19173 invoked by alias); 2 Jun 2014 14:51:57 -0000 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 Received: (qmail 19161 invoked by uid 89); 2 Jun 2014 14:51:56 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.2 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pa0-f46.google.com Received: from mail-pa0-f46.google.com (HELO mail-pa0-f46.google.com) (209.85.220.46) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Mon, 02 Jun 2014 14:51:54 +0000 Received: by mail-pa0-f46.google.com with SMTP id hz1so2005679pad.33 for ; Mon, 02 Jun 2014 07:51:53 -0700 (PDT) X-Received: by 10.68.134.101 with SMTP id pj5mr41644182pbb.62.1401720713086; Mon, 02 Jun 2014 07:51:53 -0700 (PDT) Received: from msticlxl57.ims.intel.com ([192.55.54.40]) by mx.google.com with ESMTPSA id wq10sm65094718pac.24.2014.06.02.07.51.51 for (version=TLSv1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 02 Jun 2014 07:51:52 -0700 (PDT) Date: Mon, 2 Jun 2014 18:51:44 +0400 From: Ilya Enkovich To: gcc-patches@gcc.gnu.org Subject: [PATCH, i386, Pointer Bounds Checker 18/x] Expand instrumented builtin function calls Message-ID: <20140602145144.GA53659@msticlxl57.ims.intel.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes Hi, This patch adds support for normal builtin function calls (target ones are not instrumented). The basic idea of the patch is to make call expr copy with no bounds and expand it instead. If expr is going to be emitted as a function call then original instrumented expr takes place. Handle string function separately because they are of high interest for the checker. Bootstrapped and tested on linux-x86_64. Thanks, Ilya --- gcc/ 2014-06-02 Ilya Enkovich * builtins.c: Include rtl-chkp.h, tree-chkp.h. (expand_builtin_mempcpy_args): Add orig exp as argument. Support BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK. (expand_builtin_mempcpy): Adjust expand_builtin_mempcpy_args call. (expand_builtin_stpcpy): Likewise. (expand_builtin_memset_args): Support BUILT_IN_CHKP_MEMSET_NOBND_NOCHK. (std_expand_builtin_va_start): Initialize bounds for va_list. (expand_builtin): Support instrumented calls. diff --git a/gcc/builtins.c b/gcc/builtins.c index 7357124..c0140e1 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -59,6 +59,8 @@ along with GCC; see the file COPYING3. If not see #include "builtins.h" #include "ubsan.h" #include "cilk.h" +#include "tree-chkp.h" +#include "rtl-chkp.h" static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t)); @@ -124,7 +126,7 @@ static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode); static rtx expand_builtin_memcpy (tree, rtx); static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode); static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, - enum machine_mode, int); + enum machine_mode, int, tree); static rtx expand_builtin_strcpy (tree, rtx); static rtx expand_builtin_strcpy_args (tree, tree, rtx); static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode); @@ -3284,7 +3286,8 @@ expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode) tree src = CALL_EXPR_ARG (exp, 1); tree len = CALL_EXPR_ARG (exp, 2); return expand_builtin_mempcpy_args (dest, src, len, - target, mode, /*endp=*/ 1); + target, mode, /*endp=*/ 1, + exp); } } @@ -3296,10 +3299,23 @@ expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode) static rtx expand_builtin_mempcpy_args (tree dest, tree src, tree len, - rtx target, enum machine_mode mode, int endp) + rtx target, enum machine_mode mode, int endp, + tree orig_exp) { + tree fndecl = get_callee_fndecl (orig_exp); + /* If return value is ignored, transform mempcpy into memcpy. */ - if (target == const0_rtx && builtin_decl_implicit_p (BUILT_IN_MEMCPY)) + if (target == const0_rtx + && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK + && builtin_decl_implicit_p (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK)) + { + tree fn = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK); + tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3, + dest, src, len); + return expand_expr (result, target, mode, EXPAND_NORMAL); + } + else if (target == const0_rtx + && builtin_decl_implicit_p (BUILT_IN_MEMCPY)) { tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY); tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3, @@ -3484,7 +3500,8 @@ expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode) lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1)); ret = expand_builtin_mempcpy_args (dst, src, lenp1, - target, mode, /*endp=*/2); + target, mode, /*endp=*/2, + exp); if (ret) return ret; @@ -3778,7 +3795,8 @@ expand_builtin_memset_args (tree dest, tree val, tree len, do_libcall: fndecl = get_callee_fndecl (orig_exp); fcode = DECL_FUNCTION_CODE (fndecl); - if (fcode == BUILT_IN_MEMSET) + if (fcode == BUILT_IN_MEMSET + || fcode == BUILT_IN_CHKP_MEMSET_NOBND_NOCHK) fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3, dest, val, len); else if (fcode == BUILT_IN_BZERO) @@ -4330,6 +4348,13 @@ std_expand_builtin_va_start (tree valist, rtx nextarg) { rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE); convert_move (va_r, nextarg, 0); + + /* We do not have any valid bounds for the pointer, so + just store zero bounds for it. */ + if (chkp_function_instrumented_p (current_function_decl)) + chkp_expand_bounds_reset_for_mem (valist, + make_tree (TREE_TYPE (valist), + nextarg)); } /* Expand EXP, a call to __builtin_va_start. */ @@ -5793,6 +5818,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp)); int flags; + tree orig_exp = exp; if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) return targetm.expand_builtin (exp, target, subtarget, mode, ignore); @@ -5856,6 +5882,41 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, } } + /* Currently none of builtin expand functions works with bounds. + To avoid modification of all expanders we just make a new call + expression without bound args. The original expression is used + in case we expand builtin as a call. */ + if (CALL_WITH_BOUNDS_P (exp)) + { + int new_arg_no = 0; + tree new_call; + tree arg; + call_expr_arg_iterator iter; + tree *new_args = XALLOCAVEC (tree, call_expr_nargs (exp)); + + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) + if (!POINTER_BOUNDS_P (arg)) + new_args[new_arg_no++] = arg; + + if (new_arg_no > 0) + { + new_call = build_call_array (TREE_TYPE (exp), fndecl, new_arg_no, new_args); + CALL_EXPR_STATIC_CHAIN (new_call) = CALL_EXPR_STATIC_CHAIN (exp); + CALL_EXPR_FN (new_call) = CALL_EXPR_FN (exp); + TREE_SIDE_EFFECTS (new_call) = TREE_SIDE_EFFECTS (exp); + TREE_NOTHROW (new_call) = TREE_NOTHROW (exp); + CALL_EXPR_TAILCALL (new_call) = CALL_EXPR_TAILCALL (exp); + CALL_EXPR_RETURN_SLOT_OPT (new_call) = CALL_EXPR_RETURN_SLOT_OPT (exp); + CALL_ALLOCA_FOR_VAR_P (new_call) = CALL_ALLOCA_FOR_VAR_P (exp); + CALL_FROM_THUNK_P (new_call) = CALL_FROM_THUNK_P (exp); + CALL_EXPR_VA_ARG_PACK (new_call) = CALL_EXPR_VA_ARG_PACK (exp); + SET_EXPR_LOCATION (new_call, EXPR_LOCATION (exp)); + TREE_SET_BLOCK (new_call, TREE_BLOCK (exp)); + + exp = new_call; + } + } + switch (fcode) { CASE_FLT_FN (BUILT_IN_FABS): @@ -6146,60 +6207,116 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, break; case BUILT_IN_STRLEN: + if (CALL_WITH_BOUNDS_P (orig_exp)) + break; target = expand_builtin_strlen (exp, target, target_mode); if (target) return target; break; case BUILT_IN_STRCPY: + if (CALL_WITH_BOUNDS_P (orig_exp)) + break; target = expand_builtin_strcpy (exp, target); if (target) return target; break; case BUILT_IN_STRNCPY: + if (CALL_WITH_BOUNDS_P (orig_exp)) + break; target = expand_builtin_strncpy (exp, target); if (target) return target; break; case BUILT_IN_STPCPY: + if (CALL_WITH_BOUNDS_P (orig_exp)) + break; target = expand_builtin_stpcpy (exp, target, mode); if (target) return target; break; case BUILT_IN_MEMCPY: + case BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK: + if (CALL_WITH_BOUNDS_P (orig_exp) + && fcode == BUILT_IN_MEMCPY) + break; target = expand_builtin_memcpy (exp, target); if (target) - return target; + { + /* We need to set returned bounds for instrumented + calls. */ + if (CALL_WITH_BOUNDS_P (orig_exp)) + { + rtx bnd = force_reg (BNDmode, + expand_normal (CALL_EXPR_ARG (orig_exp, 1))); + target = chkp_join_splitted_slot (target, bnd); + } + return target; + } break; case BUILT_IN_MEMPCPY: + case BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK: + if (CALL_WITH_BOUNDS_P (orig_exp) + && fcode == BUILT_IN_MEMPCPY) + break; target = expand_builtin_mempcpy (exp, target, mode); if (target) - return target; + { + /* We need to set returned bounds for instrumented + calls. */ + if (CALL_WITH_BOUNDS_P (orig_exp)) + { + rtx bnd = force_reg (BNDmode, + expand_normal (CALL_EXPR_ARG (orig_exp, 1))); + target = chkp_join_splitted_slot (target, bnd); + } + return target; + } break; case BUILT_IN_MEMSET: + case BUILT_IN_CHKP_MEMSET_NOBND_NOCHK: + if (CALL_WITH_BOUNDS_P (orig_exp) + && fcode == BUILT_IN_MEMSET) + break; target = expand_builtin_memset (exp, target, mode); if (target) - return target; + { + /* We need to set returned bounds for instrumented + calls. */ + if (CALL_WITH_BOUNDS_P (orig_exp)) + { + rtx bnd = force_reg (BNDmode, + expand_normal (CALL_EXPR_ARG (orig_exp, 1))); + target = chkp_join_splitted_slot (target, bnd); + } + return target; + } break; case BUILT_IN_BZERO: + if (CALL_WITH_BOUNDS_P (orig_exp)) + break; target = expand_builtin_bzero (exp); if (target) return target; break; case BUILT_IN_STRCMP: + if (CALL_WITH_BOUNDS_P (orig_exp)) + break; target = expand_builtin_strcmp (exp, target); if (target) return target; break; case BUILT_IN_STRNCMP: + if (CALL_WITH_BOUNDS_P (orig_exp)) + break; target = expand_builtin_strncmp (exp, target, mode); if (target) return target; @@ -6207,6 +6324,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_BCMP: case BUILT_IN_MEMCMP: + if (CALL_WITH_BOUNDS_P (orig_exp)) + break; target = expand_builtin_memcmp (exp, target, mode); if (target) return target; @@ -6588,14 +6707,17 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, /* If this is turned into an external library call, the weak parameter must be dropped to match the expected parameter list. */ - nargs = call_expr_nargs (exp); + nargs = call_expr_nargs (orig_exp); vec_alloc (vec, nargs - 1); - for (z = 0; z < 3; z++) - vec->quick_push (CALL_EXPR_ARG (exp, z)); - /* Skip the boolean weak parameter. */ - for (z = 4; z < 6; z++) - vec->quick_push (CALL_EXPR_ARG (exp, z)); - exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec); + for (z = 0; z < nargs; z++) + /* Skip the boolean weak parameter. */ + if ((!CALL_WITH_BOUNDS_P (orig_exp) && z == 3) + || (CALL_WITH_BOUNDS_P (orig_exp) && z == 5)) + continue; + else + vec->quick_push (CALL_EXPR_ARG (orig_exp, z)); + orig_exp = build_call_vec (TREE_TYPE (orig_exp), + CALL_EXPR_FN (orig_exp), vec); break; } @@ -6819,6 +6941,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_MEMPCPY_CHK: case BUILT_IN_MEMMOVE_CHK: case BUILT_IN_MEMSET_CHK: + if (CALL_WITH_BOUNDS_P (orig_exp)) + break; target = expand_builtin_memory_chk (exp, target, mode, fcode); if (target) return target; @@ -6873,7 +6997,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_CHKP_GET_PTR_UBOUND: /* We allow user CHKP builtins if Pointer Bounds Checker is off. */ - if (!flag_check_pointer_bounds) + if (!chkp_function_instrumented_p (current_function_decl)) { if (fcode == BUILT_IN_CHKP_SET_PTR_BOUNDS || fcode == BUILT_IN_CHKP_NARROW_PTR_BOUNDS @@ -6911,7 +7035,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, /* The switch statement above can drop through to cause the function to be called normally. */ - return expand_call (exp, target, ignore); + return expand_call (orig_exp, target, ignore); } /* Determine whether a tree node represents a call to a built-in