最近和同事看一个问题,就是虽然将所需的选项--coverage加到了产品的编译环境里,但是还是没有生成所希望的文件。而且自己写小程序来验证这个选项,也是没问题,可以产生程序运行时的代码覆盖率统计文件。如下:
[-rwxr-xr-x. 1 root root 33K Dec 23 12:35 a.out-rw-r--r--. 1 root root 256 Dec 23 12:35 else.gcda //the fileroot@10 test]# gcov elseFile 'else.c'Lines executed:75.00% of 8Creating 'else.c.gcov'
那问题出现到了哪里呢?后来同事经过查看一个链接脚本的更改记录,发现是链接脚本里的改动影响了这个行为。
那接下来就是要看到底是什么样的改动影响了这个行为。最终一步一步的发现是因为,在链接init_array/fini_array段的时候,默认链接脚本是使用如下的脚本,做链接:
.init_array :{PROVIDE_HIDDEN(__init_array_start = .);KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))KEEP(*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))PROVIDE_HIDDEN(__init_array_end = .);}.fini_array :{PROVIDE_HIDDEN(__fini_array_start = .);KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))KEEP(*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))PROVIDE_HIDDEN(__fini_array_end = .);}
而产品里的是:
.init_array : { KEEP (*(.init_array)) }
这两的主要区别就是少了.init_array后面的通配符。这样就可以理解了,因为--coverage是将默认编译的初始化/dump文件的函数都是放到了这个段<.fini_array.00100>:
0000000010000b4f <_GLOBAL__sub_D_00100_1_a>:10000b4f: 55push %rbp10000b50: 4889 e5 mov %rsp,%rbp10000b53: e8 98200000 callq 10002bf0 <__gcov_exit>10000b58: 5d pop %rbp10000b59: c3 retq10000b5a: 66 0f 1f 440000 nopw 0x0(%rax,%rax,1)0000000010105188 <.fini_array.00100>:10105188: 4f 0b 00 rex.WRXB or (%r8),%r81010518b: 1000 adc %al,(%rax)1010518d: 0000 add %al,(%rax) ...
最终导致文件产生不了。