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

2023-11-11

编译 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

参考:

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)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Clang Static Analyzer 系列(一)编译 Clang 及运行 Checker 的相关文章

随机推荐

  • 基于堆叠⾃编码器的时间序列预测 深层神经网络

    自适应迭代扩展卡尔曼滤波算法 AIEK 是一种滤波算法 其目的是通过迭代过程来逐渐适应不同的状态和环境 从而优化滤波效果 该算法的基本思路是在每一步迭代过程中 根据所观测的数据和状态方程 对滤波器的参数进行自适应调整 以便更好地拟合实际数据
  • python- NameError name ‘name‘ is not defined

    python NameError name name is not defined 练习写python函数的时候 遇到了NameError name name is not defined 这样的错误 百度了一下 发现name是一个系统变量
  • Selenium+Python系列 - 开发环境搭建

    优质资源分享 学习路线指引 点击解锁 知识定位 人群定位 Python实战微信订餐小程序 进阶级 本课程是python flask 微信小程序的完美结合 从项目搭建到腾讯云部署上线 打造一个全栈订餐系统 Python量化交易实战 入门级 手
  • 设计模式:代理模式

    由于某些原因需要给某对象提供一个代理以控制对该对象的访问 这时 访问对象不适合或者不能直接引用目标对象 代理对象作为访问对象和目标对象之间的中介 这就是代理模式 代理模式的主要优点有 1 代理模式在客户端与目标对象之间起到一个中介作用和保护
  • QT学习:制作树形列表菜单

    一 前言 使用QT制作树形的列表菜单 需要使用QTreeWidget和QTreeWidget两个类 最终效果如图所示 二 代码方式实现 使用代码方式实现树形菜单 首先要包含两个类库 include
  • 安全测试目录内容合集

    基础知识 安全测试基础知识 安全测试 django防御安全策略 HTTP工作原理 靶场DVWA 安全测试网站 DWVA下载安装启动 DVWA Command Injection DVWA 5 File upload 文件上传漏洞 DVWA
  • 【记录】安装Django 创建虚拟环境和新项目

    本文仅记录实际操作情况 本文参考书籍 1 2 1 确保电脑安装Python 2 创建虚拟环境 创建一个新目录test blog 再在终端中切换到这个目录 并执行如下命令创建一个虚拟环境 python m venv ll env 书上原文 这
  • 如何恢复内存卡数据?

    生活中 无论我们使用哪种存储设备 内部空间都是有限的 随着使用时间的增加 里面存储的数据会越来越多 这时如果不能及时处理 将很容易出现数据丢失 如果小伙伴们不小心碰到这样的事 要如何恢复内存卡数据呢 遇到了请不要着急 下面小编就分享可以有效
  • python读取表格画散点图_Note: Python_Matplotlib绘制平滑曲线和散点图

    给出横坐标纵坐标点 即可连线绘图 import matplotlib 调用绘图工具包 给出x y点坐标 x y 1 2 3 4 5 6 5 9 3 4 7 5 绘图 matplotlib pyplot plot x y 这样使用工具包如果程
  • python发邮件附件内容中文乱码_python3发邮件,附件名称为中文时出错

    问题描述 我写了一个发邮件的类 一切进行的很顺利 但是附件名改成中文的时候就出问题了 问题出现的环境背景及自己尝试过哪些方法 用的是python3 和email包 是了MIMEText MIMEApplication MIMEBase都不行
  • java scope_spring中的scope详解

    1 singleton 单一实例 此取值时表明容器中创建时只存在一个实例 所有引用此bean都是单一实例 如同每个国家都有一个总统 国家的所有人共用此总统 而这个国家就是一个spring容器 总统就是spring创建的类的bean 国家中的
  • Flask框架种使用ORM模型对MySQL数据库的管理

    通过flask连接MySQL数据库后 使用ORM模型对数据库管理 ORM模型的优点 使用 ORM 做数据库的开发可以有效的减少重复SQL语句的概率 写出来的模型也更加直观 清晰 支持多个关系数据库引擎 包括流行的 MySQL Postgre
  • mysql使用st_distance_sphere函数报错Incorrect arguments to st_distance_sphere

    最近发现执行mysql st distance sphere报错了 报错的信息是Incorrect arguments to st distance sphere 最开始以为是跟mysql的版本有关系 所以看了下自己本地的mysql版本 执
  • 详解shell输出重定向:>/dev/null 2>&1

    1 输入输出重定向介绍 重定向简单来说就是把本来已经默认的 确定的输入输出给重新定位到你想要的地方 重定向这个概念在C语言中就有 在C语言编程中 标准输出是屏幕 使用printf 函数默认是输出到屏幕显示 但是有时候我们需要将信息输出到文件
  • BOM特效:返回顶部按钮

    BOM特效开发 返回顶部按钮制作 BOM特效开发 返回顶部按钮制作 改变document documentElement scrollTop属性 结合定时器逐步改变此值以动画形式返回顶部 在这里插入代码片
  • 基于HAL库的FREERTOS-----------三.队列

    一 队列简介 在实际的应用中 常常会遇到一个任务或者中断服务需要和另外一个任务进行 沟通交流 这个 沟通交流 的过程其实就是消息传递的过程 在没有操作系统的时候两个应用程序进行消息传递一般使用全局变量的方式 但是如果在使用操作系统的应用中用
  • STM32学习笔记---TIM_GetFlagStatus和TIM_GetITStatus两个固件库函数的区别

    TIM GetFlagStatus和TIM GetITStatus两个函数的区别 最近结合正点原子基于STM32F103ZET6芯片开发板的触摸按键实验 在对TIM5 CH2捕获状态进行判断时发现利TIM GetFlagStatus和TIM
  • [C++]适配器模式

    适配器模式 Adapter Pattern 是作为两个不兼容的接口之间的桥梁 这种类型的设计模式属于结构型模式 它结合了两个独立接口的功能 github源码路径 https github com dangwei 90 Design Mode
  • Oracle insert all 详解

    文章目录 1 概述 2 insert 的两种形式 2 1 insert first 2 2 insert all 3 数据一致性 同时插入 3 1 验证 insert into 数据不一致 3 2 验证 insert all 数据一致 1
  • Clang Static Analyzer 系列(一)编译 Clang 及运行 Checker

    编译 Clang CSA Clang Static Analyzer 是 clang 的一部分 建议使用自行编译的 clang 源码在 llvm llvm project github com 上获取 编译 clang 前首先要生成 cla