|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 mytomorrow 于 2019-9-17 20:21 编辑 ! q/ M& C" {5 u/ R! }
5 \) q4 d% n' s! t9 K# ISparse是内核代码静态分析工具, 能够帮助我们找出代码中的隐患. l% B: q2 l3 ?8 S/ P7 Y. v5 R7 M
7 Y' v" F6 D% O) |. g) @8 f/ I主要内容:' E5 u$ ?8 ~' y! h7 C7 T
' T3 N0 ~5 g6 z, C, u1 n2 ?) D
- Sparse 介绍
- Sparse 使用方法
- Sparse 在编译内核中的使用
- 补充/ c& N3 T+ k: q" \& Y$ Q- q3 S2 `
9 R* [, m' D6 i: A4 H F. l
1. Sparse 介绍& t$ M8 V( `; }: ^: ]9 F
" U; R! r( S: R3 L/ nSparse 诞生于 2004 年, 是由linux之父开发的, 目的就是提供一个静态检查代码的工具, 从而减少linux内核的隐患.$ D) e* u0 o6 |" j1 `, d
8 g* v4 G6 V( z) U$ x4 T! b
其实在Sparse之前, 已经有了一个不错的代码静态检查工具("SWAT"), 只不过这个工具不是免费软件, 使用上有一些限制.1 o. S2 h/ D3 H9 {$ z: _
" h7 J* D6 G9 o: T2 N0 h
所以 linus 还是自己开发了一个静态检查工具.! i6 H" l9 O3 {0 D% B& z9 J9 ]
( r0 U+ o1 I$ [
具体可以参考这篇文章(2004年的文章了): Finding kernel problems automatically
3 Z0 u+ ]2 C4 O8 t& c! U- G/ ~. K
! n k/ R6 s+ o) A# A: y# \# K. G& A, A( d8 w! a
Sparse相关的资料非常少, 关于它的使用方法我也是网上查找+自己实验得出来的.
P+ n* x! X% o* {8 o m3 \. _1 s/ X% _0 ~1 }
内核代码中还有一个简略的关于 Sparse的说明文件: Documentation/sparse.txt
# P# a$ Y- m$ M6 } B* F
+ @* t X2 l9 r8 N: Q/ P2 R5 o5 T: n1 q
Sparse通过 gcc 的扩展属性 __attribute__ 以及自己定义的 __context__ 来对代码进行静态检查.5 b8 e. Q4 z8 [5 _) G
9 ^% ]! B) {% S* y- r; S
这些属性如下(尽量整理的,可能还有些不全的地方): c, w+ L9 o1 I) u
/ D5 c3 o% v* n- V
宏名称 | 宏定义 | 检查点 | | __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 |
3 K- D* _7 D4 j+ _. n. k
& |6 M- B4 M& Z6 m2 L其中 __acquires(x) 和 __releases(x), __acquire(x) 和 __release(x) 必须配对使用, 否则 Sparse 会给出警告, Z3 l# G" g! I; x; v$ i* Q
. x' s1 ?' b- h, ~5 }
注: 在Fedora系统中通过 rpm 安装的 sparse 存在一个小bug.$ [4 Q! P2 w: b5 W7 G5 t2 X
: _, D+ }. y2 F
' I( q2 H: x) v' i! x9 b
3 {. @/ f6 L/ ^ |
|