0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux内核代码的静态检查

冬至子 来源:linux与soc 作者:linux与soc 2023-06-05 14:50 次阅读

1.Sparse介绍

Linus在2004年开发了kernel代码静态检查工具,可以检查出kernel中潜在的风险代码,Sparse通过 gcc 的扩展属性__attribute__ 以及自己定义的 __context__来对代码进行静态检查,重点检查kernel代码中的变量类型和各类锁。

那么如何指定代码可以被Sparse检查的到呢?以__iomem为例,可以对需要检查的变量类型放到特定文件中,以__CHECKER__进行限定即可。

#ifdef __CHECKER__
# define __user  __attribute__((noderef, address_space(1)))
# define __kernel __attribute__((address_space(0)))
# define __safe  __attribute__((safe))
# define __force __attribute__((force))
# define __nocast __attribute__((nocast))
# define __iomem __attribute__((noderef, address_space(2)))
# define __must_hold(x) __attribute__((context(x,1,1)))
# define __acquires(x) __attribute__((context(x,0,1)))
# define __releases(x) __attribute__((context(x,1,0)))
# define __acquire(x) __context__(x,1)
# define __release(x) __context__(x,-1)
# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
# define __percpu __attribute__((noderef, address_space(3)))
# define __rcu  __attribute__((noderef, address_space(4)))
# define __private __attribute__((noderef))
extern void __chk_user_ptr(const volatile void __user *);
extern void __chk_io_ptr(const volatile void __iomem *);
# define ACCESS_PRIVATE(p, member) (*((typeof((p)- >member) __force *) &(p)- >member))
#else /* __CHECKER__ */
# ifdef STRUCTLEAK_PLUGIN
#  define __user __attribute__((user))
# else
#  define __user
# endif
# define __kernel
# define __safe
# define __force
# define __nocast
# define __iomem
# define __chk_user_ptr(x) (void)0
# define __chk_io_ptr(x) (void)0
# define __builtin_warning(x, y...) (1)
# define __must_hold(x)
# define __acquires(x)
# define __releases(x)
# define __acquire(x) (void)0
# define __release(x) (void)0
# define __cond_lock(x,c) (c)
# define __percpu
# define __rcu
# define __private
# define ACCESS_PRIVATE(p, member) ((p)- >member)
#endif /* __CHECKER__ */

2. 安装Sparse工具

通常来说,开发环境中没有Sparse工具,需要手动安装,否则报如下错误:

ubuntu16@ubuntu16:linux$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j4 C=2
  CHECK   scripts/mod/empty.c
/bin/sh: 1: sparse: not found
scripts/Makefile.build:261: recipe for target 'scripts/mod/empty.o' failed
  1. 获取Sparse代码
ubuntu16@ubuntu16:~$ git clone git://git.kernel.org/pub/scm/devel/sparse/sparse.git
Cloning into 'sparse'...
remote: Enumerating objects: 17, done.
remote: Counting objects: 100% (17/17), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 20026 (delta 6), reused 0 (delta 0), pack-reused 20009
Receiving objects: 100% (20026/20026), 4.29 MiB | 924.00 KiB/s, done.
Resolving deltas: 100% (14035/14035), done.
Checking connectivity... done.
  1. 编译Sparse
ubuntu16@ubuntu16:~$ cd sparse/
ubuntu16@ubuntu16:sparse$ make
Makefile:152: Your system does not have libxml, disabling c2xml
Makefile:170: Your system does not have sqlite3, disabling semind
Makefile:192: Your system does not have gtk3/gtk2, disabling test-inspect
Makefile:226: Your system does not have llvm, disabling sparse-llvm
  1. 安装Sparse
ubuntu16@ubuntu16:sparse$ make install
Makefile:152: Your system does not have libxml, disabling c2xml
Makefile:170: Your system does not have sqlite3, disabling semind
Makefile:192: Your system does not have gtk3/gtk2, disabling test-inspect
Makefile:226: Your system does not have llvm, disabling sparse-llvm
INSTALL /home/ubuntu16/bin/sparse
INSTALL /home/ubuntu16/bin/cgcc
INSTALL /home/ubuntu16/share/man/man1/sparse.1
INSTALL /home/ubuntu16/share/man/man1/cgcc.1
ubuntu16@ubuntu16:sparse$

3.执行Sparse静态检查

从kernel顶层Makefile中可以看出,当编译kernel时通过指定C=1C=2,可以调用到Sparse进行代码静态检查。

192 # Call a source code checker (by default, "sparse") as part of the
193 # C compilation.
194 #
195 # Use 'make C=1' to enable checking of only re-compiled files.
196 # Use 'make C=2' to enable checking of *all* source files, regardless
197 # of whether they are re-compiled or not.
198 #
199 # See the file "Documentation/dev-tools/sparse.rst" for more details,
200 # including where to get the "sparse" utility.

