内核工具 – Sparse 简介

sparse介绍

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

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

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

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

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

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

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

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

#define __bitwise    __attribute__((bitwise))     
确保变量是相同的位方式(比如 bit-endian, little-endiandeng)    
#define __user    __attribute__((noderef, address_space(1)))     
指针地址必须在用户地址空间    
#define __kernel    __attribute__((noderef, address_space(0)))     
指针地址必须在内核地址空间    
#define __iomem    __attribute__((noderef, address_space(2)))     
指针地址必须在设备地址空间    
#define __safe    __attribute__((safe))     
变量可以为空    
#define __force    __attribute__((force))     
变量可以进行强制转换    
#define __nocast    __attribute__((nocast))     
参数类型与实际参数类型必须一致    
#define __acquires(x)    __attribute__((context(x, 0, 1)))     
参数x 在执行前引用计数必须是0,执行后,引用计数必须为1    
#define __releases(x)    __attribute__((context(x, 1, 0)))     
与 __acquires(x) 相反    
#define __acquire(x)    __context__(x, 1)     
参数x 的引用计数 + 1    
#define __release(x)    __context__(x, -1)     
与 __acquire(x) 相反    
#define __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

Sparse 使用方法

__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;

__user 的使用

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

内核代码中的例子:

/*
 内核版本:v2.6.32.61  file:arch/score/kernel/signal.c 45行 
*/

static
 
int setup_sigcontext(structpt_regs *regs, struct sigcontext __user *sc)

__kernel 的使用

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

内核代码中的例子:

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

__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)

__safe 的使用

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

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

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

__force 的使用

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

内核代码中的例子:

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

__nocast 的使用

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

内核代码中的例子:

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

__acquires __releases __acquire __release的使用

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

__cond_lock 的使用

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

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

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

Sparse 在编译内核中的使用

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

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

补充

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 简介

时间: 2024-10-03 06:52:29

内核工具 – Sparse 简介的相关文章

内核工具 – Sparse 简介【转】

转自:http://www.cnblogs.com/wang_yb/p/3575039.html Sparse是内核代码静态分析工具, 能够帮助我们找出代码中的隐患. 主要内容: Sparse 介绍 Sparse 使用方法 Sparse 在编译内核中的使用 补充 1. Sparse 介绍 Sparse 诞生于 2004 年, 是由linux之父开发的, 目的就是提供一个静态检查代码的工具, 从而减少linux内核的隐患. 其实在Sparse之前, 已经有了一个不错的代码静态检查工具("SWAT&

部分GDAL工具功能简介

主要转自http://blog.csdn.net/liminlu0314?viewmode=contents 部分GDAL工具功能简介 gdalinfo.exe 显示GDAL支持的各种栅格文件的信息. gdal_translate.exe 在不同的格式间进行转换.同时,潜在的执行了一些切割.重采样和使像素比例变化的任务. gdalwarp.exe 投影转换和投影绑定.同时也可以进行图像镶嵌.这个程序可以重新投影所支持的投影,而且如果图像("raw" with)控制信息也可以把GCPs

Linux 内核引导参数简介

概述 内核引导参数大体上可以分为两类:一类与设备无关.另一类与设备有关.与设备有关的引导参数多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导参数.比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导参数,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导参数说明.大多数参数是通过"__setup(... , ...)"函数设置的,少部分是通过"early_param(..

正则表达式与grep、sed工具使用简介

正则表达式与grep.sed工具使用简介 一.正则表达式     正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑. 其介绍如下:      \ 将下一个字符标记符.或一个向后引用.或一个八进制转义符 ^ 匹配输入字符串的开始位置 $ 匹配输入字符串的结束位置 * 匹配前面的子表达式任意次 + 匹配前面的子表达式一次或多次(大于等于1次) ? 匹配前

Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装

原文:Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装 Linux内核分析(一) 从本篇博文开始我将对linux内核进行学习和分析,整个过程必将十分艰辛,但我会坚持到底,同时在博文中如果那些地方有问题还请各位大神为我讲解. 今天我们会分析到以下内容: 1.      Linux体系结构简介 2.      Linux内核源码简介 3.      Linux内核配置.编译.安装 l  Linux体系结构简介 1.       Linux体系结构(linux系统构成)

python 自动化部署工具Fabric简介

自动化部署工具Fabric简介 Fabric就是一个帮助我们在上线时减少重复/繁琐操作的自动化部署利器,对于缺乏成熟运维平台的众多小公司的运维或开发人员来说,掌握这个工具是有必要的. 1. Fabric是什么 Fabric官方文档的描述如下:      Fabric is a Python (2.5-2.7) library and command-line tool for streamlining the use of SSH for application deployment or sy

七款代码味道识别工具【简介】

代码味道识别工具 (Code Smell Detection Tools, CSDT)既可以应用于软件开发阶段,也可以应用于软件维护阶段.目前大部分IDE都集成了自动或者半自动重构工具,但是根据国外研究人员的调查发现,真正在软件开发和维护中使用重构工具的人并不多,其中有一个很重要的原因是不知道何时该重构,也就是说找不准重构时机,因此重构时机的自动识别具有很大的实用价值.很多代码味道本身就是重构时机的指示器,如果能够自动发现这些代码味道,就说明代码中存在一些不恰当的设计方案或者程序代码,在此时再实

几款具有代表性的自动化测试工具汇总简介

几款具有代表性的自动化测试工具汇总简介一.传统自动化测试工具/商业工具(传统工具较多仅介绍两款,基本都是国外的) 1.QTP,全名HP QuickTest Professional software ,最新的版本为HP QuickTest Professional 11.0QTP是quicktest Professional的简称,是一种自动测试工具.使用QTP的目的是想用它来执行重复的手动测试,主要是用于回归测试和测试同一软件的新版本.因此你在测试前要考虑好如何对应用程序进行测试,例如要测试那

内核探测工具systemtap简介【转】

转自:http://www.cnblogs.com/hazir/p/systemtap_introduction.html systemtap是内核开发者必须要掌握的一个工具,本文我将简单介绍一下此工具,后续将会有系列文章介绍systemtap的用法. 什么是systemtap 假如现在有这么一个需求:需要获取正在运行的 Linux 系统的信息,如我想知道系统什么时候发生系统调用,发生的是什么系统调用等这些信息,有什么解决方案呢? 最原始的方法是,找到内核系统调用的代码,加上我们需要获得信息的代