From patchwork Thu Nov 13 21:58:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 410620 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 7E7C51400A0 for ; Fri, 14 Nov 2014 08:58:28 +1100 (AEDT) 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=W4rVzQVIDu8fkMBRn7jvzQlY3ksfB6PuiW50K6EGRWzDV+E6bltNm kY5NOhZitQE/S4+M2w9u5/wHXEEDPObtMKhJ883UXtEG/KJ4QZhZKZ0mGj7i7fsu k1CTfxLuWzZ8HpaIRUphHlVuGl+lQylIFAD4V+ZO8LtlM0UGoNRo04= 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=JIxnMkrtzyyDLiTGExdI702jprk=; b=RAIFomMIV103BRnjkBkd dJXxittB/1UOmkhjY8rVTnTZSrdndIEJKRUvJbJzevC6EC9Bx2F9Ec2o/4UBZyXL aoV6/9By/qnasjvRh4RjZ6g7hFLriKYe93ipWshla4Cb7gY9y4WhsGmkeIz5o5gv hfBWtwDpmn7NuU2i6wBFpO0= Received: (qmail 10506 invoked by alias); 13 Nov 2014 21:58:15 -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 10415 invoked by uid 89); 13 Nov 2014 21:58:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL, BAYES_20, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 13 Nov 2014 21:58:12 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id sADLwAbh007727 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 13 Nov 2014 16:58:10 -0500 Received: from redhat.com (ovpn-116-30.ams2.redhat.com [10.36.116.30]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id sADLw5It025215 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NO); Thu, 13 Nov 2014 16:58:08 -0500 Date: Thu, 13 Nov 2014 22:58:05 +0100 From: Marek Polacek To: GCC Patches , Jakub Jelinek , Richard Biener Subject: [PATCH] -fsanitize=unreachable overhaul (PR sanitizer/63839) Message-ID: <20141113215805.GT29791@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) As Richi pointed in the pr audit trail, instrumenting via folding is bad. In this case we changed __builtin_unreachable, created by the inliner, into BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE which requires VOPS, which is a no-no in folding. So this patch: - marks BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE as const to match BUILT_IN_UNREACHABLE, - moves the __builtin_unreachable instrumentation into sanopt pass, - disables optimize_unreachable when doing the __builtin_unreachable instrumentation, - marks BUILT_IN_UNREACHABLE as "cold" (I don't see how this could make a difference?). Now, BUILT_IN_TRAP should probably be also marked as const+cold; I'm happy to do that as a follow-up. Bootstrapped/regtested on power8-linux, ok for trunk? 2014-11-13 Marek Polacek PR sanitizer/63839 * asan.c (ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST, ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST): Define. * builtin-attrs.def (ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST): Define. * builtins.c (fold_builtin_0): Don't include ubsan.h. Don't instrument BUILT_IN_UNREACHABLE here. * builtins.def (BUILT_IN_UNREACHABLE): Make cold. * sanitizer.def (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE): Make const. * sanopt.c (pass_sanopt::execute): Instrument BUILT_IN_UNREACHABLE. * tree-ssa-ccp.c (optimize_unreachable): Bail out if SANITIZE_UNREACHABLE. * ubsan.c (ubsan_instrument_unreachable): Rewrite for GIMPLE. * ubsan.h (ubsan_instrument_unreachable): Adjust declaration. testsuite/ * c-c++-common/ubsan/pr63839.c: New test. * c-c++-common/ubsan/unreachable-2.c: New test. Marek diff --git gcc/asan.c gcc/asan.c index 79dede7..2961b44 100644 --- gcc/asan.c +++ gcc/asan.c @@ -2346,6 +2346,9 @@ initialize_sanitizer_builtins (void) #define ATTR_TMPURE_NOTHROW_LEAF_LIST ECF_TM_PURE | ATTR_NOTHROW_LEAF_LIST #undef ATTR_NORETURN_NOTHROW_LEAF_LIST #define ATTR_NORETURN_NOTHROW_LEAF_LIST ECF_NORETURN | ATTR_NOTHROW_LEAF_LIST +#undef ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST +#define ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST \ + ECF_CONST | ATTR_NORETURN_NOTHROW_LEAF_LIST #undef ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST #define ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST \ ECF_TM_PURE | ATTR_NORETURN_NOTHROW_LEAF_LIST @@ -2355,6 +2358,9 @@ initialize_sanitizer_builtins (void) #undef ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST #define ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST \ /* ECF_COLD missing */ ATTR_NORETURN_NOTHROW_LEAF_LIST +#undef ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST +#define ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST \ + /* ECF_COLD missing */ ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST #undef DEF_SANITIZER_BUILTIN #define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ decl = add_builtin_function ("__builtin_" NAME, TYPE, ENUM, \ diff --git gcc/builtin-attrs.def gcc/builtin-attrs.def index 9c05a94..c707367 100644 --- gcc/builtin-attrs.def +++ gcc/builtin-attrs.def @@ -145,6 +145,8 @@ DEF_ATTR_TREE_LIST (ATTR_SENTINEL_NOTHROW_LIST, ATTR_SENTINEL, \ ATTR_NULL, ATTR_NOTHROW_LIST) DEF_ATTR_TREE_LIST (ATTR_SENTINEL_NOTHROW_LEAF_LIST, ATTR_SENTINEL, \ ATTR_NULL, ATTR_NOTHROW_LEAF_LIST) +DEF_ATTR_TREE_LIST (ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST, ATTR_CONST,\ + ATTR_NULL, ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST) /* Functions whose pointer parameter(s) are all nonnull. */ DEF_ATTR_TREE_LIST (ATTR_NONNULL_LIST, ATTR_NONNULL, ATTR_NULL, ATTR_NULL) diff --git gcc/builtins.c gcc/builtins.c index 1cd65ed..311c0e3 100644 --- gcc/builtins.c +++ gcc/builtins.c @@ -64,7 +64,6 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "builtins.h" #include "asan.h" -#include "ubsan.h" #include "cilk.h" #include "ipa-ref.h" #include "lto-streamer.h" @@ -9803,14 +9802,6 @@ fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED) case BUILT_IN_CLASSIFY_TYPE: return fold_builtin_classify_type (NULL_TREE); - case BUILT_IN_UNREACHABLE: - if (flag_sanitize & SANITIZE_UNREACHABLE - && (current_function_decl == NULL - || !lookup_attribute ("no_sanitize_undefined", - DECL_ATTRIBUTES (current_function_decl)))) - return ubsan_instrument_unreachable (loc); - break; - default: break; } diff --git gcc/builtins.def gcc/builtins.def index 0406016..8699a41 100644 --- gcc/builtins.def +++ gcc/builtins.def @@ -803,7 +803,7 @@ DEF_GCC_BUILTIN (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, ATTR_NOTHROW_L DEF_EXT_LIB_BUILTIN (BUILT_IN_STRFMON, "strfmon", BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_NOTHROW_3_4) DEF_LIB_BUILTIN (BUILT_IN_STRFTIME, "strftime", BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR, ATTR_FORMAT_STRFTIME_NOTHROW_3_0) DEF_GCC_BUILTIN (BUILT_IN_TRAP, "trap", BT_FN_VOID, ATTR_NORETURN_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_UNREACHABLE, "unreachable", BT_FN_VOID, ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_UNREACHABLE, "unreachable", BT_FN_VOID, ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_UNWIND_INIT, "unwind_init", BT_FN_VOID, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_UPDATE_SETJMP_BUF, "update_setjmp_buf", BT_FN_VOID_PTR_INT, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_VA_COPY, "va_copy", BT_FN_VOID_VALIST_REF_VALIST_ARG, ATTR_NOTHROW_LEAF_LIST) diff --git gcc/sanitizer.def gcc/sanitizer.def index cddc5ea..3fc8c83 100644 --- gcc/sanitizer.def +++ gcc/sanitizer.def @@ -394,7 +394,7 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS, DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE, "__ubsan_handle_builtin_unreachable", BT_FN_VOID_PTR, - ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST) + ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_MISSING_RETURN, "__ubsan_handle_missing_return", BT_FN_VOID_PTR, diff --git gcc/sanopt.c gcc/sanopt.c index 0fc032a..fe2e42d 100644 --- gcc/sanopt.c +++ gcc/sanopt.c @@ -312,6 +312,21 @@ pass_sanopt::execute (function *fun) break; } } + else if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) + { + tree callee = gimple_call_fndecl (stmt); + switch (DECL_FUNCTION_CODE (callee)) + { + case BUILT_IN_UNREACHABLE: + if (flag_sanitize & SANITIZE_UNREACHABLE + && !lookup_attribute ("no_sanitize_undefined", + DECL_ATTRIBUTES (fun->decl))) + no_next = ubsan_instrument_unreachable (&gsi); + break; + default: + break; + } + } if (dump_file && (dump_flags & TDF_DETAILS)) { diff --git gcc/testsuite/c-c++-common/ubsan/pr63839.c gcc/testsuite/c-c++-common/ubsan/pr63839.c index e69de29..e3933f7 100644 --- gcc/testsuite/c-c++-common/ubsan/pr63839.c +++ gcc/testsuite/c-c++-common/ubsan/pr63839.c @@ -0,0 +1,23 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=unreachable" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */ +/* { dg-shouldfail "ubsan" } */ + +static void __attribute__ ((noreturn)) +bar () +{ +} /* { dg-warning "function does return" } */ + +void +foo () +{ + bar (); +} + +int +main (void) +{ + foo (); +} + +/* { dg-output "execution reached a __builtin_unreachable\\(\\) call" } */ diff --git gcc/testsuite/c-c++-common/ubsan/unreachable-2.c gcc/testsuite/c-c++-common/ubsan/unreachable-2.c index e69de29..783ebc2 100644 --- gcc/testsuite/c-c++-common/ubsan/unreachable-2.c +++ gcc/testsuite/c-c++-common/ubsan/unreachable-2.c @@ -0,0 +1,14 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=unreachable" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */ +/* { dg-shouldfail "ubsan" } */ + +int e; + +int +main (void) +{ + return e ? 0 : (__builtin_unreachable (), 1); +} + +/* { dg-output "execution reached a __builtin_unreachable\\(\\) call" } */ diff --git gcc/tree-ssa-ccp.c gcc/tree-ssa-ccp.c index 52d8503..31ca0e1 100644 --- gcc/tree-ssa-ccp.c +++ gcc/tree-ssa-ccp.c @@ -2568,6 +2568,9 @@ optimize_unreachable (gimple_stmt_iterator i) edge e; bool ret; + if (flag_sanitize & SANITIZE_UNREACHABLE) + return false; + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { stmt = gsi_stmt (gsi); diff --git gcc/ubsan.c gcc/ubsan.c index 41cf546..b5b1b92 100644 --- gcc/ubsan.c +++ gcc/ubsan.c @@ -588,17 +588,26 @@ ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...) /* Instrument the __builtin_unreachable call. We just call the libubsan routine instead. */ -tree -ubsan_instrument_unreachable (location_t loc) +bool +ubsan_instrument_unreachable (gimple_stmt_iterator *gsi) { - if (flag_sanitize_undefined_trap_on_error) - return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); + gimple g; + location_t loc = gimple_location (gsi_stmt (*gsi)); - initialize_sanitizer_builtins (); - tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc, NULL_TREE, - NULL_TREE); - tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE); - return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data)); + if (flag_sanitize_undefined_trap_on_error) + g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0); + else + { + tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc, + NULL_TREE, NULL_TREE); + data = build_fold_addr_expr_loc (loc, data); + tree fn + = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE); + g = gimple_build_call (fn, 1, data); + } + gimple_set_location (g, loc); + gsi_replace (gsi, g, false); + return false; } /* Return true if T is a call to a libubsan routine. */ diff --git gcc/ubsan.h gcc/ubsan.h index 27c18eb..dcdbb4f 100644 --- gcc/ubsan.h +++ gcc/ubsan.h @@ -41,7 +41,7 @@ enum ubsan_print_style { extern bool ubsan_expand_bounds_ifn (gimple_stmt_iterator *); extern bool ubsan_expand_null_ifn (gimple_stmt_iterator *); extern bool ubsan_expand_objsize_ifn (gimple_stmt_iterator *); -extern tree ubsan_instrument_unreachable (location_t); +extern bool ubsan_instrument_unreachable (gimple_stmt_iterator *); extern tree ubsan_create_data (const char *, int, const location_t *, ...); extern tree ubsan_type_descriptor (tree, enum ubsan_print_style = UBSAN_PRINT_NORMAL); extern tree ubsan_encode_value (tree, bool = false);