你好,游客 登录 注册 搜索
背景:
阅读新闻

Linux平台代码覆盖率测试-编译过程自动化及对链接的解释

[日期:2011-05-27] 来源:csdn  作者:阿波ID:livelylittlefish [字体: ]

Content

0.

1. 生成各个文件的步骤

1.1 未加入覆盖率测试选项

1.1.1 编译步骤

1.1.2 目标文件的符号表

1.2 加入覆盖率测试选项

1.2.1 编译步骤

1.2.2 目标文件的符号表

1.3 gcc verbose选项

2. 编译自动化

2.1 使用collect2makefile

2.2 不使用collect2makefile

3. 关于链接的讨论

3.1 链接顺序讨论

3.2 错误链接顺序的例子

4. 额外的话

5. 小结

 

 

0.

 

"Linux平台代码覆盖率测试-GCC插桩前后汇编代码对比分析"一文中的编译过程能否自动化?能否使用makefile的方式进行?其链接过程使用ld或者collect2如何?

 

——这将是本文讨论的重点。本文gcc版本为gcc-4.1.2

 

1. 生成各个文件的步骤

 

1.1 未加入覆盖率测试选项

 

1.1.1 编译步骤

 

(1) 预处理:生成test.i文件

 

# cpp test.c -o test.i    //或者

# cpp test.c > test.i     //或者

# gcc -E test.c -o test.i

 

(2) 编译:生成test.s文件

 

# gcc -S test.i

 

(3) 汇编:生成test.o文件

 

# as -o test.o test.s     //或者

# gcc -c test.s -o test.o

 

(4) 链接:生成可执行文件test

 

# gcc -o test test.o

 

或者,

# /usr/libexec/gcc/i386-RedHat-linux/4.1.2/collect2 --eh-frame-hdr --build-id -m elf_i386 --hash-style=gnu -dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbegin.o -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2/../../.. -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i386-redhat-linux/4.1.2/crtend.o /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crtn.o test.o -o test

/usr/lib/gcc/i386-redhat-linux/4.1.2/../../..就是/usr/lib,因此,也可以简写为。

/usr/libexec/gcc/i386-redhat-linux/4.1.2/collect2 --eh-frame-hdr --build-id -m elf_i386 --hash-style=gnu -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbegin.o -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i386-redhat-linux/4.1.2/crtend.o /usr/lib/crtn.o test.o -o test

1.1.2 目标文件的符号表

 

可通过如下命令查看test.o中的符号表。//后是笔者加入的注释。

# objdump -t test.o

 

test.o:     file format elf32-i386

 

SYMBOL TABLE:

00000000 l    df *ABS*  00000000 test.c

00000000 l    d  .text  00000000 .text

00000000 l    d  .data  00000000 .data

00000000 l    d  .bss   00000000 .bss

00000000 l    d  .rodata        00000000 .rodata

00000000 l    d  .note.GNU-stack        00000000 .note.GNU-stack

00000000 l    d  .comment       00000000 .comment

00000000 g     F .text  0000005f main

00000000         *UND*  00000000 puts    //就是undefined,故需要连接其他的目标文件

 

# nm test.o

00000000 T main    //T即为text symbol,大写表示global

         U puts    //就是undefined,故需要连接其他的目标文件 


1.2 加入覆盖率测试选项

 

1.2.1 编译步骤

 

步骤同上,只是在编译生成test.s文件时加上"-fprofile-arcs -ftest-coverage"覆盖率测试选项即可。

 

另外,使用collect2的链接步骤稍有不同,需要链接gcov静态库(libgcov.a)。如下。

# /usr/libexec/gcc/i386-redhat-linux/4.1.2/collect2 --eh-frame-hdr --build-id -m elf_i386 --hash-style=gnu -dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbegin.o test.o -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2/../../.. -lgcov -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i386-redhat-linux/4.1.2/crtend.o /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crtn.o -o test

或者简写为。

/usr/libexec/gcc/i386-redhat-linux/4.1.2/collect2 --eh-frame-hdr --build-id -m elf_i386 --hash-style=gnu -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbegin.o test.o -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib -lgcov -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i386-redhat-linux/4.1.2/crtend.o /usr/lib/crtn.o -o test

当然,命令亦会完成链接并生成可执行文件。

# gcc -o test test.o -lgcov

 

libgcov.a位于/usr/lib/gcc/i386-redhat-linux/4.1.2目录。

 

1.2.2 目标文件的符号表

 

看看加入覆盖率测试选项后的目标文件test.o中的符号表。

# objdump -t test.o

 

test.o:     file format elf32-i386

 

SYMBOL TABLE:

00000000 l    df *ABS*  00000000 test.c

00000000 l    d  .text  00000000 .text

00000000 l    d  .data  00000000 .data

00000000 l    d  .bss   00000000 .bss

00000000 l    d  .rodata        00000000 .rodata

000000eb l     F .text  00000014 _GLOBAL__I_0_main

00000000 l    d  .ctors 00000000 .ctors

00000000 l    d  .note.GNU-stack        00000000 .note.GNU-stack

00000000 l    d  .comment       00000000 .comment

00000000 g     F .text  000000eb main

00000000         *UND*  00000000 puts              //就是undefined,故需要连接其他的目标文件,下同

00000000         *UND*  00000000 __gcov_merge_add

00000000         *UND*  00000000 __gcov_init

 

# nm test.o

000000eb t _GLOBAL__I_0_main    //t即为text symbol,小写表示local

         U __gcov_init          //就是undefined,故需要连接其他的目标文件,下同

         U __gcov_merge_add

00000000 T main

         U puts

1.3 gcc verbose选项

 

这是如何知道的呢?——gcc命令-v选项即可。

# gcc -v test.c [-o test]

# gcc -fprofile-arcs -ftest-coverage -v test.c [-o test]

[]表示出现0次或1次。

-v,即verbose选项,以下是中的解释,原文更贴切,此处不翻译。

The '-v' option can also be used to display detailed information about the exact sequence of commands used to compile and link a program.

linux
相关资讯       Linux编程 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款