原始碼分析 Linux 核心工具Sparse

2021-07-13 12:42:26 字數 2857 閱讀 6211

sparse誕生於2023年,是由linux之父開發的,目的就是提供乙個靜態檢查**的工具,從而減少linux核心的隱患。起始,在sparse之前已經有了乙個不錯的**靜態檢查工具(swat),只不過這個工具不是免費軟體,使用上有一些限制。所以linus自己開發了乙個靜態檢查工具。

核心**中有乙個對sparse的簡略說明文件:documentation/sparse.txt。

sparse通過gcc的擴充套件屬性__attribute__以及自己定義的__context__來對**進行靜態檢查。

這些屬性如下:

巨集名稱巨集定義

說明__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

__attribute__((context(x, 1, 0)))

與__acquires(x)相反

__acquire

__context__(x, 1)

引數x的引用計數+1

__release

__context__(x, 1)

與__acquire(x)相反

__cond_lock(x,c)

((c) ? () : 0)

引數c 不為0時,引用計數 + 1, 並返回1

其中__acquires(x)和__releases,__acquire和__release必須配對使用,否則sparse會發出警告

主要作用就是確保核心使用的整數是在同樣的位方式下。對於使用了這個巨集的變數,sparse會檢查這個變數是否一直在同一種位方式(big-endian,little-endian或其他)下被使用。如果此變數在多個位方式下被使用了,sparse會給出警告。

/* kernel version:4.6.2 */

/* file:include/linux/types.h line:158 */

typedef

unsigned __bitwise__ fmode_t;

如果使用了__user巨集的指標不在使用者位址空間初始化,或者指向核心位址空間、裝置位址空間等,sparse會給出警告。

/* kernel version:4.6.2 */

/* file:kernel/ldt.c line:153 */

static

int read_ldt(void __user *ptr, unsigned

long bytecount)

如果使用了__kernel巨集的指標不在核心位址空間初始化,或者指向使用者位址空間、裝置位址空間等,sparse會給出警告。

/* kernel version:4.6.2 */

/* file:drivers/s390/char/hmcdrv_ftp.h line:52 */

void __kernel *buf;

如果使用了__iomem巨集的指標不在裝置位址空間初始化,或者指向使用者位址空間、核心位址空間等,sparse會給出警告。

/* kernel version:4.6.2 */

/* file:kernel/apic/io_apic.c line:461 */

struct io_apic __iomem *io_apic;

如果使用了__safe巨集修飾的變數在使用前沒有判斷它是否為空(null),sparse會給出警告。

最新的gcc應該已經會對這種情況給出警告,所以沒有必要用sparse去檢查。

如果使用了__force修飾的變數可以進行強制型別轉換,沒有使用__force修飾的變數進行強制型別轉換時,sparse會給出警告。

/* kernel version:4.6.2 */

/* file:include/asm/io.h line:213 */

memset((void __force *)addr, val, count);

如果使用了__nocast修飾的引數必須和實際傳入的引數型別一致才可以,否則sparse會給出警告。

/* kernel version:4.6.2 */

/* file:include/asm-generic/cputime_nsecs.h line:21 */

typedef u64

__nocast cputime_t;

這4個巨集都是和鎖有關的,__acquires和__releases、__acquire和__release必須成對使用,否則sparse會警告。

Linux核心 fork 原始碼分析

核心版本 linux 4.4.18 原始碼位置 這裡 接著 呼叫copy process 它設定了程序描述符以及子程序所需的任何其他核心資料結構。ftrace graph init task 初始化ftrace,核心追蹤函式呼叫。rt mutex init task 初始化鎖。copy creds ...

linux核心原始碼目錄結構分析

注 本文是學習朱老師課程整理的筆記,基於linux2.6.35.7和九鼎x210bv3s開發板進行移植。arch。arch是architecture的縮寫。arch目錄下是好多個不同架構的cpu的子目錄,譬如arm這種cpu的所有檔案都在arch arm目錄下,x86的cpu的所有檔案都在arch ...

linux核心原始碼目錄結構分析

1 分析原始碼目錄下的單個檔案 1 kbuild,kbuild是kernel build的意思,就是核心編譯的意思。這個檔案就是linux核心特有的核心編譯體系需要用到的檔案。2 makefile,這個是linux核心的總makefile,整個核心工程用這個makefile來管理的。3 mk,是九鼎...