Clang Static Analyzer 系列(一)编译 Clang 及运行 Checker

编译 Clang

CSA (Clang Static Analyzer) 是 clang 的一部分。建议使用自行编译的 clang ,源码在 llvm/llvm-project (github.com) 上获取。

编译 clang 前首先要生成 clang 的编译脚本。在生成 clang 的编译脚本时通常需要设置如下几个参数:

  • -S 源代码路径

  • -B 生成的编译脚本放置的目录

  • -G 编译工具的选择,对应生成不同工具需要的编译脚本,如 ninja ,默认是 make 和 cmake

  • -DLLVM_ENABLE_PROJECTS 说明要编译的子项目,如 clang 、 clang-tools-extra 等,默认是 all

  • -DCMAKE_BUILD_TYPE 说明编译的类型,如 Debug 、 Release 等,默认是 Debug

  • -CMAKE_INSTALL_PREFIX 类似于 configure 脚本的 –prefix ,用于配合 INSTALL 指令( make install )使用,指定安装路径

  • -DCMAKE_CXX_COMPILERDCMAKE_C_COMPILER 指定使用的编译器,如 clang 或 gcc

使用 cmake 的例子1:

cd llvm-project
mkdir build
cd build
cmake -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" ../llvm
cmake -DLLVM_ENABLE_PROJECTS=clang -G "Unix Makefiles" ../llvm
make

使用 cmake 的例子2:

git clone --depth 1 --branch llvmorg-12.0.1 https://github.com/llvm/llvm-project.git
cmake -S llvm-project/llvm -B llvm-project/build \
        -DCMAKE_BUILD_TYPE=Release \
        -DLLVM_ENABLE_PROJECTS=all \
        -DCMAKE_CXX_COMPILER=clang++ \
        -DCMAKE_C_COMPILER=clang
cmake --build llvm-project/build -j8
cmake --install llvm-project/build --prefix /usr/local  # or somewhere else

使用 ninja 的例子:

cd llvm-project
mkdir build
cd build
cmake -S ../llvm -B build -G Ninja -DLLVM_ENABLE_PROJECTS="clang;libcxx;libcxxabi" -DCMAKE_INSTALL_PREFIX=/home/xxx/llvm_project/build_tmp
cd build
ninja && ninja install

最终我的版本:

cd llvm-project
mkdir installed
# 编译 Debug 版本的 clang 和 clang-tools-extra ,中间编译脚本存储在 build ,生成的可执行程序包安装在 installed
cmake -S llvm -B build -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_INSTALL_PREFIX=$PWD/installed
# 使用 build 目录中的内容进行编译
cmake --build build -j8
# 安装到前面 DCMAKE_INSTALL_PREFIX 指定的目录
# 试过 cmake --install build --prefix installed 不成功
make install
# 把生成的 clang 等可执行文件路径设置到环境变量中
export PATH=/xxx/llvm-project/installed/bin/:$PATH

新版(240322):

xz -dk llvm-project-15.0.4.src.tar.xz
tar -xf llvm-project-15.0.4.src.tar
mkdir llvm-project-15.0.4.src_installed
cd llvm-project-15.0.4.src
# 编译配置 Debug 版本的 clang 和 clang-tools-extra ,中间编译脚本存储在 build ,生成的可执行程序包安装在 installed
cmake -S llvm -B build -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_INSTALL_PREFIX=$PWD/../llvm-project-15.0.4.src_installed
# 使用 build 目录中的内容进行编译
cmake --build build -j8
# 安装到前面 DCMAKE_INSTALL_PREFIX 指定的目录
cd build && make install

参考:

Clang - Getting Started (llvm.org)

LLVM(1)-编译自己的LLVM和Clang - 掘金 (juejin.cn)

打印 AST CFG CallGraph ExplodedGraph 等信息

拥有 clang 的可执行文件后,我们可以先试一下输出代码的基础信息,如 AST 、 CFG 、 CallGraph 和 ExplodedGraph 。其中 AST 并非 CSA 提供的功能,后面三种图都可以通过指定 CSA 的 Checker 进行输出。 ExplodedGraph 是 CSA 中最重要的概念,包含了代码的执行路径和程序状态。这里需要注意使用 debug 开头的 Checker 需要 clang 是 Debug 版本,也就是如果想要输出 CFG 、 CallGraph 和 ExplodedGraph 信息,则需要编译 clang 时指定 -DCMAKE_BUILD_TYPEDebug

打印 AST 信息:

clang -cc1 -ast-dump test.c

列出 CSA 中支持列出的信息:

# 以 llvm-project 12.0.1 为例,仅 -analyzer-checker-help 无法显示所有的 Checkers
# 若需要显示 debug 开头的 Checkers ,需要使用 -analyzer-checker-help-developer
clang -cc1 -analyzer-checker-help-developer

