GCOV 交叉分析:__gcov_flush() 不会刷新共享库的覆盖率数据

utp*_*pal 4 code-coverage gcov

我正在尝试获取基于 ARM 的嵌入式系统的代码覆盖率。使用 x86 进行交叉编译。基本上,我有一个交叉分析问题。

对于我想要生成代码覆盖率数据的应用程序,我定义了一个信号处理程序,在其中调用__gcov_flush()将代码覆盖率数据刷新到 .gcda 文件。我正在向应用程序发送 SIGUSR1。该应用程序使用多个 .so 文件,其中实现了大部分代码和逻辑。

当我向进程发送信号时,只会创建/更新应用程序的 .gcda 文件。.so 的 .gcda 文件根本不会创建/更新。

有没有办法刷新__gcov_flush()应用程序正在使用的 .so 的所有覆盖数据?

我不想强迫应用程序这样做,exit()因为这会破坏我想要做的事情的目的。我需要能够转储应用程序及其在运行时使用的 .so 的覆盖率数据。请帮忙!!

使用 ARM GCC v4.5.1。

这是我迄今为止为生成代码覆盖率数据所做的工作:

我在主 makefile 中为 GCC 定义了以下选项: CFLAGS += -fprofile-arcs -ftest-coverage LDFLAGS += -fprofile-arcs -ftest-coverage

我还将GCOV_PREFIXGCOV_PREFIX_STRIP作为目标系统上的全局环境变量导出,以强制在特定路径中创建 .gcda 文件。这是有效的。

__gcov_flush()我唯一的问题是 .so 的 .gcda 文件在从应用程序调用时没有创建/更新。

小智 5

这个问题在 GCC 邮件列表上得到了解答。TLDR:需要在每个使用的共享库中添加一个处理程序,该处理程序将转储覆盖率数据。然后需要调用这些处理程序。

邮件列表中的详细答复如下。

来自邮件列表的问题

2015 年 6 月 19 日星期五,Utpal Patel 写道:

我正在尝试获取基于 ARM 的嵌入式系统的代码覆盖率。使用 x86 进行交叉编译。基本上,我有一个交叉分析问题。

对于我想要生成代码覆盖率数据的应用程序,我定义了一个信号处理程序,在其中调用 __gcov_flush() 将代码覆盖率数据刷新到 .gcda 文件。我正在向应用程序发送 SIGUSR1。该应用程序使用多个 .so 文件,其中实现了大部分代码和逻辑。

当我向进程发送信号时,只会创建/更新应用程序的 .gcda 文件。.so 的 .gcda 文件根本不会创建/更新。

有没有办法让 __gcov_flush() 刷新应用程序正在使用的 .so 的所有覆盖数据?

我不想强制应用程序退出(),因为这会破坏我想要做的事情的目的。我需要能够转储应用程序及其在运行时使用的 .so 的覆盖率数据。请帮忙!!

来自邮件列表的答复

当您编译应用程序时,-fprofile-arcs -ftest-coverage 仅对应用程序进行了检测(概念上,应用程序最小生成树的每个基本块中都有一个 64 位计数器),这些计数器就是__gcov_flush()转储的内容。

因此,如果您想从库中分析信息,则需要编译库以进行分析,因为 gcov 是一种静态工具,如果没有.so像您的应用程序一样编译它以进行分析,则无法从 a 中获取信息。如果应用程序是为了分析而编译的,那么当您调用时,它的数据将被转储 __gcov_flush(),但由于您无法向库发送信号来调用某些处理程序,因此您需要在库中安装一些其他机制,例如强力放置一个

int libdump(void) {
        __gcov_flush();                                                         
}
Run Code Online (Sandbox Code Playgroud)

进入库并从应用程序信号处理程序中调用它,就像您__gcov_flush();现在调用的那样。

这是来自一个简单的库,它只提供一个 open 调用,它是 libc open 和 libdump 函数的包装器

    2:   77:int libdump(void) {
    2:   78:        __gcov_flush();
    1:   79:        return 0;
    -:   80:}
    -:   81:/* we now can get code coverage of the library */
  145:   82:int open(const char *pathname, int flags, mode_t mode) {
  145:   83:        return __open(pathname, flags, mode);
    -:   84:}
Run Code Online (Sandbox Code Playgroud)

该库是用

gcc -fPIC -Wall -g -O2 -fprofile-arcs -ftest-coverage -shared -o libgctest.so.0 libgc.c 
Run Code Online (Sandbox Code Playgroud)

应用程序libdump()在信号处理程序中有

int libdump(void);

void gc_handler(int signum)
{
        printf("received signal\n");
        __gcov_flush(); /* dump coverage data on receiving SIGUSR1 */
        libdump();      /* and dump library converage data */
}
Run Code Online (Sandbox Code Playgroud)

并编译为

gcc -O2 -fprofile-arcs -ftest-coverage hello.c -o hello -lgctest
 `kill -10 <PIDOF application>` will now dump the gcda of both application and library.
Run Code Online (Sandbox Code Playgroud)

HTH霍夫拉特

ps: 我不知道为什么 libhandler 中 return 0 行的计数也不是 2....