593 lines
16 KiB
ReStructuredText
593 lines
16 KiB
ReStructuredText
.. _coccinelle:
|
|
|
|
..
|
|
Copyright 2010 Nicolas Palix <npalix@diku.dk>
|
|
Copyright 2010 Julia Lawall <julia.lawall@lip6.fr>
|
|
Copyright 2010 Gilles Muller <Gilles.Muller@lip6.fr>
|
|
|
|
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.
|
|
|
|
.. note::
|
|
Linux and macOS development environments are supported, but not Windows.
|
|
|
|
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. :
|
|
|
|
.. hlist::
|
|
|
|
* 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:
|
|
|
|
.. code-block:: console
|
|
|
|
./autogen
|
|
./configure
|
|
make
|
|
|
|
as a regular user, and install it with:
|
|
|
|
.. code-block:: console
|
|
|
|
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 Semantic Patch Language(SmPL) grammar documentation refer to:
|
|
|
|
http://coccinelle.lip6.fr/documentation.php
|
|
|
|
Using Coccinelle on Zephyr
|
|
**************************
|
|
|
|
``coccicheck`` checker is the front-end to the Coccinelle infrastructure
|
|
and has various modes:
|
|
|
|
Four basic modes are defined: ``patch``, ``report``, ``context``, and
|
|
``org``. The mode to use is specified by setting ``--mode=<mode>`` or
|
|
``-m=<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:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --mode=report
|
|
|
|
To produce patches, run:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --mode=patch
|
|
|
|
The ``coccicheck`` target applies every semantic patch available in the
|
|
sub-directories of ``scripts/coccinelle`` to the entire source code tree.
|
|
|
|
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 any static code analyzer, Coccinelle produces false
|
|
positives. Thus, reports must be carefully checked, and patches reviewed.
|
|
|
|
To enable verbose messages set ``--verbose=1`` option, for example:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --mode=report --verbose=1
|
|
|
|
Coccinelle parallelization
|
|
**************************
|
|
|
|
By default, ``coccicheck`` tries to run as parallel as possible. To change
|
|
the parallelism, set the ``--jobs=<number>`` option. For example, to run
|
|
across 4 CPUs:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --mode=report --jobs=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, the return value of the ``coccicheck``
|
|
command captures this return value.
|
|
|
|
Using Coccinelle with a single semantic patch
|
|
*********************************************
|
|
|
|
The option ``--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:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --mode=report --cocci=<example.cocci>
|
|
|
|
or:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --mode=report --cocci=./path/to/<example.cocci>
|
|
|
|
|
|
Controlling which files are processed by Coccinelle
|
|
***************************************************
|
|
|
|
By default the entire source tree is checked.
|
|
|
|
To apply Coccinelle to a specific directory, pass the path of specific
|
|
directory as an argument.
|
|
|
|
For example, to check ``drivers/usb/`` one may write:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --mode=patch drivers/usb/
|
|
|
|
The ``report`` mode is the default. You can select another one with the
|
|
``--mode=<mode>`` option 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 verbose option, 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.err`` option to ``coccicheck``. For
|
|
instance:
|
|
|
|
.. code-block:: console
|
|
|
|
rm -f cocci.err
|
|
./scripts/coccicheck --mode=patch --debug=cocci.err
|
|
cat cocci.err
|
|
|
|
Debugging support is only supported when using Coccinelle >= 1.0.2.
|
|
|
|
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.
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --sp-flag="--use-glimpse"
|
|
|
|
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:
|
|
|
|
.. code-block:: console
|
|
|
|
mkid -i C --output .id-utils.index
|
|
|
|
If you have another database filename you can also just symlink with this
|
|
name.
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --sp-flag="--use-idutils"
|
|
|
|
Alternatively you can specify the database filename explicitly, for
|
|
instance:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --sp-flag="--use-idutils /full-path/to/ID"
|
|
|
|
Sometimes coccinelle doesn't recognize or parse complex macro variables
|
|
due to insufficient definition. Therefore, to make it parsable we
|
|
explicitly provide the prototype of the complex macro using the
|
|
``---macro-file-builtins <headerfile.h>`` flag.
|
|
|
|
The ``<headerfile.h>`` should contain the complete prototype of
|
|
the complex macro from which spatch engine can extract the type
|
|
information required during transformation.
|
|
|
|
For example:
|
|
|
|
``Z_SYSCALL_HANDLER`` is not recognized by coccinelle. Therefore, we
|
|
put its prototype in a header file, say for example ``mymacros.h``.
|
|
|
|
.. code-block:: console
|
|
|
|
$ cat mymacros.h
|
|
#define Z_SYSCALL_HANDLER int xxx
|
|
|
|
Now we pass the header file ``mymacros.h`` during transformation:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --sp-flag="---macro-file-builtins mymacros.h"
|
|
|
|
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:
|
|
|
|
.. code-block:: console
|
|
|
|
// Options: --no-includes --include-headers
|
|
|
|
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/``.
|
|
|
|
The cocci script should have the following properties:
|
|
|
|
* The script **must** have ``report`` mode.
|
|
|
|
* The first few lines should state the purpose of the script
|
|
using ``///`` comments . Usually, this message would be used as the
|
|
commit log when proposing a patch based on the script.
|
|
|
|
Example
|
|
=======
|
|
|
|
.. code-block:: console
|
|
|
|
/// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element
|
|
|
|
* A more detailed information about the script with exceptional cases
|
|
or false positives (if any) can be listed using ``//#`` comments.
|
|
|
|
Example
|
|
=======
|
|
|
|
.. code-block:: console
|
|
|
|
//# This makes an effort to find cases where ARRAY_SIZE can be used such as
|
|
//# where there is a division of sizeof the array by the sizeof its first
|
|
//# element or by any indexed element or the element type. It replaces the
|
|
//# division of the two sizeofs by ARRAY_SIZE.
|
|
|
|
* Confidence: It is a property defined to specify the accuracy level of
|
|
the script. It can be either ``High``, ``Moderate`` or ``Low`` depending
|
|
upon the number of false positives observed.
|
|
|
|
Example
|
|
=======
|
|
|
|
.. code-block:: console
|
|
|
|
// Confidence: High
|
|
|
|
* Virtual rules: These are required to support the various modes framed
|
|
in the script. The virtual rule specified in the script should have
|
|
the corresponding mode handling rule.
|
|
|
|
Example
|
|
=======
|
|
|
|
.. code-block:: console
|
|
|
|
virtual context
|
|
|
|
@depends on context@
|
|
type T;
|
|
T[] E;
|
|
@@
|
|
(
|
|
* (sizeof(E)/sizeof(*E))
|
|
|
|
|
* (sizeof(E)/sizeof(E[...]))
|
|
|
|
|
* (sizeof(E)/sizeof(T))
|
|
)
|
|
|
|
Detailed description of the ``report`` mode
|
|
*******************************************
|
|
|
|
``report`` generates a list in the following format:
|
|
|
|
.. code-block:: console
|
|
|
|
file:line:column-column: message
|
|
|
|
Example
|
|
=======
|
|
|
|
Running:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --mode=report --cocci=scripts/coccinelle/array_size.cocci
|
|
|
|
will execute the following part of the SmPL script:
|
|
|
|
.. code-block:: console
|
|
|
|
<smpl>
|
|
|
|
@r depends on (org || report)@
|
|
type T;
|
|
T[] E;
|
|
position p;
|
|
@@
|
|
(
|
|
(sizeof(E)@p /sizeof(*E))
|
|
|
|
|
(sizeof(E)@p /sizeof(E[...]))
|
|
|
|
|
(sizeof(E)@p /sizeof(T))
|
|
)
|
|
|
|
@script:python depends on report@
|
|
p << r.p;
|
|
@@
|
|
|
|
msg="WARNING: Use ARRAY_SIZE"
|
|
coccilib.report.print_report(p[0], msg)
|
|
|
|
</smpl>
|
|
|
|
This SmPL excerpt generates entries on the standard output, as
|
|
illustrated below:
|
|
|
|
.. code-block:: console
|
|
|
|
ext/hal/nxp/mcux/drivers/lpc/fsl_wwdt.c:66:49-50: WARNING: Use ARRAY_SIZE
|
|
ext/hal/nxp/mcux/drivers/lpc/fsl_ctimer.c:74:53-54: WARNING: Use ARRAY_SIZE
|
|
ext/hal/nxp/mcux/drivers/imx/fsl_dcp.c:944:45-46: WARNING: Use ARRAY_SIZE
|
|
|
|
|
|
Detailed description of the ``patch`` mode
|
|
******************************************
|
|
|
|
When the ``patch`` mode is available, it proposes a fix for each problem
|
|
identified.
|
|
|
|
Example
|
|
=======
|
|
|
|
Running:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --mode=patch --cocci=scripts/coccinelle/misc/array_size.cocci
|
|
|
|
will execute the following part of the SmPL script:
|
|
|
|
.. code-block:: console
|
|
|
|
<smpl>
|
|
|
|
@depends on patch@
|
|
type T;
|
|
T[] E;
|
|
@@
|
|
(
|
|
- (sizeof(E)/sizeof(*E))
|
|
+ ARRAY_SIZE(E)
|
|
|
|
|
- (sizeof(E)/sizeof(E[...]))
|
|
+ ARRAY_SIZE(E)
|
|
|
|
|
- (sizeof(E)/sizeof(T))
|
|
+ ARRAY_SIZE(E)
|
|
)
|
|
|
|
</smpl>
|
|
|
|
This SmPL excerpt generates patch hunks on the standard output, as
|
|
illustrated below:
|
|
|
|
.. code-block:: console
|
|
|
|
diff -u -p a/ext/lib/encoding/tinycbor/src/cborvalidation.c b/ext/lib/encoding/tinycbor/src/cborvalidation.c
|
|
--- a/ext/lib/encoding/tinycbor/src/cborvalidation.c
|
|
+++ b/ext/lib/encoding/tinycbor/src/cborvalidation.c
|
|
@@ -325,7 +325,7 @@ static inline CborError validate_number(
|
|
static inline CborError validate_tag(CborValue *it, CborTag tag, int flags, int recursionLeft)
|
|
{
|
|
CborType type = cbor_value_get_type(it);
|
|
- const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]);
|
|
+ const size_t knownTagCount = ARRAY_SIZE(knownTagData);
|
|
const struct KnownTagData *tagData = knownTagData;
|
|
const struct KnownTagData * const knownTagDataEnd = knownTagData + knownTagCount;
|
|
|
|
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:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --mode=context --cocci=scripts/coccinelle/array_size.cocci
|
|
|
|
will execute the following part of the SmPL script:
|
|
|
|
.. code-block:: console
|
|
|
|
<smpl>
|
|
|
|
@depends on context@
|
|
type T;
|
|
T[] E;
|
|
@@
|
|
(
|
|
* (sizeof(E)/sizeof(*E))
|
|
|
|
|
* (sizeof(E)/sizeof(E[...]))
|
|
|
|
|
* (sizeof(E)/sizeof(T))
|
|
)
|
|
|
|
</smpl>
|
|
|
|
This SmPL excerpt generates diff hunks on the standard output, as
|
|
illustrated below:
|
|
|
|
.. code-block:: console
|
|
|
|
diff -u -p ext/lib/encoding/tinycbor/src/cborvalidation.c /tmp/nothing/ext/lib/encoding/tinycbor/src/cborvalidation.c
|
|
--- ext/lib/encoding/tinycbor/src/cborvalidation.c
|
|
+++ /tmp/nothing/ext/lib/encoding/tinycbor/src/cborvalidation.c
|
|
@@ -325,7 +325,6 @@ static inline CborError validate_number(
|
|
static inline CborError validate_tag(CborValue *it, CborTag tag, int flags, int recursionLeft)
|
|
{
|
|
CborType type = cbor_value_get_type(it);
|
|
- const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]);
|
|
const struct KnownTagData *tagData = knownTagData;
|
|
const struct KnownTagData * const knownTagDataEnd = knownTagData + knownTagCount;
|
|
|
|
Detailed description of the ``org`` mode
|
|
****************************************
|
|
|
|
``org`` generates a report in the Org mode format of Emacs.
|
|
|
|
Example
|
|
=======
|
|
|
|
Running:
|
|
|
|
.. code-block:: console
|
|
|
|
./scripts/coccicheck --mode=org --cocci=scripts/coccinelle/misc/array_size.cocci
|
|
|
|
will execute the following part of the SmPL script:
|
|
|
|
.. code-block:: console
|
|
|
|
<smpl>
|
|
|
|
@r depends on (org || report)@
|
|
type T;
|
|
T[] E;
|
|
position p;
|
|
@@
|
|
(
|
|
(sizeof(E)@p /sizeof(*E))
|
|
|
|
|
(sizeof(E)@p /sizeof(E[...]))
|
|
|
|
|
(sizeof(E)@p /sizeof(T))
|
|
)
|
|
|
|
@script:python depends on org@
|
|
p << r.p;
|
|
@@
|
|
coccilib.org.print_todo(p[0], "WARNING should use ARRAY_SIZE")
|
|
|
|
</smpl>
|
|
|
|
This SmPL excerpt generates Org entries on the standard output, as
|
|
illustrated below:
|
|
|
|
.. code-block:: console
|
|
|
|
* TODO [[view:ext/lib/encoding/tinycbor/src/cborvalidation.c::face=ovl-face1::linb=328::colb=52::cole=53][WARNING should use ARRAY_SIZE]]
|
|
|
|
Coccinelle Mailing List
|
|
***********************
|
|
|
|
Subscribe to the coccinelle mailing list:
|
|
|
|
* https://systeme.lip6.fr/mailman/listinfo/cocci
|
|
|
|
Archives:
|
|
|
|
* https://lore.kernel.org/cocci/
|
|
* https://systeme.lip6.fr/pipermail/cocci/
|