其中 debug 开头的 Checkers 有:

debug.AnalysisOrder           Print callbacks that are called during analysis in order
debug.ConfigDumper            Dump config table
debug.DebugContainerModeling  Check the analyzer's understanding of C++ containers
debug.DebugIteratorModeling   Check the analyzer's understanding of C++ iterators
debug.DumpCFG                 Display Control-Flow Graphs
debug.DumpCallGraph           Display Call Graph
debug.DumpCalls               Print calls as they are traversed by the engine
debug.DumpControlDependencies Print the post control dependency tree for a given CFG
debug.DumpDominators          Print the dominance tree for a given CFG
debug.DumpLiveExprs           Print results of live expression analysis
debug.DumpLiveVars            Print results of live variable analysis
debug.DumpPostDominators      Print the post dominance tree for a given CFG
debug.DumpTraversal           Print branch conditions as they are traversed by the engine
debug.ExprInspection          Check the analyzer's understanding of expressions
debug.ReportStmts             Emits a warning for every statement.
debug.Stats                   Emit warnings with analyzer statistics
debug.StdCLibraryFunctionsTester
Add test functions to the summary map, so testing of individual summary constituents becomes possible.
debug.StreamTester            Add test functions to StreamChecker for test and debugging purposes.
debug.TaintTest               Mark tainted symbols as such.
debug.ViewCFG                 View Control-Flow Graphs using GraphViz
debug.ViewCallGraph           View Call Graph using GraphViz
debug.ViewExplodedGraph       View Exploded Graphs using GraphViz

打印 CFG 、 CallGraph 、 ExplodedGraph 信息:

clang -cc1 -analyze -analyzer-checker=debug.DumpCFG test.c
# 针对 c++ ,建议使用 -Xclang 和 -c ,如果使用 -cc1 可能还需要手动 -I 指定库头文件地址
# -Xclang <arg>    Pass <arg> to the clang compiler  表示传参给编译器部分
# -c               Only run preprocess, compile, and assemble steps
clang++ -Xclang -analyze -Xclang -analyzer-checker=debug.DumpCFG -c test.cpp
# 或直接使用 --analyze 来执行 CSA ,就不需要使用 -c ,本身 CSA 就不会进行编译后的过程
clang++ --analyze -Xclang -analyzer-checker=debug.DumpCFG test.cpp
clang++ --analyze -Xclang -analyzer-checker=debug.ViewCFG test.cpp
clang++ --analyze -Xclang -analyzer-checker=debug.DumpCallGraph test.cpp
clang++ --analyze -Xclang -analyzer-checker=debug.ViewCallGraph test.cpp
clang++ --analyze -Xclang -analyzer-checker=debug.ViewExplodedGraph test.cpp

对于 View 开头的选项即查看 CFG 等,需要有合适的 viewer ,推荐安装 Graphviz :

sudo apt install graphviz

一般来说安装后使用 View 选项即可弹出窗口显示图, dot 文件会暂时保存到 tmp 目录中,若想保存为 SVG (推荐)或 JPG 或 PDF 格式可以:

dot -Tsvg /tmp/ExprEngine-123456.dot > ExprEngine-123456.svg
dot -Tjpg /tmp/ExprEngine-123456.dot > ExprEngine-123456.jpg
dot -Tpdf /tmp/ExprEngine-123456.dot > ExprEngine-123456.pdf

对于一个函数内容比较多时,建议关闭 dotty 弹出窗口,否则有可能一下弹出上千个窗口。

参考:

clang static analyzer源码分析(二)_电影旅行敲代码的博客-CSDN博客

PDF | Graphviz

运行 Checker 检查代码

使用 --analyze 选项运行 CSA

CSA 中包含很多写好的 Checker ,或者我们可以编写自己的 Checker 。这些 Checker 不是被动地读取 ExplodedGraph 的信息,而是主动参与到 ExplodedGraph 的建立中,帮助我们发现安全问题。其实在查看 CFG 、 CallGraph 和 ExplodedGraph 信息时,我们就已经运行了 Checker ,这里更正式地讲一下如何运行 Checker 。

Clang 的 --analyze 编译选项表示运行静态分析器(the static analyzer,指的就是 CSA):

# --analyze  Run the static analyzer
clang --analyze test.c
# 另一种方式
clang -Xclang -analyze -c test.c

使用 -analyzer-checker 选项指定具体的 Checker :

clang --analyze -Xclang -analyzer-checker=core test.c

列出可用的 Checker :

clang -cc1 -analyzer-checker-help
clang -cc1 -analyzer-checker-help-developer

默认分析的输出为 plist 格式,指定输出 html 格式的报告,这时需要用 -o 指定输出的路径:

