首页
社区
课程
招聘
gcc -O2编译,gdb单步执行怪怪的
发表于: 2024-5-22 19:12 10366

gcc -O2编译,gdb单步执行怪怪的

2024-5-22 19:12
10366

代码(test.c):

编译:

调试:

此时rip指向main()函数的第一条指令,打印foo变量,显示"<optimized out>"。

此时rip指向main()函数的第二条指令,打印foo变量,仍然显示"<optimized out>"。

此时rip指向main()函数的第三条指令,打印foo变量,仍然显示"<optimized out>"。

可以看到:C代码与汇编代码界面吻合,一边到达printf()函数,一边到达为printf()传参的指令,但是奇怪的是,既然"foo=rand()"执行完了,为什么看不到foo的值?

此时rip指向main()函数的第四条指令,打印foo变量,仍然显示"<optimized out>"。

可以看到:C代码界面的显示很奇怪,没到下一行,反而回到上一行了,不过从汇编代码看,此时确实是在备份rand()的返回值(rax->rbx)

此时rip指向main()函数的第五条指令(地址:0x40047d),打印foo变量,显示为rand()返回值。

为什么到达第五条指令,才能显示foo的值?

这是因为,gdb是根据.debug_info节区的指引,获取foo的值,而"location list"表示:更详细指引信息,参照.debug_loc节区。

.debug_loc节区内容表示,执行到[0x40047d, 0x400481)指令时,rax寄存器的值,即为foo的值,执行到[0x400481, 0x400489)指令时,rbx寄存器的值,即为foo的值。

这一定与代码的逻辑吻合:

一方面,其实执行到0x400476时,即rand()一执行完,就可以通过"p $rax",知道foo的值了,但是gcc生成的起始地址是0x40047d,那"p foo"就只能晚一点才能显示出来;

另一方面,[0x400476, 0x40047f)区间的指令,都未修改rax寄存器,但是执行到0x400481处时,eax寄存器就被异或为0了,所以从0x400481开始,需要从rbx寄存器,获取foo的值(0x40047b处的指令,已经将eax备份到ebx了)。


为什么gcc -O0,不会显示"<optimized out>"?


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2024-5-23 15:15 被jmpcall编辑 ,原因:
收藏
免费 2
支持
分享
最新回复 (1)
雪    币: 237
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
要调试最好是不开优化,要开优化只推荐汇编调试,源码是对不上的,很多变量或者逻辑都会被优化。
2024-5-26 18:54
0
游客
登录 | 注册 方可回帖
返回
//