我试图找出段错误的原因,并使用 gdb 的 btrace 将其缩小到 PLT。段错误发生在从 PLT 跳转到 GOT 的过程中,我将其解释为表示 PLT 在执行过程中损坏。根据下面的分析,这种解释是否正确?PLT 腐败的罪魁祸首是什么?堆栈溢出?我相信在这种情况下,在 GOT 地址上安装一个观察点可能会有所帮助。会watch -l 0x55555562f048
是正确的方法吗?欢迎其他调试想法。
对于上下文,段错误发生在调用strlen
in 函数期间foo
:
int foo(char * path, ...) {
...
if (strlen(path) >= PATH_MAX) {
相应的装配线是:
0x58114 <foo+212> cmpq $0x0,-0x4c8(%rbp)
0x5811c <foo+220> jne 0x5812a <foo+234>
0x5811e <foo+222> lea 0xb96fb(%rip),%rdi # 0x111820
0x58125 <foo+229> callq 0x376c0 <__ubsan_handle_nonnull_arg@plt>
0x5812a <foo+234> mov -0x4c8(%rbp),%rax
0x58131 <foo+241> mov %rax,%rdi
0x58134 <foo+244> callq 0x37090 <strlen@plt>
首先,path
与 NULL ( cmpq $0x0,-0x4c8(%rbp)
) 进行比较,我相信在这种情况下,它只是为 ubsan 仪器添加的。没有遵循该分支,程序跳转到<foo+234>
,它为strlen
调用设置,通过移动path
到rax
然后rdi
,最后调用strlen@plt
。record btrace
在gdb
此之前运行会产生以下指令历史记录:
(gdb) record btrace
(gdb) c
136 0x00005555555ac114 <foo+212>: cmpq $0x0,-0x4c8(%rbp)
137 0x00005555555ac11c <foo+220>: jne 0x5555555ac12a <foo+234>
138 0x00005555555ac12a <foo+234>: mov -0x4c8(%rbp),%rax
139 0x00005555555ac131 <foo+241>: mov %rax,%rdi
140 0x00005555555ac134 <foo+244>: callq 0x55555558b090 <strlen@plt>
141 0x000055555558b090 <strlen@plt+0>: jmpq *0xa3fb2(%rip) # 0x55555562f048 <strlen@got.plt>
在这里,我们看到它path
不为空,因此程序跳转到<foo+234>
,并为strlen
调用 ( mov
, mov
, callq <strlen@plt>
) 设置。最后执行的指令是到GOT ( ) 中jmpq *0xa3fb2(%rip)
的条目,因此程序崩溃并且 gdb 丢失了上下文(报告它)。strlen
strlen@got.plt
Cannot find bounds of current function