-
-
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编辑
,原因: