요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. Copyright 2010 Nicolas Palix <[email protected]>
.. Copyright 2010 Julia Lawall <[email protected]>
.. Copyright 2010 Gilles Muller <[email protected]>
.. highlight:: none
.. _devtools_coccinelle:
Coccinelle
==========
Coccinelle is a tool for pattern matching and text transformation that has
many uses in kernel development, including the application of complex,
tree-wide patches and detection of problematic programming patterns.
Getting Coccinelle
------------------
The semantic patches included in the kernel use features and options
which are provided by Coccinelle version 1.0.0-rc11 and above.
Using earlier versions will fail as the option names used by
the Coccinelle files and coccicheck have been updated.
Coccinelle is available through the package manager
of many distributions, e.g. :
- Debian
- Fedora
- Ubuntu
- OpenSUSE
- Arch Linux
- NetBSD
- FreeBSD
Some distribution packages are obsolete and it is recommended
to use the latest version released from the Coccinelle homepage at
http://coccinelle.lip6.fr/
Or from Github at:
https://github.com/coccinelle/coccinelle
Once you have it, run the following commands::
./autogen
./configure
make
as a regular user, and install it with::
sudo make install
More detailed installation instructions to build from source can be
found at:
https://github.com/coccinelle/coccinelle/blob/master/install.txt
Supplemental documentation
--------------------------
For supplemental documentation refer to the wiki:
https://bottest.wiki.kernel.org/coccicheck
The wiki documentation always refers to the linux-next version of the script.
For Semantic Patch Language(SmPL) grammar documentation refer to:
https://coccinelle.gitlabpages.inria.fr/website/docs/main_grammar.html
Using Coccinelle on the Linux kernel
------------------------------------
A Coccinelle-specific target is defined in the top level
Makefile. This target is named ``coccicheck`` and calls the ``coccicheck``
front-end in the ``scripts`` directory.
Four basic modes are defined: ``patch``, ``report``, ``context``, and
``org``. The mode to use is specified by setting the MODE variable with
``MODE=<mode>``.
- ``patch`` proposes a fix, when possible.
- ``report`` generates a list in the following format:
file:line:column-column: message
- ``context`` highlights lines of interest and their context in a
diff-like style. Lines of interest are indicated with ``-``.
- ``org`` generates a report in the Org mode format of Emacs.
Note that not all semantic patches implement all modes. For easy use
of Coccinelle, the default mode is "report".
Two other modes provide some common combinations of these modes.
- ``chain`` tries the previous modes in the order above until one succeeds.
- ``rep+ctxt`` runs successively the report mode and the context mode.
It should be used with the C option (described later)
which checks the code on a file basis.
Examples
~~~~~~~~
To make a report for every semantic patch, run the following command::
make coccicheck MODE=report
To produce patches, run::
make coccicheck MODE=patch
The coccicheck target applies every semantic patch available in the
sub-directories of ``scripts/coccinelle`` to the entire Linux kernel.
For each semantic patch, a commit message is proposed. It gives a
description of the problem being checked by the semantic patch, and
includes a reference to Coccinelle.
As with any static code analyzer, Coccinelle produces false
positives. Thus, reports must be carefully checked, and patches
reviewed.
To enable verbose messages set the V= variable, for example::
make coccicheck MODE=report V=1
Coccinelle parallelization
--------------------------
By default, coccicheck tries to run as parallel as possible. To change
the parallelism, set the J= variable. For example, to run across 4 CPUs::
make coccicheck MODE=report J=4
As of Coccinelle 1.0.2 Coccinelle uses Ocaml parmap for parallelization;
if support for this is detected you will benefit from parmap parallelization.
When parmap is enabled coccicheck will enable dynamic load balancing by using
``--chunksize 1`` argument. This ensures we keep feeding threads with work
one by one, so that we avoid the situation where most work gets done by only
a few threads. With dynamic load balancing, if a thread finishes early we keep
feeding it more work.
When parmap is enabled, if an error occurs in Coccinelle, this error
value is propagated back, and the return value of the ``make coccicheck``
command captures this return value.
Using Coccinelle with a single semantic patch
---------------------------------------------
The optional make variable COCCI can be used to check a single
semantic patch. In that case, the variable must be initialized with
the name of the semantic patch to apply.
For instance::
make coccicheck COCCI=<my_SP.cocci> MODE=patch
or::
make coccicheck COCCI=<my_SP.cocci> MODE=report
Controlling Which Files are Processed by Coccinelle
---------------------------------------------------
By default the entire kernel source tree is checked.
To apply Coccinelle to a specific directory, ``M=`` can be used.
For example, to check drivers/net/wireless/ one may write::
make coccicheck M=drivers/net/wireless/
To apply Coccinelle on a file basis, instead of a directory basis, the
C variable is used by the makefile to select which files to work with.
This variable can be used to run scripts for the entire kernel, a
specific directory, or for a single file.
For example, to check drivers/bluetooth/bfusb.c, the value 1 is
passed to the C variable to check files that make considers
need to be compiled.::
make C=1 CHECK=scripts/coccicheck drivers/bluetooth/bfusb.o
The value 2 is passed to the C variable to check files regardless of
whether they need to be compiled or not.::
make C=2 CHECK=scripts/coccicheck drivers/bluetooth/bfusb.o
In these modes, which work on a file basis, there is no information
about semantic patches displayed, and no commit message proposed.
This runs every semantic patch in scripts/coccinelle by default. The
COCCI variable may additionally be used to only apply a single
semantic patch as shown in the previous section.
The "report" mode is the default. You can select another one with the
MODE variable explained above.
Debugging Coccinelle SmPL patches
---------------------------------
Using coccicheck is best as it provides in the spatch command line
include options matching the options used when we compile the kernel.
You can learn what these options are by using V=1; you could then
manually run Coccinelle with debug options added.
Alternatively you can debug running Coccinelle against SmPL patches
by asking for stderr to be redirected to stderr. By default stderr
is redirected to /dev/null; if you'd like to capture stderr you
can specify the ``DEBUG_FILE="file.txt"`` option to coccicheck. For
instance::
rm -f cocci.err
make coccicheck COCCI=scripts/coccinelle/free/kfree.cocci MODE=report DEBUG_FILE=cocci.err
cat cocci.err
You can use SPFLAGS to add debugging flags; for instance you may want to
add both ``--profile --show-trying`` to SPFLAGS when debugging. For example
you may want to use::
rm -f err.log
export COCCI=scripts/coccinelle/misc/irqf_oneshot.cocci
make coccicheck DEBUG_FILE="err.log" MODE=report SPFLAGS="--profile --show-trying" M=./drivers/mfd
err.log will now have the profiling information, while stdout will
provide some progress information as Coccinelle moves forward with
work.
NOTE:
DEBUG_FILE support is only supported when using coccinelle >= 1.0.2.
Currently, DEBUG_FILE support is only available to check folders, and
not single files. This is because checking a single file requires spatch
to be called twice leading to DEBUG_FILE being set both times to the same value,
giving rise to an error.
.cocciconfig support
--------------------
Coccinelle supports reading .cocciconfig for default Coccinelle options that
should be used every time spatch is spawned. The order of precedence for
variables for .cocciconfig is as follows:
- Your current user's home directory is processed first
- Your directory from which spatch is called is processed next
- The directory provided with the ``--dir`` option is processed last, if used
``make coccicheck`` also supports using M= targets. If you do not supply
any M= target, it is assumed you want to target the entire kernel.
The kernel coccicheck script has::
OPTIONS="--dir $srcroot $COCCIINCLUDE"
Here, $srcroot refers to the source directory of the target: it points to the
external module's source directory when M= used, and otherwise, to the kernel
source directory. The third rule ensures the spatch reads the .cocciconfig from
the target directory, allowing external modules to have their own .cocciconfig
file.
If not using the kernel's coccicheck target, keep the above precedence
order logic of .cocciconfig reading. If using the kernel's coccicheck target,
override any of the kernel's .coccicheck's settings using SPFLAGS.
We help Coccinelle when used against Linux with a set of sensible default
options for Linux with our own Linux .cocciconfig. This hints to coccinelle
that git can be used for ``git grep`` queries over coccigrep. A timeout of 200
seconds should suffice for now.
The options picked up by coccinelle when reading a .cocciconfig do not appear
as arguments to spatch processes running on your system. To confirm what
options will be used by Coccinelle run::
spatch --print-options-only
You can override with your own preferred index option by using SPFLAGS. Take
note that when there are conflicting options Coccinelle takes precedence for
the last options passed. Using .cocciconfig is possible to use idutils, however
given the order of precedence followed by Coccinelle, since the kernel now
carries its own .cocciconfig, you will need to use SPFLAGS to use idutils if
desired. See below section "Additional flags" for more details on how to use
idutils.
Additional flags
----------------
Additional flags can be passed to spatch through the SPFLAGS
variable. This works as Coccinelle respects the last flags
given to it when options are in conflict. ::
make SPFLAGS=--use-glimpse coccicheck
Coccinelle supports idutils as well but requires coccinelle >= 1.0.6.
When no ID file is specified coccinelle assumes your ID database file
is in the file .id-utils.index on the top level of the kernel. Coccinelle
carries a script scripts/idutils_index.sh which creates the database with::
mkid -i C --output .id-utils.index
If you have another database filename you can also just symlink with this
name. ::
make SPFLAGS=--use-idutils coccicheck
Alternatively you can specify the database filename explicitly, for
instance::
make SPFLAGS="--use-idutils /full-path/to/ID" coccicheck
See ``spatch --help`` to learn more about spatch options.
Note that the ``--use-glimpse`` and ``--use-idutils`` options
require external tools for indexing the code. None of them is
thus active by default. However, by indexing the code with
one of these tools, and according to the cocci file used,
spatch could proceed the entire code base more quickly.
SmPL patch specific options
---------------------------
SmPL patches can have their own requirements for options passed
to Coccinelle. SmPL patch-specific options can be provided by
providing them at the top of the SmPL patch, for instance::
// Options: --no-includes --include-headers
SmPL patch Coccinelle requirements
----------------------------------
As Coccinelle features get added some more advanced SmPL patches
may require newer versions of Coccinelle. If an SmPL patch requires
a minimum version of Coccinelle, this can be specified as follows,
as an example if requiring at least Coccinelle >= 1.0.5::
// Requires: 1.0.5
Proposing new semantic patches
------------------------------
New semantic patches can be proposed and submitted by kernel
developers. For sake of clarity, they should be organized in the
sub-directories of ``scripts/coccinelle/``.
Detailed description of the ``report`` mode
-------------------------------------------
``report`` generates a list in the following format::
file:line:column-column: message
Example
~~~~~~~
Running::
make coccicheck MODE=report COCCI=scripts/coccinelle/api/err_cast.cocci
will execute the following part of the SmPL script::
<smpl>
@r depends on !context && !patch && (org || report)@
expression x;
position p;
@@
ERR_PTR@p(PTR_ERR(x))
@script:python depends on report@
p << r.p;
x << r.x;
@@
msg="ERR_CAST can be used with %s" % (x)
coccilib.report.print_report(p[0], msg)
</smpl>
This SmPL excerpt generates entries on the standard output, as
illustrated below::
/home/user/linux/crypto/ctr.c:188:9-16: ERR_CAST can be used with alg
/home/user/linux/crypto/authenc.c:619:9-16: ERR_CAST can be used with auth
/home/user/linux/crypto/xts.c:227:9-16: ERR_CAST can be used with alg
Detailed description of the ``patch`` mode
------------------------------------------
When the ``patch`` mode is available, it proposes a fix for each problem
identified.
Example
~~~~~~~
Running::
make coccicheck MODE=patch COCCI=scripts/coccinelle/api/err_cast.cocci
will execute the following part of the SmPL script::
<smpl>
@ depends on !context && patch && !org && !report @
expression x;
@@
- ERR_PTR(PTR_ERR(x))
+ ERR_CAST(x)
</smpl>
This SmPL excerpt generates patch hunks on the standard output, as
illustrated below::
diff -u -p a/crypto/ctr.c b/crypto/ctr.c
--- a/crypto/ctr.c 2010-05-26 10:49:38.000000000 +0200
+++ b/crypto/ctr.c 2010-06-03 23:44:49.000000000 +0200
@@ -185,7 +185,7 @@ static struct crypto_instance *crypto_ct
alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER,
CRYPTO_ALG_TYPE_MASK);
if (IS_ERR(alg))
- return ERR_PTR(PTR_ERR(alg));
+ return ERR_CAST(alg);
/* Block size must be >= 4 bytes. */
err = -EINVAL;
Detailed description of the ``context`` mode
--------------------------------------------
``context`` highlights lines of interest and their context
in a diff-like style.
**NOTE**: The diff-like output generated is NOT an applicable patch. The
intent of the ``context`` mode is to highlight the important lines
(annotated with minus, ``-``) and gives some surrounding context
lines around. This output can be used with the diff mode of
Emacs to review the code.
Example
~~~~~~~
Running::
make coccicheck MODE=context COCCI=scripts/coccinelle/api/err_cast.cocci
will execute the following part of the SmPL script::
<smpl>
@ depends on context && !patch && !org && !report@
expression x;
@@
* ERR_PTR(PTR_ERR(x))
</smpl>
This SmPL excerpt generates diff hunks on the standard output, as
illustrated below::
diff -u -p /home/user/linux/crypto/ctr.c /tmp/nothing
--- /home/user/linux/crypto/ctr.c 2010-05-26 10:49:38.000000000 +0200
+++ /tmp/nothing
@@ -185,7 +185,6 @@ static struct crypto_instance *crypto_ct
alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER,
CRYPTO_ALG_TYPE_MASK);
if (IS_ERR(alg))
- return ERR_PTR(PTR_ERR(alg));
/* Block size must be >= 4 bytes. */
err = -EINVAL;
Detailed description of the ``org`` mode
----------------------------------------
``org`` generates a report in the Org mode format of Emacs.
Example
~~~~~~~
Running::
make coccicheck MODE=org COCCI=scripts/coccinelle/api/err_cast.cocci
will execute the following part of the SmPL script::
<smpl>
@r depends on !context && !patch && (org || report)@
expression x;
position p;
@@
ERR_PTR@p(PTR_ERR(x))
@script:python depends on org@
p << r.p;
x << r.x;
@@
msg="ERR_CAST can be used with %s" % (x)
msg_safe=msg.replace("[","@(").replace("]",")")
coccilib.org.print_todo(p[0], msg_safe)
</smpl>
This SmPL excerpt generates Org entries on the standard output, as
illustrated below::
* TODO [[view:/home/user/linux/crypto/ctr.c::face=ovl-face1::linb=188::colb=9::cole=16][ERR_CAST can be used with alg]]
* TODO [[view:/home/user/linux/crypto/authenc.c::face=ovl-face1::linb=619::colb=9::cole=16][ERR_CAST can be used with auth]]
* TODO [[view:/home/user/linux/crypto/xts.c::face=ovl-face1::linb=227::colb=9::cole=16][ERR_CAST can be used with alg]]
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Coccinelle 소개와 설치
1-70저작권 2010 Nicolas Palix <[email protected]>
저작권 2010 Julia Lawall <[email protected]>
저작권 2010 Gilles Muller <[email protected]>
Coccinelle
Coccinelle은 패턴 일치와 텍스트 변환을 수행하는 도구입니다. 복잡한 트리 전체 패치 적용과 문제가 있는 프로그래밍 패턴 탐지를 비롯해 커널 개발에서 다양한 용도로 사용됩니다.
Coccinelle 구하기
커널에 포함된 semantic patch는 Coccinelle 1.0.0-rc11 이상에서 제공하는 기능과 옵션을 사용합니다. Coccinelle 파일과 coccicheck에서 사용하는 옵션 이름이 갱신되었으므로 이전 버전을 사용하면 실패합니다.
Coccinelle은 Debian, Fedora, Ubuntu, OpenSUSE, Arch Linux, NetBSD, FreeBSD 등 여러 배포판의 패키지 관리자를 통해 설치할 수 있습니다.
일부 배포판 패키지는 오래되었으므로 Coccinelle 홈페이지에서 공개한 최신 버전을 사용하는 것이 좋습니다.
http://coccinelle.lip6.fr/
또는 다음 GitHub 저장소에서 받을 수 있습니다.
https://github.com/coccinelle/coccinelle
소스를 받은 뒤 일반 사용자로 다음 명령을 실행하십시오.
./autogen
./configure
make
그런 다음 다음 명령으로 설치하십시오.
sudo make install
소스 빌드에 관한 더 자세한 설치 지침은 다음 위치에 있습니다.
https://github.com/coccinelle/coccinelle/blob/master/install.txt
보충 문서
보충 문서는 다음 wiki를 참조하십시오.
https://bottest.wiki.kernel.org/coccicheck
wiki 문서는 항상 linux-next 버전의 스크립트를 기준으로 합니다.
Semantic Patch Language(SmPL) 문법 문서는 다음을 참조하십시오.
https://coccinelle.gitlabpages.inria.fr/website/docs/main_grammar.html
Linux 커널에서 Coccinelle 사용
71-129Linux 커널에서 Coccinelle 사용
최상위 Makefile에는 Coccinelle 전용 target이 정의되어 있습니다. 이 target의 이름은 `coccicheck`이며 `scripts` 디렉터리의 `coccicheck` 프런트엔드를 호출합니다.
네 가지 기본 mode는 `patch`, `report`, `context`, `org`입니다. 사용할 mode는 `MODE=<mode>`로 MODE 변수를 설정해 지정합니다.
`patch`는 가능할 때 수정안을 제안합니다.
`report`는 `file:line:column-column: message` 형식의 목록을 생성합니다.
`context`는 관심 있는 줄과 그 주변을 diff와 비슷한 스타일로 강조합니다. 관심 있는 줄은 `-`로 표시합니다.
`org`는 Emacs의 Org mode 형식으로 보고서를 생성합니다.
모든 semantic patch가 모든 mode를 구현하는 것은 아닙니다. Coccinelle을 쉽게 사용할 수 있도록 기본 mode는 `report`입니다.
그 밖의 두 mode는 앞선 mode들의 일반적인 조합을 제공합니다.
`chain`은 앞의 mode들을 위 순서대로 시도해 하나가 성공할 때까지 진행합니다.
`rep+ctxt`는 report mode와 context mode를 차례로 실행합니다. 파일 단위로 코드를 검사하는 C 옵션과 함께 사용해야 합니다. C 옵션은 뒤에서 설명합니다.
예제
모든 semantic patch에 대해 보고서를 만들려면 다음 명령을 실행하십시오.
make coccicheck MODE=report
패치를 생성하려면 다음을 실행하십시오.
make coccicheck MODE=patch
coccicheck target은 `scripts/coccinelle`의 하위 디렉터리에 있는 모든 semantic patch를 전체 Linux 커널에 적용합니다.
각 semantic patch마다 commit message를 제안합니다. 이 메시지는 semantic patch가 검사하는 문제를 설명하고 Coccinelle 참조를 포함합니다.
다른 정적 코드 분석기와 마찬가지로 Coccinelle도 false positive를 생성합니다. 따라서 보고서는 주의 깊게 확인하고 패치는 검토해야 합니다.
상세 메시지를 활성화하려면 V= 변수를 설정하십시오. 예를 들면 다음과 같습니다.
make coccicheck MODE=report V=1
Coccinelle 병렬화
130-150Coccinelle 병렬화
기본적으로 coccicheck는 가능한 한 병렬로 실행하려고 합니다. 병렬도를 바꾸려면 J= 변수를 설정하십시오. 예를 들어 CPU 4개에서 실행하려면 다음과 같이 합니다.
make coccicheck MODE=report J=4
Coccinelle 1.0.2부터 Coccinelle은 병렬화에 OCaml parmap을 사용합니다. 이 지원이 감지되면 parmap 병렬화의 이점을 얻을 수 있습니다.
parmap이 활성화되면 coccicheck는 `--chunksize 1` 인수를 사용해 동적 부하 분산을 활성화합니다. 작업을 thread에 하나씩 계속 공급하므로 대부분의 작업이 소수 thread에서만 처리되는 상황을 피합니다. 동적 부하 분산에서는 thread가 일찍 끝나면 더 많은 작업을 계속 공급합니다.
parmap이 활성화된 상태에서 Coccinelle 오류가 발생하면 그 오류 값이 다시 전달되며, `make coccicheck` 명령의 반환값이 이 값을 담습니다.
단일 semantic patch 사용
151-166단일 semantic patch로 Coccinelle 사용
선택적 make 변수 COCCI를 사용하면 semantic patch 하나만 검사할 수 있습니다. 이때 변수는 적용할 semantic patch의 이름으로 초기화해야 합니다.
예를 들면 다음과 같습니다.
make coccicheck COCCI=<my_SP.cocci> MODE=patch
또는 다음과 같이 실행합니다.
make coccicheck COCCI=<my_SP.cocci> MODE=report
Coccinelle 처리 파일 제어
167-202Coccinelle이 처리할 파일 제어
기본적으로 전체 커널 소스 트리를 검사합니다.
특정 디렉터리에 Coccinelle을 적용하려면 `M=`을 사용할 수 있습니다. 예를 들어 `drivers/net/wireless/`를 검사하려면 다음과 같이 작성할 수 있습니다.
make coccicheck M=drivers/net/wireless/
디렉터리 단위가 아니라 파일 단위로 Coccinelle을 적용하려면 Makefile이 C 변수를 사용해 작업할 파일을 선택합니다. 이 변수로 전체 커널, 특정 디렉터리 또는 단일 파일에 스크립트를 실행할 수 있습니다.
예를 들어 `drivers/bluetooth/bfusb.c`를 검사할 때 make가 컴파일해야 한다고 판단한 파일을 검사하려면 C 변수에 값 1을 전달합니다.
make C=1 CHECK=scripts/coccicheck drivers/bluetooth/bfusb.o
컴파일 필요 여부와 관계없이 파일을 검사하려면 C 변수에 값 2를 전달합니다.
make C=2 CHECK=scripts/coccicheck drivers/bluetooth/bfusb.o
파일 단위로 동작하는 이 mode들에서는 semantic patch 정보가 표시되지 않고 commit message도 제안되지 않습니다.
기본적으로 `scripts/coccinelle`의 모든 semantic patch를 실행합니다. 앞 절에서 보인 것처럼 COCCI 변수를 추가로 사용하면 semantic patch 하나만 적용할 수 있습니다.
`report` mode가 기본값입니다. 앞서 설명한 MODE 변수로 다른 mode를 선택할 수 있습니다.
Coccinelle SmPL patch 디버깅
203-241Coccinelle SmPL patch 디버깅
coccicheck는 커널을 컴파일할 때 쓰는 옵션과 일치하는 include 옵션을 spatch 명령행에 제공하므로 이를 사용하는 것이 가장 좋습니다. V=1을 사용하면 이 옵션들을 확인할 수 있고, 이후 debug 옵션을 추가해 Coccinelle을 직접 실행할 수 있습니다.
또는 stderr를 지정한 파일로 보내도록 요청해 SmPL patch에 대한 Coccinelle 실행을 디버깅할 수 있습니다. 기본적으로 stderr는 `/dev/null`로 리디렉션됩니다. stderr를 기록하려면 coccicheck에 `DEBUG_FILE="file.txt"` 옵션을 지정할 수 있습니다. 예를 들면 다음과 같습니다.
rm -f cocci.err
make coccicheck COCCI=scripts/coccinelle/free/kfree.cocci MODE=report DEBUG_FILE=cocci.err
cat cocci.err
SPFLAGS로 디버깅 flag를 추가할 수 있습니다. 디버깅할 때 SPFLAGS에 `--profile --show-trying`을 함께 추가할 수 있습니다. 예를 들면 다음과 같습니다.
rm -f err.log
export COCCI=scripts/coccinelle/misc/irqf_oneshot.cocci
make coccicheck DEBUG_FILE="err.log" MODE=report SPFLAGS="--profile --show-trying" M=./drivers/mfd
이제 err.log에는 profiling 정보가 기록되고, stdout에는 Coccinelle이 작업을 진행하는 동안의 일부 진행 정보가 출력됩니다.
참고:
DEBUG_FILE은 Coccinelle 1.0.2 이상에서만 지원됩니다.
현재 DEBUG_FILE은 폴더 검사에만 사용할 수 있고 단일 파일 검사에는 사용할 수 없습니다. 단일 파일을 검사하려면 spatch를 두 번 호출해야 하며, 두 호출에서 DEBUG_FILE이 같은 값으로 설정되어 오류가 발생하기 때문입니다.
.cocciconfig 지원
242-287.cocciconfig 지원
Coccinelle은 spatch를 실행할 때마다 사용할 기본 Coccinelle 옵션을 `.cocciconfig`에서 읽을 수 있습니다. `.cocciconfig` 변수의 우선순위는 다음과 같습니다.
현재 사용자의 home directory를 먼저 처리합니다.
spatch를 호출한 directory를 그다음 처리합니다.
사용했다면 `--dir` 옵션으로 지정한 directory를 마지막에 처리합니다.
`make coccicheck`는 M= target도 지원합니다. M= target을 지정하지 않으면 전체 커널을 대상으로 한다고 간주합니다. 커널 coccicheck 스크립트에는 다음 설정이 있습니다.
OPTIONS="--dir $srcroot $COCCIINCLUDE"
여기서 `$srcroot`는 target의 source directory를 가리킵니다. M=을 사용하면 external module의 source directory를, 그렇지 않으면 kernel source directory를 가리킵니다. 세 번째 규칙은 spatch가 target directory의 `.cocciconfig`를 읽도록 보장하므로 external module이 자체 `.cocciconfig` 파일을 가질 수 있습니다.
커널의 coccicheck target을 사용하지 않는다면 위의 `.cocciconfig` 읽기 우선순위 논리를 유지하십시오. 커널의 coccicheck target을 사용한다면 SPFLAGS로 커널 `.coccicheck` 설정을 재정의하십시오.
Linux에서 Coccinelle을 사용할 때 합리적인 기본 옵션을 제공하도록 Linux 자체 `.cocciconfig`를 둡니다. 이 파일은 coccigrep 대신 `git grep` 질의에 git을 사용할 수 있음을 Coccinelle에 알려 줍니다. 현재는 200초 timeout이면 충분합니다.
Coccinelle이 `.cocciconfig`에서 읽은 옵션은 시스템에서 실행 중인 spatch process의 인수로 나타나지 않습니다. Coccinelle이 사용할 옵션을 확인하려면 다음을 실행하십시오.
spatch --print-options-only
SPFLAGS를 사용해 선호하는 index 옵션으로 재정의할 수 있습니다. 충돌하는 옵션이 있으면 Coccinelle은 마지막에 전달된 옵션을 우선한다는 점에 유의하십시오. `.cocciconfig`로 idutils를 사용할 수 있지만, Coccinelle의 우선순위와 커널 자체 `.cocciconfig` 때문에 idutils를 사용하려면 SPFLAGS가 필요합니다. 사용 방법은 아래의 '추가 flag' 절을 참조하십시오.
추가 flag와 코드 index
288-321추가 flag
SPFLAGS 변수를 통해 spatch에 추가 flag를 전달할 수 있습니다. 옵션이 충돌하면 Coccinelle이 마지막으로 전달된 flag를 따르므로 이 방식이 동작합니다.
make SPFLAGS=--use-glimpse coccicheck
Coccinelle은 idutils도 지원하지만 Coccinelle 1.0.6 이상이 필요합니다. ID 파일을 지정하지 않으면 Coccinelle은 커널 최상위의 `.id-utils.index` 파일을 ID database로 간주합니다. Coccinelle은 다음 명령으로 database를 생성하는 `scripts/idutils_index.sh` 스크립트를 제공합니다.
mkid -i C --output .id-utils.index
database 파일 이름이 다르면 이 이름으로 symbolic link를 만들어도 됩니다.
make SPFLAGS=--use-idutils coccicheck
또는 다음 예처럼 database 파일 이름을 명시적으로 지정할 수 있습니다.
make SPFLAGS="--use-idutils /full-path/to/ID" coccicheck
spatch 옵션에 관한 자세한 내용은 `spatch --help`를 참조하십시오.
`--use-glimpse`와 `--use-idutils` 옵션은 코드를 index하는 외부 도구가 필요하므로 기본적으로 활성화되지 않습니다. 그러나 이 도구 중 하나로 코드를 index하면 사용하는 cocci 파일에 따라 spatch가 전체 code base를 더 빠르게 처리할 수 있습니다.
SmPL patch 전용 옵션과 요구 버전
322-340SmPL patch 전용 옵션
SmPL patch는 Coccinelle에 전달할 옵션에 자체 요구 사항을 둘 수 있습니다. SmPL patch 전용 옵션은 다음 예처럼 SmPL patch 맨 위에 지정할 수 있습니다.
// Options: --no-includes --include-headers
SmPL patch의 Coccinelle 요구 사항
Coccinelle에 기능이 추가됨에 따라 더 발전된 SmPL patch는 새 버전의 Coccinelle을 요구할 수 있습니다. SmPL patch가 최소 Coccinelle 버전을 요구한다면 다음과 같이 지정할 수 있습니다. 이 예는 Coccinelle 1.0.5 이상을 요구합니다.
// Requires: 1.0.5
새 semantic patch 제안
341-348새 semantic patch 제안
커널 개발자는 새로운 semantic patch를 제안하고 제출할 수 있습니다. 명확성을 위해 `scripts/coccinelle/`의 하위 디렉터리에 정리해야 합니다.
report mode 상세 설명
349-389`report` mode 상세 설명
`report`는 다음 형식의 목록을 생성합니다.
file:line:column-column: message
예제
다음을 실행하면
make coccicheck MODE=report COCCI=scripts/coccinelle/api/err_cast.cocci
SmPL 스크립트의 다음 부분이 실행됩니다.
<smpl>
@r depends on !context && !patch && (org || report)@
expression x;
position p;
@@
ERR_PTR@p(PTR_ERR(x))
@script:python depends on report@
p << r.p;
x << r.x;
@@
msg="ERR_CAST can be used with %s" % (x)
coccilib.report.print_report(p[0], msg)
</smpl>
이 SmPL 발췌문은 아래와 같이 standard output에 항목을 생성합니다.
/home/user/linux/crypto/ctr.c:188:9-16: ERR_CAST can be used with alg
/home/user/linux/crypto/authenc.c:619:9-16: ERR_CAST can be used with auth
/home/user/linux/crypto/xts.c:227:9-16: ERR_CAST can be used with alg
patch mode 상세 설명
390-429`patch` mode 상세 설명
`patch` mode를 사용할 수 있으면 식별된 각 문제에 대한 수정안을 제안합니다.
예제
다음을 실행하면
make coccicheck MODE=patch COCCI=scripts/coccinelle/api/err_cast.cocci
SmPL 스크립트의 다음 부분이 실행됩니다.
<smpl>
@ depends on !context && patch && !org && !report @
expression x;
@@
- ERR_PTR(PTR_ERR(x))
+ ERR_CAST(x)
</smpl>
이 SmPL 발췌문은 아래와 같이 standard output에 patch hunk를 생성합니다.
diff -u -p a/crypto/ctr.c b/crypto/ctr.c
--- a/crypto/ctr.c 2010-05-26 10:49:38.000000000 +0200
+++ b/crypto/ctr.c 2010-06-03 23:44:49.000000000 +0200
@@ -185,7 +185,7 @@ static struct crypto_instance *crypto_ct
alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER,
CRYPTO_ALG_TYPE_MASK);
if (IS_ERR(alg))
- return ERR_PTR(PTR_ERR(alg));
+ return ERR_CAST(alg);
/* Block size must be >= 4 bytes. */
err = -EINVAL;
context mode 상세 설명
430-473`context` mode 상세 설명
`context`는 관심 있는 줄과 그 주변을 diff와 비슷한 스타일로 강조합니다.
참고: 생성되는 diff 형태의 출력은 적용 가능한 patch가 아닙니다. `context` mode의 목적은 중요한 줄을 빼기 표시 `-`로 주석 처리해 강조하고 주변 context 줄을 함께 제공하는 것입니다. 이 출력은 Emacs의 diff mode에서 코드를 검토하는 데 사용할 수 있습니다.
예제
다음을 실행하면
make coccicheck MODE=context COCCI=scripts/coccinelle/api/err_cast.cocci
SmPL 스크립트의 다음 부분이 실행됩니다.
<smpl>
@ depends on context && !patch && !org && !report@
expression x;
@@
* ERR_PTR(PTR_ERR(x))
</smpl>
이 SmPL 발췌문은 아래와 같이 standard output에 diff hunk를 생성합니다.
diff -u -p /home/user/linux/crypto/ctr.c /tmp/nothing
--- /home/user/linux/crypto/ctr.c 2010-05-26 10:49:38.000000000 +0200
+++ /tmp/nothing
@@ -185,7 +185,6 @@ static struct crypto_instance *crypto_ct
alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER,
CRYPTO_ALG_TYPE_MASK);
if (IS_ERR(alg))
- return ERR_PTR(PTR_ERR(alg));
/* Block size must be >= 4 bytes. */
err = -EINVAL;
org mode 상세 설명
474-511`org` mode 상세 설명
`org`는 Emacs의 Org mode 형식으로 보고서를 생성합니다.
예제
다음을 실행하면
make coccicheck MODE=org COCCI=scripts/coccinelle/api/err_cast.cocci
SmPL 스크립트의 다음 부분이 실행됩니다.
<smpl>
@r depends on !context && !patch && (org || report)@
expression x;
position p;
@@
ERR_PTR@p(PTR_ERR(x))
@script:python depends on org@
p << r.p;
x << r.x;
@@
msg="ERR_CAST can be used with %s" % (x)
msg_safe=msg.replace("[","@(").replace("]",")")
coccilib.org.print_todo(p[0], msg_safe)
</smpl>
이 SmPL 발췌문은 아래와 같이 standard output에 Org 항목을 생성합니다.
* TODO [[view:/home/user/linux/crypto/ctr.c::face=ovl-face1::linb=188::colb=9::cole=16][ERR_CAST can be used with alg]]
* TODO [[view:/home/user/linux/crypto/authenc.c::face=ovl-face1::linb=619::colb=9::cole=16][ERR_CAST can be used with auth]]
* TODO [[view:/home/user/linux/crypto/xts.c::face=ovl-face1::linb=227::colb=9::cole=16][ERR_CAST can be used with alg]]
요약과 해설
coccinelle.rst:1-511Coccinelle은 SmPL semantic patch로 커널 코드의 구조적 패턴을 찾아 보고하거나 일괄 변환합니다. 커널의 `make coccicheck` 프런트엔드는 `report`, `patch`, `context`, `org` mode와 COCCI, M, C, J 같은 변수를 조합해 검사 종류와 범위를 제어합니다.
정적 분석 결과에는 false positive가 있을 수 있으므로 생성된 보고서와 patch를 사람이 검토해야 합니다. 재현성과 성능을 위해 Coccinelle 버전, `.cocciconfig` 우선순위, SPFLAGS, index database 및 병렬 실행의 오류 반환도 함께 확인하는 것이 중요합니다.