美文网首页
Linux开发工具-sparse

Linux开发工具-sparse

作者: 吴丹_89fc | 来源:发表于2020-10-04 07:32 被阅读0次

    Linux开发工具-sparse

    简介

    sparse是Linux内核开发者早期开发的静态代码检查工具,用于在编译阶段快速发现代码中隐含的问题,像加解锁未配对等。

    sparse利用了GCC专门提供的编译attribute来实现。

    安装

    使用说明

    • 命令:sparse xxx.c

      注意: sparse本身有点编译器性质, 它在预处理源文件时会自动打开功能宏__CHECKER__
      
    • Linux kernel

      • Makefile

         # Call a source code checker (by default, "sparse") as part of the
        # C compilation.
        #
        # Use 'make C=1' to enable checking of only re-compiled files.
        # Use 'make C=2' to enable checking of *all* source files, regardless
        # of whether they are re-compiled or not.
        #
        # See the file "Documentation/sparse.txt" for more details, including
        # where to get the "sparse" utility.
        
        ifeq ("$(origin C)", "command line")
          KBUILD_CHECKSRC = $(C)
        endif
        ifndef KBUILD_CHECKSRC
          KBUILD_CHECKSRC = 0
        endif
        
        CHECK       = sparse
        CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise -Wno-return-void $(CF)
        
        export KBUILD_CHECKSRC
        
      • scripts/Makefile.build

        # Linus' kernel sanity checking tool
        ifneq ($(KBUILD_CHECKSRC),0)
          ifeq ($(KBUILD_CHECKSRC),2)
            quiet_cmd_force_checksrc = CHECK   $<
                  cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
          else
              quiet_cmd_checksrc     = CHECK   $<
                    cmd_checksrc     = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
          endif
        endif
        
        define rule_cc_o_c
                $(call echo-cmd,checksrc) $(cmd_checksrc)                         \
                $(call echo-cmd,cc_o_c) $(cmd_cc_o_c);                            \
                $(cmd_modversions_c)                                              \
                $(call echo-cmd,record_mcount)                                    \
                $(cmd_record_mcount)                                              \
                scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' >    \
                                                              $(dot-target).tmp;  \
                rm -f $(depfile);                                                 \
                mv -f $(dot-target).tmp $(dot-target).cmd
        endef
        
      • include/linux/compiler.h

        #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)))
        #ifdef CONFIG_SPARSE_RCU_POINTER
        # define __rcu        __attribute__((noderef, address_space(4)))
        #else
        # define __rcu
        #endif
        extern void __chk_user_ptr(const volatile void __user *);
        extern void __chk_io_ptr(const volatile void __iomem *);
        #else
        # define __user
        # 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
        #endif
        
      • make C=1:检查重新编译的C文件

      • make C=2:检查所有的C文件(不论是否有重新编译)

    • 普通程序

      • 示例程序

        #include <stdio.h>
        
        typedef int lock_t;
        
        #ifdef __CHECKER__
        # 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)
        #else
        # define __must_hold(x)
        # define __acquires(x)
        # define __releases(x)
        # define __acquire(x) (void)0
        # define __release(x) (void)0
        #endif
        
        static inline void lock_t_lock(lock_t *ll) __acquires(ll);
        static inline void lock_t_unlock(lock_t *ll) __releases(ll);
        
        static inline void lock_t_lock(lock_t *ll)
        {
                __acquire(ll);
        }
        
        static inline void lock_t_unlock(lock_t *ll)
        {
                __release(ll);
        }
        
        static lock_t mylock;
        
        void run(int a)
        {
                lock_t_lock(&mylock);
                if (a == 0) {
                        return;
                }
                lock_t_unlock(&mylock);
        }
        
        int main(int argc, char *argv[])
        {
                run(1);
                return 0;
        }
        
      • 运行效果

        root@ubuntu:~# gcc test.c
        root@ubuntu:~# 
        root@ubuntu:~# 
        root@ubuntu:~# sparse test.c
        test.c:35:6: warning: symbol 'run' was not declared. Should it be static?
        test.c:35:6: warning: context imbalance in 'run' - wrong count at exit
        

    相关文章

      网友评论

          本文标题:Linux开发工具-sparse

          本文链接:https://www.haomeiwen.com/subject/prnguktx.html