Received: by 2002:a25:e74b:0:0:0:0:0 with SMTP id e72csp277502ybh; Mon, 20 Jul 2020 16:38:53 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzpJzBq1xeMrm0QzwuiuHtKzTlcYbs0ZWuiyZstEIJ9nWmlkarrJNy76UKSNGWY3ywn2sGt X-Received: by 2002:a17:906:c30b:: with SMTP id s11mr23389455ejz.263.1595288333484; Mon, 20 Jul 2020 16:38:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1595288333; cv=none; d=google.com; s=arc-20160816; b=KpwJDLqOylN8f+CyPygFI96oINEJ7O9L/lsQl/+8HwzvwRy1Jq0C6269/vH9bRJMSt yRX4QOxqbd6w9pM7i3+hIusDd2sMCEgtGgk+aeW+jpoYaXgpT+4CXZJnOZ4wwhNmRcaJ WIKf56taEl1xwy3KCvdAwnvr38r+7kKE8jizMhzLdLLep/uQh7Gw1QhQmyLIeyDEyC8M CPkxpcTYO4fQU3neZaHWvrdiiAZ9vDXILAOsUgDba9uiCS8CBNbeHWIv1iKbGNjkuDXO VP9i7vCymUlGlgYoldVuIQ88KdPGRm+T5vID8E7pNIE7UWkTdD5U0U3DgHM5x+4HWOk+ 9IjQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:dkim-signature; bh=mWZKxoXF+Te4mputAXDqqY/dB7J/WdxovoeFbRYCpJE=; b=leL3TIMAkk7bPrD85wRkC08rbU5Szrs21lgFxaI3E935BB6sfT9p16hZcv8lRmvCvb VMNA/sVLKpEo7j1ZOmEPuQIEzx6pGevABKQCbP8vnJi8lacrdwXC3SDVYViKj34xlyQ4 5dpXVR7g/u72Erw7m/C51f+Ca8A3HSMtIHmwM8LUOOOkWwyTNNTXodPMXPX/KsSUfNyR PBpOFGWJwG9fFIqvuErjusmboYc5D1UVBZxr5Q1zE6ssC43S44LVA68NdYP2qJH3cO3b fgyf/bK9AhHwwDtLGF9e99IbaLSOkPd9c3cu17k3Dw85l/AjqfE+b+BcmORpLcnTnrnJ Hc+g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=BPWrYBNd; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id mf27si11641248ejb.83.2020.07.20.16.38.29; Mon, 20 Jul 2020 16:38:53 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=BPWrYBNd; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726907AbgGTXfy (ORCPT + 99 others); Mon, 20 Jul 2020 19:35:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55702 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726425AbgGTXfy (ORCPT ); Mon, 20 Jul 2020 19:35:54 -0400 Received: from mail-qk1-x74a.google.com (mail-qk1-x74a.google.com [IPv6:2607:f8b0:4864:20::74a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 01C11C061794 for ; Mon, 20 Jul 2020 16:35:54 -0700 (PDT) Received: by mail-qk1-x74a.google.com with SMTP id h4so12509533qkl.23 for ; Mon, 20 Jul 2020 16:35:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=mWZKxoXF+Te4mputAXDqqY/dB7J/WdxovoeFbRYCpJE=; b=BPWrYBNdCpvomKbvbfjEbSAdblRizGHuyW5dY45HKa322xgYaY/sm+HtpMmj6ecl76 V6sKB9ShyFPOBnmNZR+e2xDwaoFEK14gADm5ZTXyF/8jAdOoNDsV6X8hBG0S5gcy0UEn MAykzdzJG988ri6fvw63K0xPtLXwFvu+QeCiwDoIMNTwjB1csx0kioT/e3uKf7B9hRG0 J1MwnYMuYH61W2DDgfpsX18rhUj3jsDqNI29Thi1J5K96yeHR9gLq2JQlSxOdcRq/9Nv jZaPP5em0A1C7bxv8xKqzqUxaV/mdQXs45xWaAUW5Cnrbi1Y5baEebOcLbBWoMKfFuDw 1qgQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=mWZKxoXF+Te4mputAXDqqY/dB7J/WdxovoeFbRYCpJE=; b=aP1CpdCva5K2vr710Xxfk+LcOUzUY137XLdqKIX5BBtkrCzKuIZo9wSKpciQVyfb7l sAqK6W0jI4GybDN7twjMZ4OARbIlf5hoV9rHKxqZ6ZeBhYlIhc5whAb9mS/yv3V7Lodf hJENxX/UDn2aNORPyEOe5k7nzOMakpoAzih1I1mfOzeHpMJHIozshx95xh8hdYbDkdf2 yV4XMgG1ezQXjPnVIe77nm3DZvVsYZYuEZInkWY4j3v//dwM/A4NLIXYSnP17X1hNACY UFhb4fTkufihGVTECJ+xzPjIEWbrysF5bFHyWGNgf41G4/MPFlcn6/7BO8/lirROrrYk aM0g== X-Gm-Message-State: AOAM5323xqy+afww0pRYQgbHjqNyFiRkLTUOsa3EK2c4RFqeD1KGu4zp vNTRs4kkDshgGhDFTtPDkAEvxTwSCQ== X-Received: by 2002:a0c:f991:: with SMTP id t17mr24424118qvn.50.1595288153124; Mon, 20 Jul 2020 16:35:53 -0700 (PDT) Date: Mon, 20 Jul 2020 23:34:51 +0000 In-Reply-To: Message-Id: <20200720233450.238022-1-nhuck@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.28.0.rc0.105.gf9edc3c819-goog Subject: [PATCH v4] Makefile: Add clang-tidy and static analyzer support to makefile From: Nathan Huckleberry To: masahiroy@kernel.org, michal.lkml@markovi.net Cc: linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, clang-built-linux@googlegroups.com, pirama@google.com, morbo@google.com, Nathan Huckleberry Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch adds clang-tidy and the clang static-analyzer as make targets. The goal of this patch is to make static analysis tools usable and extendable by any developer or researcher who is familiar with basic c++. The current static analysis tools require intimate knowledge of the internal workings of the static analysis. Clang-tidy and the clang static analyzers expose an easy to use api and allow users unfamiliar with clang to write new checks with relative ease. ===Clang-tidy=== Clang-tidy is an easily extendable 'linter' that runs on the AST. Clang-tidy checks are easy to write and understand. A check consists of two parts, a matcher and a checker. The matcher is created using a domain specific language that acts on the AST (https://clang.llvm.org/docs/LibASTMatchersReference.html). When AST nodes are found by the matcher a callback is made to the checker. The checker can then execute additional checks and issue warnings. Here is an example clang-tidy check to report functions that have calls to local_irq_disable without calls to local_irq_enable and vice-versa. Functions flagged with __attribute((annotation("ignore_irq_balancing"))) are ignored for analysis. (https://reviews.llvm.org/D65828) ===Clang static analyzer=== The clang static analyzer is a more powerful static analysis tool that uses symbolic execution to find bugs. Currently there is a check that looks for potential security bugs from invalid uses of kmalloc and kfree. There are several more general purpose checks that are useful for the kernel. The clang static analyzer is well documented and designed to be extensible. (https://clang-analyzer.llvm.org/checker_dev_manual.html) (https://github.com/haoNoQ/clang-analyzer-guide/releases/download/v0.1/clang-analyzer-guide-v0.1.pdf) The main draw of the clang tools is how accessible they are. The clang documentation is very nice and these tools are built specifically to be easily extendable by any developer. They provide an accessible method of bug-finding and research to people who are not overly familiar with the kernel codebase. Signed-off-by: Nathan Huckleberry --- Changes v3->v4 * Update usages of static-analyzer to clang-analyzer * Clarify -* explicitly in comment * Remove filename printing MAINTAINERS | 1 + Makefile | 3 + scripts/clang-tools/Makefile.clang-tools | 23 +++++++ .../{ => clang-tools}/gen_compile_commands.py | 0 scripts/clang-tools/run-clang-tools.py | 69 +++++++++++++++++++ 5 files changed, 96 insertions(+) create mode 100644 scripts/clang-tools/Makefile.clang-tools rename scripts/{ => clang-tools}/gen_compile_commands.py (100%) create mode 100755 scripts/clang-tools/run-clang-tools.py diff --git a/MAINTAINERS b/MAINTAINERS index 1d4aa7f942de..a444564e5572 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4198,6 +4198,7 @@ W: https://clangbuiltlinux.github.io/ B: https://github.com/ClangBuiltLinux/linux/issues C: irc://chat.freenode.net/clangbuiltlinux F: Documentation/kbuild/llvm.rst +F: scripts/clang-tools/ K: \b(?i:clang|llvm)\b CLEANCACHE API diff --git a/Makefile b/Makefile index fe0164a654c7..3e2df010b342 100644 --- a/Makefile +++ b/Makefile @@ -747,6 +747,7 @@ KBUILD_CFLAGS += $(call cc-option,-fno-allow-store-data-races) include scripts/Makefile.kcov include scripts/Makefile.gcc-plugins +include scripts/clang-tools/Makefile.clang-tools ifdef CONFIG_READABLE_ASM # Disable optimizations that make assembler listings hard to read. @@ -1543,6 +1544,8 @@ help: @echo ' export_report - List the usages of all exported symbols' @echo ' headerdep - Detect inclusion cycles in headers' @echo ' coccicheck - Check with Coccinelle' + @echo ' clang-analyzer - Check with clang static analyzer' + @echo ' clang-tidy - Check with clang-tidy' @echo '' @echo 'Tools:' @echo ' nsdeps - Generate missing symbol namespace dependencies' diff --git a/scripts/clang-tools/Makefile.clang-tools b/scripts/clang-tools/Makefile.clang-tools new file mode 100644 index 000000000000..5c9d76f77595 --- /dev/null +++ b/scripts/clang-tools/Makefile.clang-tools @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) Google LLC, 2020 +# +# Author: Nathan Huckleberry +# +PHONY += clang-tidy +clang-tidy: +ifdef CONFIG_CC_IS_CLANG + $(PYTHON3) scripts/clang-tools/gen_compile_commands.py + $(PYTHON3) scripts/clang-tools/run-clang-tools.py clang-tidy compile_commands.json +else + $(error clang-tidy requires CC=clang) +endif + +PHONY += clang-analyzer +clang-analyzer: +ifdef CONFIG_CC_IS_CLANG + $(PYTHON3) scripts/clang-tools/gen_compile_commands.py + $(PYTHON3) scripts/clang-tools/run-clang-tools.py clang-analyzer compile_commands.json +else + $(error clang-analyzer requires CC=clang) +endif diff --git a/scripts/gen_compile_commands.py b/scripts/clang-tools/gen_compile_commands.py similarity index 100% rename from scripts/gen_compile_commands.py rename to scripts/clang-tools/gen_compile_commands.py diff --git a/scripts/clang-tools/run-clang-tools.py b/scripts/clang-tools/run-clang-tools.py new file mode 100755 index 000000000000..44527b3663e9 --- /dev/null +++ b/scripts/clang-tools/run-clang-tools.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) Google LLC, 2020 +# +# Author: Nathan Huckleberry +# +"""A helper routine run clang-tidy and the clang static-analyzer on +compile_commands.json.""" + +import argparse +import json +import logging +import multiprocessing +import os +import subprocess +import sys + +def parse_arguments(): + """Set up and parses command-line arguments. + Returns: + args: Dict of parsed args + Has keys "file" and "type" + """ + usage = """Run clang-tidy or the clang static-analyzer on a + compilation database.""" + parser = argparse.ArgumentParser(description=usage) + + type_help = ("Type of analysis to be performed") + parser.add_argument("type", choices=["clang-tidy", "clang-analyzer"], + help=type_help) + file_path_help = ("Path to the compilation database to parse") + parser.add_argument("file", type=str, help=file_path_help) + + args = parser.parse_args() + + return args + +def init(l,t): + global lock + global analysis_type + lock = l + analysis_type = t + +def run_analysis(entry): + filename = entry["file"] + #Disable all checks, then re-enable the ones we want + checks = "-checks=-*,linuxkernel-*" if (analysis_type == "clang-tidy") else "-checks=-*,clang-analyzer-*" + p = subprocess.run(["clang-tidy", "-p", os.getcwd(), + checks, filename], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + lock.acquire() + sys.stderr.buffer.write(p.stdout) + lock.release() + + +def main(): + args = parse_arguments() + filename = args.file + + #Read JSON data into the datastore variable + with open(filename, "r") as f: + datastore = json.load(f) + lock = multiprocessing.Lock() + pool = multiprocessing.Pool(initializer=init, initargs=(lock, args.type)) + pool.map(run_analysis,datastore) + +if __name__ == "__main__": + main() -- 2.28.0.rc0.105.gf9edc3c819-goog