요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. Copyright 2004 Linus Torvalds
.. Copyright 2004 Pavel Machek <[email protected]>
.. Copyright 2006 Bob Copeland <[email protected]>
Sparse
======
Sparse is a semantic checker for C programs; it can be used to find a
number of potential problems with kernel code. See
https://lwn.net/Articles/689907/ for an overview of sparse; this document
contains some kernel-specific sparse information.
More information on sparse, mainly about its internals, can be found in
its official pages at https://sparse.docs.kernel.org.
Using sparse for typechecking
-----------------------------
"__bitwise" is a type attribute, so you have to do something like this::
typedef int __bitwise pm_request_t;
enum pm_request {
PM_SUSPEND = (__force pm_request_t) 1,
PM_RESUME = (__force pm_request_t) 2
};
which makes PM_SUSPEND and PM_RESUME "bitwise" integers (the "__force" is
there because sparse will complain about casting to/from a bitwise type,
but in this case we really _do_ want to force the conversion). And because
the enum values are all the same type, now "enum pm_request" will be that
type too.
And with gcc, all the "__bitwise"/"__force stuff" goes away, and it all
ends up looking just like integers to gcc.
Quite frankly, you don't need the enum there. The above all really just
boils down to one special "int __bitwise" type.
So the simpler way is to just do::
typedef int __bitwise pm_request_t;
#define PM_SUSPEND ((__force pm_request_t) 1)
#define PM_RESUME ((__force pm_request_t) 2)
and you now have all the infrastructure needed for strict typechecking.
One small note: the constant integer "0" is special. You can use a
constant zero as a bitwise integer type without sparse ever complaining.
This is because "bitwise" (as the name implies) was designed for making
sure that bitwise types don't get mixed up (little-endian vs big-endian
vs cpu-endian vs whatever), and there the constant "0" really _is_
special.
Using sparse for lock checking
------------------------------
The following macros are undefined for gcc and defined during a sparse
run to use the "context" tracking feature of sparse, applied to
locking. These annotations tell sparse when a lock is held, with
regard to the annotated function's entry and exit.
__must_hold - The specified lock is held on function entry and exit.
__acquires - The specified lock is held on function exit, but not entry.
__releases - The specified lock is held on function entry, but not exit.
If the function enters and exits without the lock held, acquiring and
releasing the lock inside the function in a balanced way, no
annotation is needed. The three annotations above are for cases where
sparse would otherwise report a context imbalance.
Getting sparse
--------------
You can get tarballs of the latest released versions from:
https://www.kernel.org/pub/software/devel/sparse/dist/
Alternatively, you can get snapshots of the latest development version
of sparse using git to clone::
git://git.kernel.org/pub/scm/devel/sparse/sparse.git
Once you have it, just do::
make
make install
as a regular user, and it will install sparse in your ~/bin directory.
Using sparse
------------
Do a kernel make with "make C=1" to run sparse on all the C files that get
recompiled, or use "make C=2" to run sparse on the files whether they need to
be recompiled or not. The latter is a fast way to check the whole tree if you
have already built it.
The optional make variable CF can be used to pass arguments to sparse. The
build system passes -Wbitwise to sparse automatically.
Note that sparse defines the __CHECKER__ preprocessor symbol.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Sparse semantic checker
1-15Copyright 2004 Linus Torvalds
Copyright 2004 Pavel Machek <[email protected]>
Copyright 2006 Bob Copeland <[email protected]>
Sparse
Sparse는 C program용 semantic checker이며 kernel code의 여러 잠재적 문제를 찾는 데 사용할 수 있습니다. 개요는 `https://lwn.net/Articles/689907/`을 참조하십시오. 이 문서는 kernel-specific Sparse 정보를 제공합니다.
Sparse 내부 구현을 중심으로 한 추가 정보는 official page `https://sparse.docs.kernel.org`에 있습니다.
Sparse typechecking
16-55Typechecking에 Sparse 사용
`__bitwise`는 type attribute이므로 다음과 같이 type과 enum을 정의할 수 있습니다.
typedef int __bitwise pm_request_t;
enum pm_request {
PM_SUSPEND = (__force pm_request_t) 1,
PM_RESUME = (__force pm_request_t) 2
};
이렇게 하면 `PM_SUSPEND`와 `PM_RESUME`가 bitwise integer가 됩니다. Sparse는 bitwise type으로 또는 그 type에서 casting할 때 warning을 내므로, 여기서는 의도한 conversion임을 나타내기 위해 `__force`를 사용합니다. Enum value가 모두 같은 type이므로 `enum pm_request`도 그 type이 됩니다.
GCC에서는 `__bitwise`와 `__force` 관련 annotation이 사라져 모두 일반 integer처럼 보입니다.
실제로 enum은 필수가 아니며 위 구성은 하나의 특수 `int __bitwise` type으로 요약할 수 있습니다. 더 간단한 방식은 다음과 같습니다.
typedef int __bitwise pm_request_t;
#define PM_SUSPEND ((__force pm_request_t) 1)
#define PM_RESUME ((__force pm_request_t) 2)
이제 strict typechecking에 필요한 infrastructure가 갖춰집니다.
작은 예외로 constant integer 0은 특별합니다. Sparse warning 없이 constant zero를 bitwise integer type으로 사용할 수 있습니다.
Bitwise type은 little-endian, big-endian, cpu-endian 같은 서로 다른 bitwise type이 섞이지 않게 설계되었으며 이 context에서 constant 0은 실제로 공통의 특별한 값이기 때문입니다.
Sparse lock checking
56-74Lock checking에 Sparse 사용
다음 macro는 GCC에서는 정의되지 않고 Sparse 실행 중에는 context tracking feature를 locking에 적용하도록 정의됩니다. Annotation 대상 function의 entry와 exit에서 lock held state를 Sparse에 알려 줍니다.
`__must_hold`: 지정 lock은 function entry와 exit 모두에서 held 상태입니다.
`__acquires`: 지정 lock은 entry에서는 held가 아니고 exit에서는 held 상태입니다.
`__releases`: 지정 lock은 entry에서는 held이고 exit에서는 held가 아닙니다.
Function이 lock을 held하지 않은 상태로 들어오고 나가며 내부에서 balanced하게 acquire와 release한다면 annotation이 필요 없습니다. 위 세 annotation은 그렇지 않으면 Sparse가 context imbalance를 report할 경우에 사용합니다.
Function 경계의 lock state를 entry와 exit 기준으로 정리했습니다.
Sparse 설치와 kernel build에서 실행
75-104Sparse 받기
최신 release tarball은 `https://www.kernel.org/pub/software/devel/sparse/dist/`에서 받을 수 있습니다.
또는 git으로 최신 development snapshot repository를 clone할 수 있습니다.
git://git.kernel.org/pub/scm/devel/sparse/sparse.git
받은 source에서 일반 user로 다음 command를 실행합니다.
make
make install
Sparse는 `~/bin` directory에 설치됩니다.
Sparse 사용
Kernel을 `make C=1`로 build하면 다시 compile되는 모든 C file에 Sparse를 실행합니다. `make C=2`는 recompile 필요 여부와 관계없이 file에 Sparse를 실행합니다. Tree를 이미 build했다면 전체 tree를 빠르게 검사하는 방법입니다.
선택적 make variable `CF`로 Sparse argument를 전달할 수 있습니다. Build system은 `-Wbitwise`를 자동으로 전달합니다.
Sparse는 `__CHECKER__` preprocessor symbol을 정의합니다.
요약과 해설
sparse.rst:1-104Sparse는 kernel C code의 semantic problem을 찾습니다. `__bitwise`와 `__force`는 endian 등 서로 다른 integer domain을 엄격히 구분하고 lock annotation은 function 경계의 held state를 추적합니다.
`make C=1`은 recompile되는 file을, `make C=2`는 전체 대상 file을 검사합니다. `CF`로 추가 argument를 전달하며 build system은 bitwise warning을 자동 활성화합니다.