Sparse是内核代码静态分析工具, 能够帮助我们找出代码中的隐患.

主要内容:

  • Sparse 介绍
  • Sparse 使用方法
  • Sparse 在编译内核中的使用
  • 补充

1. Sparse 介绍

Sparse 诞生于 2004 年, 是由linux之父开发的, 目的就是提供一个静态检查代码的工具, 从而减少linux内核的隐患.

其实在Sparse之前, 已经有了一个不错的代码静态检查工具("SWAT"), 只不过这个工具不是免费软件, 使用上有一些限制.

所以 linus 还是自己开发了一个静态检查工具.

具体可以参考这篇文章(2004年的文章了): Finding kernel problems automatically

Sparse相关的资料非常少, 关于它的使用方法我也是网上查找+自己实验得出来的.

内核代码中还有一个简略的关于 Sparse的说明文件: Documentation/sparse.txt

Sparse通过 gcc 的扩展属性 __attribute__ 以及自己定义的 __context__ 来对代码进行静态检查.

这些属性如下(尽量整理的,可能还有些不全的地方):

宏名称

宏定义

检查点

__bitwise __attribute__((bitwise)) 确保变量是相同的位方式(比如 bit-endian, little-endiandeng)
__user __attribute__((noderef, address_space(1))) 指针地址必须在用户地址空间
__kernel __attribute__((noderef, address_space(0))) 指针地址必须在内核地址空间
__iomem __attribute__((noderef, address_space(2))) 指针地址必须在设备地址空间
__safe __attribute__((safe)) 变量可以为空
__force __attribute__((force)) 变量可以进行强制转换
__nocast __attribute__((nocast)) 参数类型与实际参数类型必须一致
__acquires(x) __attribute__((context(x, 0, 1))) 参数x 在执行前引用计数必须是0,执行后,引用计数必须为1
__releases(x) __attribute__((context(x, 1, 0))) 与 __acquires(x) 相反
__acquire(x) __context__(x, 1) 参数x 的引用计数 + 1
__release(x) __context__(x, -1) 与 __acquire(x) 相反
__cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) 参数c 不为0时,引用计数 + 1, 并返回1

其中 __acquires(x) 和 __releases(x), __acquire(x) 和 __release(x) 必须配对使用, 否则 Sparse 会给出警告

: 在Fedora系统中通过 rpm 安装的 sparse 存在一个小bug.

即使用时会报出 error: unable to open ’stddef.h’ 的错误, 最好从自己源码编译安装 sparse.

参考: http://wangcong.org/blog/archives/504

2. Sparse 使用方法

2.1 __bitwise 的使用

主要作用就是确保内核使用的整数是在同样的位方式下.

在内核代码根目录下 grep -r '__bitwise', 会发现内核代码中很多地方都使用了这个宏.

对于使用了这个宏的变量, Sparse 会检查这个变量是否一直在同一种位方式(big-endian, little-endian或其他)下被使用,

如果此变量在多个位方式下被使用了, Sparse 会给出警告.

内核代码中的例子:

/* 内核版本:v2.6.32.61  file:include/sound/core.h 51行 */
typedef int __bitwise snd_device_type_t;

2.2 __user 的使用

如果使用了 __user 宏的指针不在用户地址空间初始化, 或者指向内核地址空间, 设备地址空间等等, Sparse会给出警告.

内核代码中的例子:

/* 内核版本:v2.6.32.61  file:arch/score/kernel/signal.c 45行 */
static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)

2.3 __kernel 的使用

如果使用了 __kernel 宏的指针不在内核地址空间初始化, 或者指向用户地址空间, 设备地址空间等等, Sparse会给出警告.

内核代码中的例子:

/* 内核版本:v2.6.32.61  file:arch/s390/lib/uaccess_pt.c 180行 */
memcpy(to, (void __kernel __force *) from, n);

2.4 __iomem 的使用

