From patchwork Tue Jun 9 11:53:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 1305841 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49h7n7548cz9sQx for ; Tue, 9 Jun 2020 21:53:46 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3ACC2383E811; Tue, 9 Jun 2020 11:53:42 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by sourceware.org (Postfix) with ESMTPS id CF471383F869 for ; Tue, 9 Jun 2020 11:53:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org CF471383F869 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mliska@suse.cz X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 68AAFACBD; Tue, 9 Jun 2020 11:53:42 +0000 (UTC) From: =?utf-8?q?Martin_Li=C5=A1ka?= Subject: [PATCH] sanitizer: do not inline no-sanitize into sanitizer fn To: gcc-patches@gcc.gnu.org Message-ID: <0575e910-77da-cd5a-555b-95ea8432fd32@suse.cz> Date: Tue, 9 Jun 2020 13:53:38 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.8.1 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-14.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jakub Jelinek , Marco Elver , Borislav Petkov , Jan Hubicka Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" Hello. The patch is follow up of the kernel discussion: https://lore.kernel.org/lkml/CANpmjNNRz5OVKb6PE7K6GjfoGbht_ZhyPkNG9aD+KjNDzK7hGg@mail.gmail.com/ The patch changes inliner in the following way: 1) do not compare caller and callee sanitizer attributes for always_inline functions - that matches Clang behavior 2) do not inline if one function is sanitized and the second one isn't (for all ASAN, UBSAN, TSAN, LSAN sanitizers); that also matches what Clang does Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed? Thanks, Martin gcc/ChangeLog: * cif-code.def (ATTRIBUTE_MISMATCH): Rename to... (SANITIZE_ATTRIBUTE_MISMATCH): ...this. * ipa-inline.c (sanitize_attrs_match_for_inline_p): Handle all sanitizer options. (can_inline_edge_p): Use renamed CIF_* enum value. gcc/testsuite/ChangeLog: * c-c++-common/asan/inline.c: New test. * c-c++-common/tsan/inline.c: New test. * c-c++-common/ubsan/inline.c: New test. --- gcc/cif-code.def | 7 +++--- gcc/ipa-inline.c | 29 ++++++++++++++--------- gcc/testsuite/c-c++-common/asan/inline.c | 20 ++++++++++++++++ gcc/testsuite/c-c++-common/tsan/inline.c | 20 ++++++++++++++++ gcc/testsuite/c-c++-common/ubsan/inline.c | 20 ++++++++++++++++ 5 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/asan/inline.c create mode 100644 gcc/testsuite/c-c++-common/tsan/inline.c create mode 100644 gcc/testsuite/c-c++-common/ubsan/inline.c diff --git a/gcc/cif-code.def b/gcc/cif-code.def index 31c18c6c691..c65b2477203 100644 --- a/gcc/cif-code.def +++ b/gcc/cif-code.def @@ -128,9 +128,10 @@ DEFCIFCODE(OPTIMIZATION_MISMATCH, CIF_FINAL_ERROR, DEFCIFCODE(USES_COMDAT_LOCAL, CIF_FINAL_ERROR, N_("callee refers to comdat-local symbols")) -/* We can't inline because of mismatched caller/callee attributes. */ -DEFCIFCODE(ATTRIBUTE_MISMATCH, CIF_FINAL_ERROR, - N_("function attribute mismatch")) +/* We can't inline because of mismatched caller/callee + sanitizer attributes. */ +DEFCIFCODE(SANITIZE_ATTRIBUTE_MISMATCH, CIF_FINAL_ERROR, + N_("sanitizer function attribute mismatch")) /* We can't inline because the user requests only static functions but the function has external linkage for live patching purpose. */ diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index f71443feff7..edf4095bcbc 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -264,18 +264,25 @@ sanitize_attrs_match_for_inline_p (const_tree caller, const_tree callee) if (!caller || !callee) return true; - /* Allow inlining always_inline functions into no_sanitize_address - functions. */ - if (!sanitize_flags_p (SANITIZE_ADDRESS, caller) - && lookup_attribute ("always_inline", DECL_ATTRIBUTES (callee))) + /* Follow clang and allow inlining for always_inline functions. */ + if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (callee))) return true; - return ((sanitize_flags_p (SANITIZE_ADDRESS, caller) - == sanitize_flags_p (SANITIZE_ADDRESS, callee)) - && (sanitize_flags_p (SANITIZE_POINTER_COMPARE, caller) - == sanitize_flags_p (SANITIZE_POINTER_COMPARE, callee)) - && (sanitize_flags_p (SANITIZE_POINTER_SUBTRACT, caller) - == sanitize_flags_p (SANITIZE_POINTER_SUBTRACT, callee))); + const sanitize_code codes[] = + { + SANITIZE_ADDRESS, + SANITIZE_THREAD, + SANITIZE_LEAK, + SANITIZE_UNDEFINED, + SANITIZE_UNDEFINED_NONDEFAULT + }; + + for (unsigned i = 0; i < sizeof (codes) / sizeof (codes[0]); i++) + if (sanitize_flags_p (codes[i], caller) + != sanitize_flags_p (codes[i], callee)) + return false; + + return true; } /* Used for flags where it is safe to inline when caller's value is @@ -382,7 +389,7 @@ can_inline_edge_p (struct cgraph_edge *e, bool report, /* Don't inline a function with mismatched sanitization attributes. */ else if (!sanitize_attrs_match_for_inline_p (caller->decl, callee->decl)) { - e->inline_failed = CIF_ATTRIBUTE_MISMATCH; + e->inline_failed = CIF_SANITIZE_ATTRIBUTE_MISMATCH; inlinable = false; } if (!inlinable && report) diff --git a/gcc/testsuite/c-c++-common/asan/inline.c b/gcc/testsuite/c-c++-common/asan/inline.c new file mode 100644 index 00000000000..7c36702cf9e --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/inline.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=address -c -O3 -fdump-tree-optimized" } */ + +int x; + +static inline +__attribute__((no_sanitize("address"))) +void do_not_sanitize(void) +{ + x++; +} + +void +sanitize_this(void) +{ + x++; + do_not_sanitize(); +} + +/* { dg-final { scan-tree-dump-times "Function do_not_sanitize" 1 "optimized" } } */ diff --git a/gcc/testsuite/c-c++-common/tsan/inline.c b/gcc/testsuite/c-c++-common/tsan/inline.c new file mode 100644 index 00000000000..7fb3e576f54 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/inline.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=thread -c -O3 -fdump-tree-optimized" } */ + +int x; + +static inline +__attribute__((no_sanitize("thread"))) +void do_not_sanitize(void) +{ + x++; +} + +void +sanitize_this(void) +{ + x++; + do_not_sanitize(); +} + +/* { dg-final { scan-tree-dump-times "Function do_not_sanitize" 1 "optimized" } } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/inline.c b/gcc/testsuite/c-c++-common/ubsan/inline.c new file mode 100644 index 00000000000..de9660427f6 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/inline.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=vla-bound -c -O3 -fdump-tree-optimized" } */ + +int x; + +static inline +__attribute__((no_sanitize("undefined"))) +void do_not_sanitize(void) +{ + x++; +} + +void +sanitize_this(void) +{ + x++; + do_not_sanitize(); +} + +/* { dg-final { scan-tree-dump-times "Function do_not_sanitize" 1 "optimized" } } */