本节书摘来自华章出版社《深入分析GCC 》一书中的第2章,第2.5节,作者 王亚刚 ,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
2.5 GCC调试选项
GCC本身对包含了众多的调试选项,既可以为用户程序生成调试信息,也可以将GCC运行过程中的关键信息保存在文件或输出在终端上,常用的调试选项如表2-2所示。如果需要了解GCC在处理的各个阶段里中间表示的具体内容,或者需要了解GCC中某个处理过程对于中间表示的处理细节时,就可以使用表2-2中给出的各种GCC调试选项,输出GCC运行过程中所生成的中间表示的调试信息和处理过程细节,并结合GCC的代码,从而了解GCC的具体工作细节。
假设有如下的源代码:
[GCC@localhost test]$ cat test.c
int main(){
int i=0, sum=0;
sum = sum + i;
return sum;
}
为了了解GCC对该文件编译过程中的主要处理过程,可以使用如下命令输出GCC处理过程的主要调试信息和工作流程。
[GCC@localhost test]$ ~/paag-gcc/host-i686-pc-linux-gnu/gcc/cc1 -fdump-tree-all -fdump-rtl-all test.c
[GCC@localhost test]$ ls test.c*
test.c test.c.123t.optimized test.c.168r.asmcons
test.c.001t.tu test.c.125t.blocks test.c.171r.subregs_of_mode_init
test.c.003t.original test.c.126t.final_cleanup test.c.172r.ira
test.c.004t.gimple test.c.128r.expand test.c.173r.subregs_of_mode_finish
test.c.006t.vcg test.c.129r.sibling test.c.176r.split2
test.c.007t.useless test.c.131r.initvals test.c.178r.pro_and_epilogue
test.c.010t.lower test.c.132r.unshare test.c.192r.stack
test.c.011t.ehopt test.c.133r.vregs test.c.193r.alignments
test.c.012t.eh test.c.134r.into_cfglayout test.c.196r.mach
test.c.013t.cfg test.c.135r.jump test.c.197r.barriers
test.c.014t.cplxlower0 test.c.154r.reginfo test.c.200r.eh_ranges
test.c.015t.veclower test.c.157r.outof_cfglayout test.c.201r.shorten
test.c.021t.cleanup_cfg test.c.163r.split1 test.c.202r.dfinish
test.c.023t.ssa test.c.165r.dfinit test.c.203t.statistics
test.c.038t.release_ssa test.c.166r.mode_sw
可以看出,此时输出的各种调试文件名称格式为:test.c.nnn[r/t].name,其中nnn为一个编号,t表示该处理过程是基于tree的GIMPLE处理过程,r表示该处理过程是基于RTL的处理过程。如果读者关注函数控制流图(CFG,Control F?low Graph)的信息,那么可以打开test.c.013t.cfg文件,查看其中的具体内容。内容如下:
[GCC@localhost test]$ cat test.c.013t.cfg
;; Function main (main)
Merging blocks 2 and 3
main ()
{
int sum;
int i;
int D.1234;
<bb 2>:
i = 0;
sum = 0;
sum = sum + i;
D.1234 = sum;
return D.1234;
}
其中就包含了例子中给出函数的控制流图,如果想了解更详细的CFG信息,也可以使用如下的编译形式:
[GCC@localhost test]$ ~/paag-gcc/host-i686-pc-linux-gnu/gcc/cc1 -fdump-tree-cfg-all test.c
[GCC@localhost test]$ cat test.c.013t.cfg
;; Function main (main)
Scope blocks:
{ Scope block #0
intD.0 iD.1232; (unused)
intD.0 sumD.1233; (unused)
}
Pass statistics:
----------------
Merging blocks 2 and 3
main ()
{
intD.0 sumD.1233;
intD.0 iD.1232;
intD.0 D.1234;
# BLOCK 2
# PRED: ENTRY (fallthru)
iD.1232 = 0;
sumD.1233 = 0;
sumD.1233 = sumD.1233 + iD.1232;
D.1234 = sumD.1233;
return D.1234;
# SUCC: EXIT
}
可以看出,GCC编译时会生成更加详细的CFG信息。
读者也可以根据自己的需要,合理地使用表2-2中的调试选项,输出GCC编译过程中感兴趣的调试信息,从而分析GCC的工作细节。