执行结果:

ubuntu16@ubuntu16:linux$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j4 C=2
  CHECK   scripts/mod/empty.c
  CALL    scripts/atomic/check-atomics.sh
  CALL    scripts/checksyscalls.sh
  CHECK   arch/arm/vfp/vfpmodule.c
  CHECK   init/main.c
arch/arm/vfp/vfpmodule.c:38:17: warning: symbol 'vfp_vector' was not declared. Should it be static?
arch/arm/vfp/vfpmodule.c:56:17: warning: symbol 'vfp_current_hw_state' was not declared. Should it be static?
arch/arm/vfp/vfpmodule.c:323:6: warning: symbol 'VFP_bounce' was not declared. Should it be static?
arch/arm/vfp/vfpmodule.c:714:6: warning: symbol 'kernel_neon_begin' was not declared. Should it be static?
arch/arm/vfp/vfpmodule.c:745:6: warning: symbol 'kernel_neon_end' was not declared. Should it be static?
...
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • ARM
    ARM
    +关注

    关注

    134

    文章

    8653

    浏览量

    361832
  • LINUX内核
    +关注

    关注

    1

    文章

    311

    浏览量

    21389
  • gcc编译器
    +关注

    关注

    0

    文章

    78

    浏览量

    3233
收藏 人收藏

    评论

    相关推荐

    linux内核代码

    linux内核代码
    发表于 08-20 22:52

    如何向Linux内核提交驱动

    /CodingStyle文档,或者我之前的博文《谈谈Linux内核驱动的coding style》。我们在提交驱动之前还需要用静态代码检查
    发表于 09-08 16:53

    Linux内核代码

    Linux内核代码本章讲述在L i n u x内核源码中,应该从何处开始查找特定的内核函数。本书并不要求读者具有C语言编程能力,也不要求读
    发表于 02-09 15:24 36次下载

    Linux内核代码漫游

    Linux内核代码漫游 本章试图以顺序的方式来解释Linux代码,以帮助读者对源代码的体系
    发表于 02-09 15:27 26次下载

    Linux 内核代码

    Linux 内核代码 实模式setup阶段setup用于体系结构相关的硬件初始化工作,在arch目录中的各个系统结构的平台相关都有类似功能的代码。在32位的x86平台中,s
    发表于 02-10 13:45 28次下载

    嵌入式LINUX内核网络栈(源代码)

    本文选择 LINUX-1.2.13 内核所包含的网络部分代码分析(注意网络部分代码内核代码的演
    发表于 05-12 10:39 57次下载
    嵌入式<b class='flag-5'>LINUX</b><b class='flag-5'>内核</b>网络栈(源<b class='flag-5'>代码</b>)

    Linux内核代码情景分析(全册高清带书签)

    Linux内核代码情景分析(全册高清带书签)
    发表于 01-14 15:20 50次下载

    Linux内核代码感悟

    直接访问校内外的 lxr 网站)的。如果在 windows 下也可以用 source insight。以下的当前路径为内核代码路径,通常为/usr/src/linux内核版本为 2
    发表于 09-11 17:01 18次下载
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b><b class='flag-5'>代码</b>感悟

    怎样去读Linux内核代码

    怎样去读Linux内核代码
    发表于 10-25 10:15 13次下载
    怎样去读<b class='flag-5'>Linux</b><b class='flag-5'>内核</b>源<b class='flag-5'>代码</b>

    Linux内核代码情景分析(全册高清带书签)pdf下载

    Linux内核代码情景分析需要的拿走吧
    发表于 01-04 16:57 8次下载

    如何在ZC702板上运行Linux内核代码

    了解如何获取Xilinx Linux内核代码,配置它,构建内核和设备树,最后在ZC702板上运行新内核
    的头像 发表于 11-23 07:09 3141次阅读

    关于Linux内核代码风格

    从而导致的问题。因为当时代码量不大,所以解决问题的时间相对较少。在代码量增大的情况下可以借助工具进行自动修改。 快速修改编码风格的工具 scripts/checkpatch.pl 这是一个检查patch是否符合
    的头像 发表于 04-25 14:50 1558次阅读

    Linux内核代码60%都是驱动?

    为什么Linux内核代码60%都是驱动? 如果每支持新的设备就加入驱动,内核会不会变得越来越臃肿?
    的头像 发表于 07-11 11:48 452次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b><b class='flag-5'>代码</b>60%都是驱动?

    linux内核代码详解

     在安装好的Linux系统中,内核的源代码位于/ust/src/linux.如果是从GNU网站下载的Linux
    发表于 09-06 17:01 2次下载

    Linux内核如何使用结构体和函数指针?

    我将结合具体的Linux内核驱动框架代码来展示Linux内核如何使用结构体和函数指针。
    的头像 发表于 09-06 14:17 570次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>如何使用结构体和函数指针?