为 C 代码覆盖率分析生成定义使用路径

Generating Define-Use Paths for C Code coverage analysis

如何为 C 代码生成未覆盖的定义使用路径(例如使用 gcc)。 正如我所看到的,这个主题只是学术性的。 (与线覆盖不同)

资源:http://whiteboxtest.com/Data-Flow-Testing.php

您需要一个工具来确定代码中的每个定义、所有可能的用途(例如,计算 Def-Use 对),将每个 Def-Use 对与定义的变量和程序位置(文件、 Def 和 Use 点的行、列)。

然后对于每个 def-use 对,您需要在记录该 def-use 对的使用的程序中添加检测 ("probes"),当它被使用时(通常接近使用),作为特定于该 def-use 对的某种布尔变量。 因为有很多这样的布尔值,所以将各个布尔值组织为布尔数组很有用。 (明显的优化以最小化插入的探针数量:一个基本块在执行时将满足许多 def-use 对;表示基本块执行的布尔值 [block coverage] 可以作为一组 def-use 对。我'我确定还有其他类似的优化。)。

在运行程序之后,必须转储这些布尔变量,计算实际的 def-use 信息(例如,包括使用块覆盖率数据),然后显示它。

用于修改程序以通过源到源程序转换来执行此操作的标准方案。我的论文 Branch Coverage for Arbitrary Languages Made Easy 展示了如何使用我们的 DMS 软件再工程工具包及其重写规则风格来做到这一点。本文侧重于分支(块)覆盖,但仪器方面很好。使用的典型转换规则如下所示:

rule mark_if_then_else(condition:expression; tstmt:statement; estmt:statement)=
   “if (\condition) \tstmt else \estmt;”
rewrites to
   “if (\condition)
       { visited[\new_place\(\tstmt\)]=1;
         \tstmt}
    else
       { visited[\new_place\(\estmt\)]=1;
         \estmt
       };” 

此规则修改 if-then-else 构造以收集 "visited" 每个有条件执行的块(then 和 else 子句)的布尔值,为每个新块生成一个新索引。 \xxxx 表示“语法类型为 ssss 的任意代码结构,如果转换规则签名(第一行)声明了 ssss: xxxx。您可以查看更多关于 DMS 重写规则的精确语法和含义的信息 here

事实证明获取 def-use 信息很难;您需要相当于编译器前端的东西,因此 OP 提到了 GCC。 GCC 不会进行源到源的转换,但是通过使用过程代码修改 GCC 源以添加探测器,您可以获得与 gcov 所做的源到二进制转换基本相同的效果。不过,一般来说,GCC 不想帮助您进行这种自定义检测。

我不知道,但我很确定 Clang 会计算 def-use 信息。可以使用 Clang 进行源到源转换,但我没有这方面的经验。

我知道我们的 DMS does compute def-use information 适用于 C 和 C++。这及其执行源到源转换的能力将使构建 def-use 覆盖工具在技术上变得简单。 (没有问,但是DMS也计算控制流,所以也可以直接做路径覆盖。)

然后就是搭建展示工具的问题了。您需要一些可以显示 def 使用对及其状态的东西,可能与代码上的 with/superimposed 相关联,因此很容易理解每​​个 def 和使用。因此,您需要记录有关每个 def 和 use 位置的行和列精确信息。我不认为你可以从 GCC 得到它;它在二进制文件中没有该信息,但可能在其构造的 AST 中有。您可以从 DMS 和 Clang 获取列信息(我认为)。