Sparse Introduction
Sparse was born in 2004 and was developed by the father of Linux. It aims to provide a tool for static code check to reduce the hidden risks of Linux kernel.
In fact, we already had a good static code check tool ("SWAT") before sparse, but this tool is not a free software and has some restrictions on its use.
Therefore, Linus developed a static check tool.
For details, refer to this article (in 2004): Finding kernel problems automatically
Sparse has very little information about its usage. I also found it online and obtained it through my own experiments.
The kernel code also provides a brief description of sparse: Documentation/sparse.txt
Sparse uses the extended attribute _ of GCC and its own defined _ context _ to perform static checks on the code.
These attributes are as follows (try to sort them out, and there may be some incomplete ones ):
# DEFINE _ bitwise _ attribute _ (bitwise) Ensure that the variables are in the same bit mode (such as bit-Endian, little-endiandeng) # DEFINE _ User _ attribute _ (noderef, address_space (1 ))) the pointer address must be in the user address space # DEFINE _ KERNEL _ attribute _ (noderef, address_space (0 ))) the pointer address must be in the kernel address space # DEFINE _ iomem _ attribute _ (noderef, address_space (2 ))) the pointer address must be in the device address space # DEFINE _ safe _ attribute _ (SAFE )) variable can be empty # DEFINE _ force _ attribute _ (Force) variable can be forcibly converted # DEFINE _ nocast _ attribute _ (nocast) parameter types must be consistent with actual parameter types # DEFINE _ acquires (X) _ attribute _ (context (x, 0, 1) parameter X must be 0 before execution. After execution, the reference count must be 1 # DEFINE _ Releases (x) _ attribute _ (context (x, 1, 0) and _ acquires (X) opposite # DEFINE _ acquire (x) _ context _ (x, 1) parameter x reference count + 1 # DEFINE _ release (X) _ context _ (x,-1) is opposite to _ acquire (x) # DEFINE _ cond_lock (x, c) (c )? ({_ Acquire (x); 1 ;}): 0) When parameter C is not 0, the reference count is + 1, and 1 where _ acquires (X) is returned) and _ Releases (x), _ acquire (X) and _ release (x) must be paired. Otherwise, sparse will give a warning: in the RPM ora system, sparse installed through RPM has a small bug. even if an error: Unable to open 'stddef is reported. h' error, it is best to compile and install sparse from your own source code. reference: http://wangcong.org/blog/archives/504
Usage of sparse _ bitwise
The main function is to ensure that the integer used by the kernel is in the same bit mode.
In the root directory of the kernel code, grep-R' _ bitwise 'indicates that this macro is used in many kernel codes.
For a variable that uses this macro, sparse checks whether the variable has been used in the same bit mode (big-Endian, little-Endian, or other,
If this variable is used in multiple ways, sparse will give a warning.
Example in kernel code:
/* Kernel version: v2.6.32.61 file: Include/sound/CORE. h 51 line */typedef int _ bitwise snd_device_type_t;
_ User usage
If the pointer of the _ User Macro is not initialized in the user address space, or points to the kernel address space, device address space, and so on, sparse will give a warning.
Example in kernel code:
/* Kernel version: v2.6.32.61 file: ARCH/score/kernel/signal. C 45 rows */static int setup_sigcontext (structpt_regs * regs, struct sigcontext _ User * SC)
_ Use of Kernel
If the pointer with the _ KERNEL macro is not initialized in the kernel address space, or points to the user address space, device address space, etc., sparse will give a warning.
Example in kernel code:
/* Kernel version: v2.6.32.61 file: ARCH/s390/lib/uaccess_pt.c, row 180 */memcpy (to, (void _ KERNEL _ force *) from, N );
_ Iomem usage
If the pointer of the _ iomem macro is not initialized in the device address space, or directed to the user address space or kernel address space, sparse will give a warning.
Example in kernel code:
* // * Kernel version: v2.6.32.61 file: ARCH/microblaze/include/ASM/Io. H 22 rows */static inline unsigned char _ raw_readb (const volatile void _ iomem * ADDR)
_ Safe usage
If the variable modified with _ safe is not null before use, sparse will give a warning.
All kernel code in the kernel version I have referenced (v2.6.32.61) does not use _ safe. It is estimated that with the GCC version update,
GCC has given a warning for this situation, so there is no need to use sparse to check.
_ Force usage
Variables modified with _ force can be forced type conversion. If the variable modified with _ force is not used for forced type conversion, sparse will give a warning.
Example in kernel code:
/* Kernel version: v2.6.32.61 file: ARCH/s390/lib/uaccess_pt.c, row 180 */memcpy (to, (void _ KERNEL _ force *) from, N );
_ Use of nocast
The type of the parameter modified with _ nocast must be the same as the type of the actually passed parameter. Otherwise, sparse will give a warning.
Example in kernel code:
/* Kernel version: v2.6.32.61 file: fs/XFS/support/ktrace. C 55 rows */ktrace_alloc (INT nentries, unsigned int _ nocast sleep)
_ Acquires _ Releases _ acquire _ release usage
These four macros are related to locks. _ acquires and _ releases must be used in pairs. _ acquire and _ release must be used in pairs. Otherwise, sparse will give a warning.
_ Use of cond_lock
This macro is special because there are no macros such as _ cond_unlock corresponding to it.
The reason for this macro can see: http://yarchive.net/comp/linux/sparse.html last paragraph.
The source of this macro is clear, but why does it need to call _ acquire (x )? I am not very clear. I haven't found it online for a long time. Thank you very much for your advice !!!
Use of sparse in compiling the kernel
It is very simple to use sparse to perform static analysis on the kernel.
# Check all kernel code make C = 1 Check all re-compiled code make C = 2 check all code, whether it is re-compiled or not
Supplement
In addition to Static Analysis of kernel code, sparse can also be used in General C language programs.
For example, the following small example:
/*************************************** **************************************** @ File: sparse_test.c * @ Author: wangyubin * @ Date: Fri Feb 28 16:33:34 2014 ** @ brief: test each sparse checkpoint * 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 ); /* If you comment out this sparse sentence, an error is returned */return 0 ;}