手写静态分析器Checker

  • 1.简介
  • 2.编写Checker
  • 3.配置CMakeLists
  • 4.配置Checkers.td
  • 5.编译构建
  • 6.测试

1.简介

目前网上找到的一些构建Checker的方法都比较古老,随着版本更新一些库文件和依赖文件的变动老方法不太适用,所以整理了一下在10.0版本下构建Checker的方法,10.0之前没没有使用过,后面的版本应该大差不差了。

2.编写Checker

编写自定义的Checker需要在以下目录进行:

llvm/tools/clang/lib/StaticAnalyzer/Checkers

此目录存放的是当前静态分析其所有的Checker文件。
新建MyPathChecker.cpp文件并编写如下代码(实现了对扩展图的DFS,代码是师弟编写的)

#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/Analysis/Analyses/Dominators.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/CallGraph.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "llvm/Support/Process.h"
#include <vector>using namespace clang;
using namespace ento;namespace {class EGraphHelper {private:std::vector<ExplodedNode*> path;std::vector<std::vector<ExplodedNode*>> paths;public:void dfsTrave(ExplodedGraph &G) {llvm::outs() << "start dfs\n";path.clear();paths.clear();// 遍历所有根节点for (auto it = G.roots_begin(); it < G.roots_end(); it++) {// 指向ExplodedNode*指针path.push_back(*it);dfs(*it);path.pop_back();}pathTrim(paths);}void dfs(ExplodedNode* node) {// ProgramStateRef state = node->getState();// int id = state->getID();// llvm::outs() << id << "\n";// llvm::outs() << "ptr_addr: " << node << "\n";// 搜索到路径终止处if (node->getFirstSucc() == nullptr) {// 存储当前路径信息paths.push_back(path);return;}for (auto it = node->succ_begin(); it < node->succ_end(); it++) {path.push_back(*it);dfs(*it);path.pop_back();}}void pathTrim(std::vector<std::vector<ExplodedNode*>> &paths) {int pathNum = 0;for (auto path : paths) {llvm::outs() << "path-" << ++pathNum << "\n";for (auto node : path) {// ProgramStateRef state = node->getState();// int id = state->getID();// llvm::outs() << id << " ";ProgramPoint point = node->getLocation();llvm::Optional<BlockEntrance> be = point.getAs<BlockEntrance>();if (be != None) {// 收集basic block路径信息auto blockId = be->getBlock()->getBlockID();llvm::outs() << blockId << " ";}}llvm::outs() << "\n";}}
}; // end class EGraphHelperclass MyPathChecker : public Checker< check::EndAnalysis > {public:MyPathChecker() {}void checkEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng) const;
};// end class MyPathChecker
}// end namespace// 调用的回调函数
void MyPathChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng) const {llvm::outs() << "get path check\n";EGraphHelper helper;helper.dfsTrave(G);
}void ento::registerMyPathChecker(CheckerManager &mgr) {mgr.registerChecker<MyPathChecker>();
}bool ento::shouldRegisterMyPathChecker(const LangOptions &LO) {return true;
}

其中 EGraphHelper 是一个自定义工具类,主要是MyPathChecker 这个类,继承Checker类并在registerMyPathChecker中注册,shouldRegisterMyPathChecker这个个人理解是判断是否能注册此Checker,此函数存在一个问题:

bool ento::shouldRegisterMyPathChecker(const LangOptions &LO) {return true;
}

函数参数在15.0版本编译的时候应该指定如下格式:

bool ento::shouldRegisterMyPathChecker(const CheckerManager &mgr) {return true;
}

我在10.0版本编译的时候用第二种格式会报以下错误,具体原因不太清楚,可能是版本的问题,对照了源码中的方法使用第一种格式可以编译成功:

3.配置CMakeLists

如下路径配置CMakeLists,添加刚才编写的cpp文件即可

llvm/tools/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt

4.配置Checkers.td

这个是非常重要的一步,这个配置是将自定义的Checker整合到静态分析器中。
如下路径配置Checkers.td,注意:网上很多资料此路径是在lib下,应该是版本比较老的代码结构了,目前此文件在include路径下。

llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td

此文件结构如下,ParentPackage 标识当前Checker属于哪一个包(debug、core等),我们把刚才编写的checker放在了Debug中,如下。

//===----------------------------------------------------------------------===//
// Debugging checkers (for analyzer development).
//===----------------------------------------------------------------------===//let ParentPackage = Debug in {def ***def ******// 在源文件的Debug中添加如下代码即可def MyPathChecker : Checker<"MyPathChecker">,HelpText<"Check for get path">,Documentation<NotDocumented>;
}

5.编译构建

上述所有步骤准备完成之后可以构建程序了,进入最外层的build目录make然后make install就完事啦!这里就不放图片啦。

6.测试

命令如下,debug.MyPathChecker就是我们刚才编写的checker,两个-I指定了动态链接库,根据本机做调整即可,最后test.c是测试的源代码:

clang -cc1 -I /usr/include -I /home/zzh/llvm/lib/clang/10.0.0/include -analyze -analyzer-checker=debug.MyPathChecker test.c

