Linux平台代码覆盖率测试-GCC如何编译生成gcov/gcov-dump程序及其bug分析

2014-11-24 09:02:03 · 作者: · 浏览: 1

Content


0.


1. 编译 gcov/gcov-dump


2. 额外的话


3. gcov-dump 程序的一个 bug


3.1 bug 描述


3.2 bug 分析与修复


3.3 正确的输出


3.4 gcov-dump 的打印开关


3.5 一个问题:上面红色的 0 是什么?谁打印出来的?


4. 总结




0.



某些版本的 Gcc 在默认情况下编译,可能不会产生 gcov-dump 程序,或者不会安装到 /usr/bin 。但 gcov-dump 程序在做覆盖率测试时 dump 相关文件 (.gcda/.gcno) 内容时非常必要和好用。



Gcc 的编译耗时又繁琐,如果某些配置不正确,会导致编译过程中各种莫名其妙的错误。因此,本文主要讲述在不重新编译整个 Gcc 项目的情况下,如何获得 gcov-dump 程序。



本文在 Linux 平台上实验,以 gcc-4.1.2 为例,且 gcc 源代码在 /usr/src/gcc-4.1.2 目录。以下若不做特别说明, . 表示 gcc 源代码目录,即 /usr/src/gcc-4.1.2



1. 编译 gcov/gcov-dump



Gcov-dump.c 位于 ./gcc 目录下,因此,可以通过 ./gcc makefile 文件编译生成 gcov-dump gcc 目录下 configure 程序即可生成该 makefile



makefile 文件中的 gcov-dump 如下,由 ./gcc/build 下的 Makefile 文件中抽取出来。


至于其他的定义,非本文重点,不予解释。


程序提示在 ../build-i686-pc-linux-gnu/libiberty 目录下没有找到 genmodes 所需的静态库 libiberty.a



makefile 文件中也了解到, gcov/gcov-dump 实际所需的静态库是 libcpp.a libiberty.a 。实际上,只需在 gcc 目录下的 makefile 文件中指定好这两个静态库的路径 ( 绝对路径和相对路径均可 ) 即可解决问题。例如: /usr/bin/libiberty.a



2. 额外的话



不得不指出的一点:事实上,对 libcpp.a 的依赖几乎为 0 ,且对 libiberty.a 的依赖也仅限于以下函数。


这两个函数的声明在 ./include/libiberty.h 中。



因此,了解这些之后,就可以将 gcov/gcov-dump 相关的文件抽取出来,单独成为一个独立的项目,来编译出 gcov/gcov-dump ,以方便对 gcov/gcov-dump 源代码和原理的学习、调试。


——将另文讨论。



3. gcov-dump 程序的一个 bug



3.1 bug 描述



用上述生成的 gcov-dump 程序 dump 出某个 .gcda 文件的内容,如下。



很显然,该文件里并没有这些庞大的数据,也就证实了我们的猜测。基本可以确定, gcov-dump bug



3.2 bug 分析与修复



如何分析,自然想到了 gdb 。有问题的数据貌似在 dump Object Summary Program Summary 时出现的。那么在 tag_summary () 函数中设置断点是很自然的事。经一番调试后,发现问题就在 tag_summary() 函数里。如下。


其中, GCOV_COUNTERS 的定义如下,其值为 5 ,故每次打印均打印出 5 summary 的内容。但实际应该是按照 summary(Object 或者 program) 的个数来打印信息。



输出的信息,如,


counts=5, runs=1, sum_all=12, run_max=10, sum_max=10


即为 gcov_ctr_summary 结构,其定义如下。在 ./gcc/gcov_io.h 文件中。



GCOV_COUNTERS_SUMMABLE =1 ,因此, gcov_summary 结构中的 ctrs 数组,实际上是一个指针而已,当 summary 有多个时 ( 不超过 5 ) ,应该为其分配空间。