CrossTranslationUnit.rst 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. =====================================
  2. Cross Translation Unit (CTU) Analysis
  3. =====================================
  4. Normally, static analysis works in the boundary of one translation unit (TU).
  5. However, with additional steps and configuration we can enable the analysis to inline the definition of a function from another TU.
  6. .. contents::
  7. :local:
  8. Manual CTU Analysis
  9. -------------------
  10. Let's consider these source files in our minimal example:
  11. .. code-block:: cpp
  12. // main.cpp
  13. int foo();
  14. int main() {
  15. return 3 / foo();
  16. }
  17. .. code-block:: cpp
  18. // foo.cpp
  19. int foo() {
  20. return 0;
  21. }
  22. And a compilation database:
  23. .. code-block:: bash
  24. [
  25. {
  26. "directory": "/path/to/your/project",
  27. "command": "clang++ -c foo.cpp -o foo.o",
  28. "file": "foo.cpp"
  29. },
  30. {
  31. "directory": "/path/to/your/project",
  32. "command": "clang++ -c main.cpp -o main.o",
  33. "file": "main.cpp"
  34. }
  35. ]
  36. We'd like to analyze `main.cpp` and discover the division by zero bug.
  37. 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`:
  38. .. code-block:: bash
  39. $ pwd $ /path/to/your/project
  40. $ clang++ -emit-ast -o foo.cpp.ast foo.cpp
  41. $ # Check that the .ast file is generated:
  42. $ ls
  43. compile_commands.json foo.cpp.ast foo.cpp main.cpp
  44. $
  45. The next step is to create a CTU index file which holds the `USR` name and location of external definitions in the source files:
  46. .. code-block:: bash
  47. $ clang-extdef-mapping -p . foo.cpp
  48. c:@F@foo# /path/to/your/project/foo.cpp
  49. $ clang-extdef-mapping -p . foo.cpp > externalDefMap.txt
  50. We have to modify `externalDefMap.txt` to contain the name of the `.ast` files instead of the source files:
  51. .. code-block:: bash
  52. $ sed -i -e "s/.cpp/.cpp.ast/g" externalDefMap.txt
  53. We still have to further modify the `externalDefMap.txt` file to contain relative paths:
  54. .. code-block:: bash
  55. $ sed -i -e "s|$(pwd)/||g" externalDefMap.txt
  56. Now everything is available for the CTU analysis.
  57. We have to feed Clang with CTU specific extra arguments:
  58. .. code-block:: bash
  59. $ pwd
  60. /path/to/your/project
  61. $ 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
  62. main.cpp:5:12: warning: Division by zero
  63. return 3 / foo();
  64. ~~^~~~~~~
  65. 1 warning generated.
  66. $ # The plist file with the result is generated.
  67. $ ls
  68. compile_commands.json externalDefMap.txt foo.ast foo.cpp foo.cpp.ast main.cpp main.plist
  69. $
  70. This manual procedure is error-prone and not scalable, therefore to analyze real projects it is recommended to use `CodeChecker` or `scan-build-py`.
  71. Automated CTU Analysis with CodeChecker
  72. ---------------------------------------
  73. The `CodeChecker <https://github.com/Ericsson/codechecker>`_ project fully supports automated CTU analysis with Clang.
  74. Once we have set up the `PATH` environment variable and we activated the python `venv` then it is all it takes:
  75. .. code-block:: bash
  76. $ CodeChecker analyze --ctu compile_commands.json -o reports
  77. [INFO 2019-07-16 17:21] - Pre-analysis started.
  78. [INFO 2019-07-16 17:21] - Collecting data for ctu analysis.
  79. [INFO 2019-07-16 17:21] - [1/2] foo.cpp
  80. [INFO 2019-07-16 17:21] - [2/2] main.cpp
  81. [INFO 2019-07-16 17:21] - Pre-analysis finished.
  82. [INFO 2019-07-16 17:21] - Starting static analysis ...
  83. [INFO 2019-07-16 17:21] - [1/2] clangsa analyzed foo.cpp successfully.
  84. [INFO 2019-07-16 17:21] - [2/2] clangsa analyzed main.cpp successfully.
  85. [INFO 2019-07-16 17:21] - ----==== Summary ====----
  86. [INFO 2019-07-16 17:21] - Successfully analyzed
  87. [INFO 2019-07-16 17:21] - clangsa: 2
  88. [INFO 2019-07-16 17:21] - Total analyzed compilation commands: 2
  89. [INFO 2019-07-16 17:21] - ----=================----
  90. [INFO 2019-07-16 17:21] - Analysis finished.
  91. [INFO 2019-07-16 17:21] - To view results in the terminal use the "CodeChecker parse" command.
  92. [INFO 2019-07-16 17:21] - To store results use the "CodeChecker store" command.
  93. [INFO 2019-07-16 17:21] - See --help and the user guide for further options about parsing and storing the reports.
  94. [INFO 2019-07-16 17:21] - ----=================----
  95. [INFO 2019-07-16 17:21] - Analysis length: 0.659618854523 sec.
  96. $ ls
  97. compile_commands.json foo.cpp foo.cpp.ast main.cpp reports
  98. $ tree reports
  99. reports
  100. ├── compile_cmd.json
  101. ├── compiler_info.json
  102. ├── foo.cpp_53f6fbf7ab7ec9931301524b551959e2.plist
  103. ├── main.cpp_23db3d8df52ff0812e6e5a03071c8337.plist
  104. ├── metadata.json
  105. └── unique_compile_commands.json
  106. 0 directories, 6 files
  107. $
  108. The `plist` files contain the results of the analysis, which may be viewed with the regular analysis tools.
  109. E.g. one may use `CodeChecker parse` to view the results in command line:
  110. .. code-block:: bash
  111. $ CodeChecker parse reports
  112. [HIGH] /home/egbomrt/ctu_mini_raw_project/main.cpp:5:12: Division by zero [core.DivideZero]
  113. return 3 / foo();
  114. ^
  115. Found 1 defect(s) in main.cpp
  116. ----==== Summary ====----
  117. -----------------------
  118. Filename | Report count
  119. -----------------------
  120. main.cpp | 1
  121. -----------------------
  122. -----------------------
  123. Severity | Report count
  124. -----------------------
  125. HIGH | 1
  126. -----------------------
  127. ----=================----
  128. Total number of reports: 1
  129. ----=================----
  130. Or we can use `CodeChecker parse -e html` to export the results into HTML format:
  131. .. code-block:: bash
  132. $ CodeChecker parse -e html -o html_out reports
  133. $ firefox html_out/index.html
  134. Automated CTU Analysis with scan-build-py (don't do it)
  135. -------------------------------------------------------
  136. We actively develop CTU with CodeChecker as a "runner" script, `scan-build-py` is not actively developed for CTU.
  137. `scan-build-py` has various errors and issues, expect it to work with the very basic projects only.
  138. Example usage of scan-build-py:
  139. .. code-block:: bash
  140. $ /your/path/to/llvm-project/clang/tools/scan-build-py/bin/analyze-build --ctu
  141. analyze-build: Run 'scan-view /tmp/scan-build-2019-07-17-17-53-33-810365-7fqgWk' to examine bug reports.
  142. $ /your/path/to/llvm-project/clang/tools/scan-view/bin/scan-view /tmp/scan-build-2019-07-17-17-53-33-810365-7fqgWk
  143. Starting scan-view at: http://127.0.0.1:8181
  144. Use Ctrl-C to exit.
  145. [6336:6431:0717/175357.633914:ERROR:browser_process_sub_thread.cc(209)] Waited 5 ms for network service
  146. Opening in existing browser session.
  147. ^C
  148. $