生成了扩展图中的路径信息,如下:

Clang 10.0 手写静态分析器Checker相关推荐

  1. Opencv3.0 手写数字识别(Hog特征+SVM分类器)

    配置:VS2013+Opencv3.0 参考: http://blog.csdn.net/iamzhangzhuping/article/details/51254567 http://blog.cs ...

  2. pc手写识别_如何在Windows 10 PC上改善手写识别

    pc手写识别 Windows 10 lets you use handwriting input in any application, and many applications include f ...

  3. 使用Pytorch实现手写数字识别

    使用Pytorch实现手写数字识别 1. 思路和流程分析 流程: 准备数据,这些需要准备DataLoader 构建模型,这里可以使用torch构造一个深层的神经网络 模型的训练 模型的保存,保存模型, ...

  4. 使用caffemodel模型(由mnist训练)测试单张手写数字样本

    caffe中训练和测试mnist数据集都是批处理,可以反馈识别率,但是看不到单张样本的识别效果,这里使用windows自带的画图工具手写制作0~9的测试数字,然后使用caffemodel模型识别. 1 ...

  5. 深度学习笔记--pytorch从梯度下降到反向传播BP到线性回归实现,以及API调用和手写数据集的实现

    梯度下降和反向传播 目标 知道什么是梯度下降 知道什么是反向传播 1. 梯度是什么? 梯度:是一个向量,导数+变化最快的方向(学习的前进方向) 回顾机器学习 收集数据 x x x ,构建机器学习模型 ...

  6. 深度学习-Pytorch:项目标准流程【构建、保存、加载神经网络模型;数据集构建器Dataset、数据加载器DataLoader(线性回归案例、手写数字识别案例)】

    1.拿到文本,分词,清晰数据(去掉停用词语): 2.建立word2index.index2word表 3.准备好预训练好的word embedding 4.做好DataSet / Dataloader ...

  7. Pytorch CNN 手写数字识别 0-9

    使用的软件是pycharm 环境是在anaconda下创的虚拟环境pytorch 整个过程大体为,在画板手写数字,用python代码实现手写数字的批量生成,定义超参数,创建数据集包括训练集和数据集,创 ...

  8. 深度学习 第三章 tensorflow手写数字识别

    深度学习入门视频-唐宇迪 (笔记加自我整理) 深度学习 第三章 tensorflow手写数字识别 1.tensorflow常见操作 这里使用的是tensorflow1.x版本,tensorflow基本 ...

  9. pytorch 预测手写体数字_教你用PyTorch从零开始实现LeNet 5手写数字的识别

    背景 LeNET-5是最早的卷积神经网络之一,曾广泛用于美国银行.手写数字识别正确率在99%以上. PyTorch是Facebook 人工智能研究院在2017年1月,基于Torch退出的一个Pytho ...

  10. 【Machine Learning】19.多分类实践:手写数字分类

    多分类实践:手写数字分类 1.导入包 2.回顾:softmax函数 3.神经网络 3.1 问题描述 3.2 数据集 3.2.1 查看变量 3.2.2 查看维度 3.2.3 数据可视化 3.3 模型表示 ...

最新文章

  1. 程序员发长贴讲述真实某多多:薪水高,普调高,环境差,厕所少!强制去买菜,全行业竞业,穿拖鞋会被暴力执法!...
  2. linux apt qt下载,Linux如何安装 apt-get 软件管理工具
  3. 23种设计模式C++源码与UML实现--装饰者模式
  4. webpack 入口文件 php,webpack的使用详解
  5. g4e基础篇#6 了解Git历史记录
  6. pytorch构造IterableDataset,流式读取文件夹,文件夹下所有大数据文件,逐个文件!逐行读取!(pytorch Data学习四)
  7. C#中使用反射遍历一个对象属性和值以及百分数
  8. PC机中各类存储器的逻辑连接情况
  9. SVM 超平面方程
  10. 程序员常识--OJ系统及ACM测试题库大全
  11. C语言——恶搞之关机代码
  12. cydia未能联到服务器,cydia无法加载,小编教你cydia无法加载怎么解决
  13. Teststand自定义测试报告
  14. tp5模型belongsTo和hasOne以及hasMany的区别与用法
  15. 研发大局观(15.8.25 )
  16. 微信小程序实现时间预约功能
  17. php continue什么意思,php switch continue 什么意思??
  18. authorizationPolicy详解
  19. 干货丨加密数据迁移二三事
  20. 认真开始学习C语言的2天总结(师承上官可编程----老陈)

热门文章

  1. 多浏览器支持ActiveX控件
  2. jpg格式如何转eps路径_jpg/png格式图片转eps格式的方法总结
  3. Android 集成百度人脸采集,实现简单人脸采集module
  4. 域用户更改环境变更与关闭UAC
  5. Excel常用技巧——工作中最常用的30个Excel函数公式
  6. 深度WindowsXp错误的打了SP3补丁之后,无法进入系统
  7. React antd的table表格之嵌套表格
  8. HTML5与flash播放器
  9. Docker 学习笔记
  10. 交换机入门书籍推荐_网络工程学习方法/路线/专业书籍推荐