LibFuzzer使用的覆盖率统计工具为Source-based Code Coverage。
另外两个clang实现的覆盖率统计实现:

  • SanitizerCoverage: 低开销的工具。可以提供边级别的覆盖率统计;
  • gcov: gcc兼容的覆盖率统计实现,基于DebugInfo。-ftest-coverage--coverage

workflow

  • 编译附带覆盖率信息
  • 运行插桩程序
  • 创建覆盖率报告
    后面以下面的代码为例:
    ShowLineNumbers
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    % cat <<EOF > foo.cc
    #define BAR(x) ((x) || (x))
    template <typename T> void foo(T x) {
    for (unsigned I = 0; I < 10; ++I) { BAR(I); }
    }
    int main() {
    foo<int>(0);
    foo<float>(0);
    return 0;
    }
    EOF

添加覆盖率配置

加入-fprofile-instr-generate -fcoverage-mapping参数:

1
2
# Step 1: Compile with coverage enabled
% clang++ -fprofile-instr-generate -fcoverage-mapping foo.cc -o foo

可以将未加入覆盖率信息插桩的代码与加入的相互链接,只不过未插桩的不会计入覆盖率信息。
可以加入-coverage-mcdc参数来添加Modified Condition/Decision Coverage(MC/DC)覆盖率统计方法。

运行插桩程序

运行插桩程序,程序退出后会保存raw profile到环境变量LLVM_PROFILE_FILE目录下,默认保存到default.profraw文件。

查看覆盖率报告

1
2
Step 3(a): Index the raw profile.
$ llvm-profdata merge -sparse foo.profraw -o foo.profdata
showLineNumbers
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
❯ llvm-cov show ./foo -instr-profile=foo.profdata
1| |/*************************************************************************
2| | > File Name: foo.cc
3| | > Author: eutopia
4| | > Mail: 2715417602@qq.com
5| | > Created Time: Mon Aug 4 17:24:37 2025
6| | ************************************************************************/
7| |
8| 20|#define BAR(x) ((x) || (x))
9| 2|template <typename T> void foo(T x) {
10| 22| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
11| 2|}
------------------
| _Z3fooIiEvT_:
| 9| 1|template <typename T> void foo(T x) {
| 10| 11| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
| 11| 1|}
------------------
| _Z3fooIfEvT_:
| 9| 1|template <typename T> void foo(T x) {
| 10| 11| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
| 11| 1|}
------------------
12| 1|int main() {
13| 1| foo<int>(0);
14| 1| foo<float>(0);
15| 1| return 0;
16| 1|}

查看报告:

1
2
3
4
5
6
❯ llvm-cov report ./foo --instr-profile=foo.profdata
Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover Branches Missed Branches Cover
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/home/bronya/test/coverage/foo.cc 8 0 100.00% 2 0 100.00% 8 0 100.00% 6 1 83.33%
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL 8 0 100.00% 2 0 100.00% 8 0 100.00% 6 1 83.33%

后面的不太重要,暂时先不写了,可以阅读源链接
注:
SanitizerCoverage中关于边(Edge Coverage)的解释

参考链接

https://clang.llvm.org/docs/SourceBasedCodeCoverage.html