1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
|
=====================================
Cross Translation Unit (CTU) Analysis
=====================================
Normally, static analysis works in the boundary of one translation unit (TU).
However, with additional steps and configuration we can enable the analysis to inline the definition of a function from
another TU.
.. contents::
:local:
Overview
________
CTU analysis can be used in a variety of ways. The importing of external TU definitions can work with pre-dumped PCH
files or generating the necessary AST structure on-demand, during the analysis of the main TU. Driving the static
analysis can also be implemented in multiple ways. The most direct way is to specify the necessary commandline options
of the Clang frontend manually (and generate the prerequisite dependencies of the specific import method by hand). This
process can be automated by other tools, like `CodeChecker <https://github.com/Ericsson/codechecker>`_ and scan-build-py
(preference for the former).
PCH-based analysis
__________________
The analysis needs the PCH dumps of all the translations units used in the project.
These can be generated by the Clang Frontend itself, and must be arranged in a specific way in the filesystem.
The index, which maps symbols' USR names to PCH dumps containing them must also be generated by the
`clang-extdef-mapping`. Entries in the index *must* have an `.ast` suffix if the goal
is to use PCH-based analysis, as the lack of that extension signals that the entry is to be used as a source-file, and parsed on-demand.
This tool uses a :doc:`compilation database <../../JSONCompilationDatabase>` to
determine the compilation flags used.
The analysis invocation must be provided with the directory which contains the dumps and the mapping files.
Manual CTU Analysis
###################
Let's consider these source files in our minimal example:
.. code-block:: cpp
// main.cpp
int foo();
int main() {
return 3 / foo();
}
.. code-block:: cpp
// foo.cpp
int foo() {
return 0;
}
And a compilation database:
.. code-block:: bash
[
{
"directory": "/path/to/your/project",
"command": "clang++ -c foo.cpp -o foo.o",
"file": "foo.cpp"
},
{
"directory": "/path/to/your/project",
"command": "clang++ -c main.cpp -o main.o",
"file": "main.cpp"
}
]
We'd like to analyze `main.cpp` and discover the division by zero bug.
In order to be able to inline the definition of `foo` from `foo.cpp` first we have to generate the `AST` (or `PCH`) file
of `foo.cpp`:
.. code-block:: bash
$ pwd $ /path/to/your/project
$ clang++ -emit-ast -o foo.cpp.ast foo.cpp
$ # Check that the .ast file is generated:
$ ls
compile_commands.json foo.cpp.ast foo.cpp main.cpp
$
The next step is to create a CTU index file which holds the `USR` name and location of external definitions in the
source files:
.. code-block:: bash
$ clang-extdef-mapping -p . foo.cpp
c:@F@foo# /path/to/your/project/foo.cpp
$ clang-extdef-mapping -p . foo.cpp > externalDefMap.txt
We have to modify `externalDefMap.txt` to contain the name of the `.ast` files instead of the source files:
.. code-block:: bash
$ sed -i -e "s/.cpp/.cpp.ast/g" externalDefMap.txt
We still have to further modify the `externalDefMap.txt` file to contain relative paths:
.. code-block:: bash
$ sed -i -e "s|$(pwd)/||g" externalDefMap.txt
Now everything is available for the CTU analysis.
We have to feed Clang with CTU specific extra arguments:
.. code-block:: bash
$ pwd
/path/to/your/project
$ clang++ --analyze \
-Xclang -analyzer-config -Xclang experimental-enable-naive-ctu-analysis=true \
-Xclang -analyzer-config -Xclang ctu-dir=. \
-Xclang -analyzer-output=plist-multi-file \
main.cpp
main.cpp:5:12: warning: Division by zero
return 3 / foo();
~~^~~~~~~
1 warning generated.
$ # The plist file with the result is generated.
$ ls -F
compile_commands.json externalDefMap.txt foo.ast foo.cpp foo.cpp.ast main.cpp main.plist
$
This manual procedure is error-prone and not scalable, therefore to analyze real projects it is recommended to use
`CodeChecker` or `scan-build-py`.
Automated CTU Analysis with CodeChecker
#######################################
The `CodeChecker <https://github.com/Ericsson/codechecker>`_ project fully supports automated CTU analysis with Clang.
Once we have set up the `PATH` environment variable and we activated the python `venv` then it is all it takes:
.. code-block:: bash
$ CodeChecker analyze --ctu compile_commands.json -o reports
$ ls -F
compile_commands.json foo.cpp foo.cpp.ast main.cpp reports/
$ tree reports
reports
├── compile_cmd.json
├── compiler_info.json
├── foo.cpp_53f6fbf7ab7ec9931301524b551959e2.plist
├── main.cpp_23db3d8df52ff0812e6e5a03071c8337.plist
├── metadata.json
└── unique_compile_commands.json
0 directories, 6 files
$
The `plist` files contain the results of the analysis, which may be viewed with the regular analysis tools.
E.g. one may use `CodeChecker parse` to view the results in command line:
.. code-block:: bash
$ CodeChecker parse reports
[HIGH] /home/egbomrt/ctu_mini_raw_project/main.cpp:5:12: Division by zero [core.DivideZero]
return 3 / foo();
^
Found 1 defect(s) in main.cpp
----==== Summary ====----
-----------------------
Filename | Report count
-----------------------
main.cpp | 1
-----------------------
-----------------------
Severity | Report count
-----------------------
HIGH | 1
-----------------------
----=================----
Total number of reports: 1
----=================----
Or we can use `CodeChecker parse -e html` to export the results into HTML format:
.. code-block:: bash
$ CodeChecker parse -e html -o html_out reports
$ firefox html_out/index.html
Automated CTU Analysis with scan-build-py (don't do it)
#############################################################
We actively develop CTU with CodeChecker as the driver for this feature, `scan-build-py` is not actively developed for CTU.
`scan-build-py` has various errors and issues, expect it to work only with the very basic projects only.
Example usage of scan-build-py:
.. code-block:: bash
$ /your/path/to/llvm-project/clang/tools/scan-build-py/bin/analyze-build --ctu
analyze-build: Run 'scan-view /tmp/scan-build-2019-07-17-17-53-33-810365-7fqgWk' to examine bug reports.
$ /your/path/to/llvm-project/clang/tools/scan-view/bin/scan-view /tmp/scan-build-2019-07-17-17-53-33-810365-7fqgWk
Starting scan-view at: http://127.0.0.1:8181
Use Ctrl-C to exit.
[6336:6431:0717/175357.633914:ERROR:browser_process_sub_thread.cc(209)] Waited 5 ms for network service
Opening in existing browser session.
^C
$
.. _ctu-on-demand:
On-demand analysis
__________________
The analysis produces the necessary AST structure of external TUs during analysis. This requires the
exact compiler invocations for each TU, which can be generated by hand, or by tools driving the analyzer.
The compiler invocation is a shell command that could be used to compile the TU-s main source file.
The mapping from absolute source file paths of a TU to lists of compilation command segments used to
compile said TU are given in YAML format referred to as `invocation list`, and must be passed as an
analyer-config argument.
The index, which maps function USR names to source files containing them must also be generated by the
`clang-extdef-mapping`. Entries in the index must *not* have an `.ast` suffix if the goal
is to use On-demand analysis, as that extension signals that the entry is to be used as an PCH-dump.
The mapping of external definitions implicitly uses a
:doc:`compilation database <../../JSONCompilationDatabase>` to determine the compilation flags used.
The analysis invocation must be provided with the directory which contains the mapping
files, and the `invocation list` which is used to determine compiler flags.
Manual CTU Analysis
###################
Let's consider these source files in our minimal example:
.. code-block:: cpp
// main.cpp
int foo();
int main() {
return 3 / foo();
}
.. code-block:: cpp
// foo.cpp
int foo() {
return 0;
}
The compilation database:
.. code-block:: bash
[
{
"directory": "/path/to/your/project",
"command": "clang++ -c foo.cpp -o foo.o",
"file": "foo.cpp"
},
{
"directory": "/path/to/your/project",
"command": "clang++ -c main.cpp -o main.o",
"file": "main.cpp"
}
]
The `invocation list`:
.. code-block:: bash
"/path/to/your/project/foo.cpp":
- "clang++"
- "-c"
- "/path/to/your/project/foo.cpp"
- "-o"
- "/path/to/your/project/foo.o"
"/path/to/your/project/main.cpp":
- "clang++"
- "-c"
- "/path/to/your/project/main.cpp"
- "-o"
- "/path/to/your/project/main.o"
We'd like to analyze `main.cpp` and discover the division by zero bug.
As we are using On-demand mode, we only need to create a CTU index file which holds the `USR` name and location of
external definitions in the source files:
.. code-block:: bash
$ clang-extdef-mapping -p . foo.cpp
c:@F@foo# /path/to/your/project/foo.cpp
$ clang-extdef-mapping -p . foo.cpp > externalDefMap.txt
Now everything is available for the CTU analysis.
We have to feed Clang with CTU specific extra arguments:
.. code-block:: bash
$ pwd
/path/to/your/project
$ clang++ --analyze \
-Xclang -analyzer-config -Xclang experimental-enable-naive-ctu-analysis=true \
-Xclang -analyzer-config -Xclang ctu-dir=. \
-Xclang -analyzer-config -Xclang ctu-invocation-list=invocations.yaml \
-Xclang -analyzer-output=plist-multi-file \
main.cpp
main.cpp:5:12: warning: Division by zero
return 3 / foo();
~~^~~~~~~
1 warning generated.
$ # The plist file with the result is generated.
$ ls -F
compile_commands.json externalDefMap.txt foo.cpp main.cpp main.plist
$
This manual procedure is error-prone and not scalable, therefore to analyze real projects it is recommended to use
`CodeChecker` or `scan-build-py`.
Automated CTU Analysis with CodeChecker
#######################################
The `CodeChecker <https://github.com/Ericsson/codechecker>`_ project fully supports automated CTU analysis with Clang.
Once we have set up the `PATH` environment variable and we activated the python `venv` then it is all it takes:
.. code-block:: bash
$ CodeChecker analyze --ctu --ctu-ast-loading-mode on-demand compile_commands.json -o reports
$ ls -F
compile_commands.json foo.cpp main.cpp reports/
$ tree reports
reports
├── compile_cmd.json
├── compiler_info.json
├── foo.cpp_53f6fbf7ab7ec9931301524b551959e2.plist
├── main.cpp_23db3d8df52ff0812e6e5a03071c8337.plist
├── metadata.json
└── unique_compile_commands.json
0 directories, 6 files
$
The `plist` files contain the results of the analysis, which may be viewed with the regular analysis tools.
E.g. one may use `CodeChecker parse` to view the results in command line:
.. code-block:: bash
$ CodeChecker parse reports
[HIGH] /home/egbomrt/ctu_mini_raw_project/main.cpp:5:12: Division by zero [core.DivideZero]
return 3 / foo();
^
Found 1 defect(s) in main.cpp
----==== Summary ====----
-----------------------
Filename | Report count
-----------------------
main.cpp | 1
-----------------------
-----------------------
Severity | Report count
-----------------------
HIGH | 1
-----------------------
----=================----
Total number of reports: 1
----=================----
Or we can use `CodeChecker parse -e html` to export the results into HTML format:
.. code-block:: bash
$ CodeChecker parse -e html -o html_out reports
$ firefox html_out/index.html
Automated CTU Analysis with scan-build-py (don't do it)
#######################################################
We actively develop CTU with CodeChecker as the driver for feature, `scan-build-py` is not actively developed for CTU.
`scan-build-py` has various errors and issues, expect it to work only with the very basic projects only.
Currently On-demand analysis is not supported with `scan-build-py`.
|