如果使用了 __iomem 宏的指针不在设备地址空间初始化, 或者指向用户地址空间, 内核地址空间等等, Sparse会给出警告.

内核代码中的例子:

/* 内核版本:v2.6.32.61  file:arch/microblaze/include/asm/io.h 22行 */
static inline unsigned char __raw_readb(const volatile void __iomem *addr)

2.5 __safe 的使用

使用了 __safe修饰的变量在使用前没有判断它是否为空(null), Sparse会给出警告.

我参考的内核版本(v2.6.32.61) 中的所有内核代码都没有使用 __safe, 估计可能是由于随着gcc版本的更新,

gcc已经会对这种情况给出警告, 所以没有必要用Sparse去检查了.

2.6 __force 的使用

使用了__force修饰的变量可以进行强制类型转换, 没有使用 __force修饰的变量进行强制类型转换时, Sparse会给出警告.

内核代码中的例子:

/* 内核版本:v2.6.32.61  file:arch/s390/lib/uaccess_pt.c 180行 */
memcpy(to, (void __kernel __force *) from, n);

2.7 __nocast 的使用

使用了__nocast修饰的参数的类型必须和实际传入的参数类型一致才行,否则Sparse会给出警告.

内核代码中的例子:

/* 内核版本:v2.6.32.61  file:fs/xfs/support/ktrace.c 55行 */
ktrace_alloc(int nentries, unsigned int __nocast sleep)

2.8 __acquires __releases __acquire __release的使用

这4个宏都是和锁有关的, __acquires 和 __releases 必须成对使用, __acquire 和 __release 必须成对使用, 否则Sparse会给出警告.

2.9 __cond_lock 的使用

这个宏有点特别, 因为没有 __cond_unlock 之类的宏和它对应.

之所以有这个宏的原因可以参见: http://yarchive.net/comp/linux/sparse.html 最后一段.

这个宏的来源清楚了, 但是为什么这个宏里面还要调用一次 __acquire(x)? 我也不是很清楚, 在网上找了好久也没找到, 谁能指教的话非常感谢!!!

3. Sparse 在编译内核中的使用

用 Sparse 对内核进行静态分析非常简单.

# 检查所有内核代码
make C=1 检查所有重新编译的代码
make C=2 检查所有代码, 不管是不是被重新编译

4. 补充

Sparse除了能够用在内核代码的静态分析上, 其实也可以用在一般的C语言程序中.

比如下面的小例子:

/******************************************************************************* @file    : sparse_test.c* @author  : wangyubin* @date    : Fri Feb 28 16:33:34 2014* * @brief   : 测试 sparse 的各个检查点* history  : init******************************************************************************/#include <stdio.h>#define __acquire(x) __context__(x,1)
#define __release(x) __context__(x,-1)int main(int argc, char *argv[])
{int lock = 1;__acquire(lock);/* TODO something */__release(lock);            /* 注释掉这一句 sparse 就会报错 */return 0;
}

如果安装了 Sparse, 执行静态检查的命令如下:

$ sparse -a sparse_test.c
sparse_test.c:15:5: warning: context imbalance in 'main' - wrong count at exit

Sparse相关资料可以参考wiki: Sparse wiki