# --analyzer-output <value>    Static analyzer report output format (html|plist|plist-multi-file|plist-html|sarif|text).
# 输出的路径不用提前创建,会自动创建
clang --analyze --analyzer-output html -o <output-dir> test.c
clang --analyze --analyzer-output html -o <output-dir> -Xclang -analyzer-checker=core test.c
# 另一种方式(我更偏好)
clang --analyze -Xclang -analyzer-output=html -o <output-dir> test.c
clang --analyze -Xclang -analyzer-output=html -o <output-dir> -Xclang -analyzer-checker=core test.c

使用 scan-build 运行 CSA

(不推荐使用)

如果使用 scan-buildscan-view 来集成:

scan-build [scan-build options] <command> [command options]

即在编译命令 <command> 前加上 scan-build 即可。比如 scan-build makescan-build -V clang -c file.c 。其中 -V 表示输出报告。

关于 scan-buildscan-view

scan-build: scan-build is the high-level command line utility for running the analyzer
scan-view: scan-view a companion command line utility to scan-build, scan-view is used to view analysis results generated by scan-build. There is an option that one can pass to scan-build to cause scan-view to run as soon as it the analysis of a build completes

参考:

scan-build: running the analyzer from the command line (llvm.org)

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Clang静态分析器是一个用于检测C、C++和Objective-C代码中潜在问题的工具。它可以在编译时对代码进行静态分析,以检测内存泄漏、空指针引用、未初始化变量等问题,并生成相应的警告或错误信息。Clang静态分析器是Clang编译器的一部分,可以通过命令行或集成开发环境(IDE)使用。它是一个非常有用的工具,可以帮助开发人员提高代码质量和可靠性。 ### 回答2: Clang Static Analyzer(以下简称CSA)是一款由LLVM项目开发的静态分析工具。它采用基于路径进行符号执行的分析方式,在程序编写阶段对源代码进行扫描,自动检测代码中的潜在问题,如内存泄漏、空指针引用、数组越界等,并给出相应的警报和建议,帮助程序员尽早发现和修复代码中的缺陷。 CSA具有以下几个特点: 1.准确性高:采用符号执行技术,可以深入分析程序的每一个执行路径,准确地定位问题点。 2.兼容性强:支持C、C++和Objective-C等多种语言的静态分析,并支持多种平台,可在Windows、Linux、Mac OSX等多个操作系统中使用。 3.使用简单:作为Clang编译器的一部分,CSA可与其他Clang工具集成使用,无需额外设置与安装,用户只需在编译时加入相应的编译选项即可。 4.可扩展性好:CSA提供良好的插件机制,方便开发者扩展自定义的分析插件和规则库,满足不同应用场景的需求。 总之,CSA是一款十分实用的静态分析工具,可以有效地改善程序的质量,提高开发效率。使用CSA进行代码分析,不仅能够保证程序的可靠性与稳定性,同时也会让程序员更深入地了解程序设计的细节,从而提升自己的编程技能与水平。 ### 回答3: Clang是一种基于LLVM基础架构的C/C++编译器。他是Apple公司推出的,始终致力于提高代码的质量。Clang像其他编译器一样,有一个静态代码分析的工具,它叫做Clang Static Analyzer。它是一个非常有用的工具,可以检测代码中的一些潜在问题,并给出一些自动化的建议和修复建议,从而帮助开发人员开发出更好的代码。在这篇文章中,我们将讨论Clang Static Analyzer的优点和使用方法。 Clang静态分析器的优点有: 1. 更好的准确性:Clang静态分析器使用LLVM框架,这使得它在识别潜在的问题方面更准确。 2. 杜绝缺陷:Clang静态分析器可以帮助开发人员解决所有类型的缺陷,如内存泄漏、空指针解引用、死锁等等。 3. 改进效率:由于静态分析器可以自动地检查代码,它可以提高开发人员的工作效率,并且可以减少手动调试时间和成本。 Clang静态分析器的使用方法: 1. 安装Clang编译器:在使用Clang静态分析器之前,需要先安装Clang编译器。可以在https://clang.llvm.org/网站上下载Clang编译器。 2. 安装分析器:Clang分析器与Clang编译器一起安装。安装完成之后,可以在命令行上使用分析器。 3. 运行分析器:使用命令行运行Clang分析器的示例命令: $ clang --analyze [options] input-file。 4. 分析结果:在运行分析器后,它会生成分析结果文件。分析结果文件包含了所有的问题和建议。开发人员可以查看分析结果文件并根据分析结果来修改代码和修复bug。 总之,Clang Static Analyzer是一个非常有用的工具,它可以帮助开发人员提高代码质量,并且减少代码中的潜在缺陷。如果您是C/C++开发人员,那么Clang静态分析器一定会大大提高您的开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值