内核工具 – Sparse 简介相关推荐

  1. 部分GDAL工具功能简介

    部分GDAL工具功能简介 gdalinfo.exe 显示GDAL支持的各种栅格文件的信息. gdal_translate.exe 在不同的格式间进行转换.同时,潜在的执行了一些切割.重采样和使像素比例 ...

  2. Linux平台代码覆盖率测试工具GCOV的前端工具LCOV简介

    本博客 http://blog.csdn.net/livelylittlefish 贴出作者(三二一@小鱼)相关研究.学习内容所做的笔记,欢迎广大朋友指正! Content 1. Lcov是什么? 2 ...

  3. GNU工具链简介(全)

    Mips GNU工具链简介  1 . 总括 本文分三部分来介绍mips的工具链,首先工具链的总括,其次是每个工具链的简介,最后是各工具链的实际应用举例.我们的项目使用的工具链就如图1所示,声明,本文所 ...

  4. (转)Apache Commons工具集简介

    (转)Apache Commons工具集简介 Apache Commons包含了很多开源的工具,用于解决平时编程经常会遇到的问题,减少重复劳动.我选了一些比较常用的项目做简单介绍.文中用了很多网上现成 ...

  5. Tool之ADB:ADB工具的简介、安装、使用方法之详细攻略

    Tool之ADB:ADB工具的简介.安装.使用方法之详细攻略 目录 ADB工具的简介 ADB工具的安装 ADB工具的使用方法 1.基础用法

  6. Ubuntu之make:make命令行工具的简介、安装、使用方法之详细攻略

    Ubuntu之make:make命令行工具的简介.安装.使用方法之详细攻略 目录 make命令行工具的简介 make命令行工具的安装 make命令行工具的使用方法 make命令行工具的简介 Ubunt ...

  7. NPM:nodejs官方包管理工具的简介、安装、使用方法之详细攻略

    NPM:nodejs官方包管理工具的简介.安装.使用方法之详细攻略 目录 NPM之nodejs官方包管理工具的简介 NPM之nodejs官方包管理工具的安装 NPM之nodejs官方包管理工具的使用方 ...

  8. CV之LabelImg:图片标注工具之LabelImg(图像标注工具)的简介、安装、使用方法详细攻略

    CV之LabelImg:图片标注工具之LabelImg(图像标注工具)的简介.安装.使用方法详细攻略 目录 LabelImg的简介 常见的图片标注工具 LabelImg trainingImageLa ...

  9. java的网络工具netty简介

    2019独角兽企业重金招聘Python工程师标准>>> java的网络工具netty简介 Netty是一个NIO的客服端服务器框架,它可以简单.快速的搭建器一个协议包客服端服务器的应 ...

最新文章

  1. 取消Eclipse等号、分号、空格代码自动补全
  2. 2021高校毕业生薪酬Top100出炉!清华指数TOP,薪酬却排名第二
  3. boost::hana::replicate用法的测试程序
  4. uploadify 配置后,页面显示无效果
  5. Android控制EditText的焦点
  6. 在Linux系统中,使用useradd命令新建用户后,登录该用户时shell开头为$,不显示用户名和路径,如下:...
  7. 在xml中自定义属性 app
  8. MFC画图(画线、画矩形、画刷画笔的使用)
  9. 获取oracle日志文件,ORACLE关于日志文件基本操作
  10. python小学生入门教程-python 小学生教程|怎么让一个小学生学会Python?
  11. php云erp进销存v8手机端,PHP仿金蝶云ERP进销存V8网络多仓版源码
  12. Arora is a lightweight cross-platform web browser.
  13. #IP实验室,第二周复盘
  14. 基于vue+百度地图的多车实时运动及轨迹追踪实现(上帝视角篇)
  15. Virtual Private Network(虚拟专用网络)详解
  16. 湖南科技大学EDA作业
  17. 不同内核浏览器的差异以及浏览器渲染简介(转)
  18. 在Nginx中正确返回HTTPS/SSL错误
  19. selenium自动化测试--126邮箱登录问题总结
  20. Python 处理一对多考勤表

热门文章

  1. BLE蓝牙特定机型权限问题(例如小米)
  2. MIS外汇平台荣获“2013年全球最佳STP外汇交易商”
  3. python如何格式化输出百分号
  4. Tensorflow基于pb模型进行预训练(pb模型转CKPT模型)
  5. UE4官方收费资源,售价总和大几千
  6. i5 1135g7和i7 1165g7核显一样吗 i51135g7和i71165g7的相差大吗
  7. 防火墙双机设备(旁挂组网),HRP双主原因
  8. 如何使用 rmdir 命令删除目录?
  9. 转载 鼠绘夸张动漫人物
  10. bitnami redmine mysql_Bitnami Redmine 安装笔记