我有一个堆栈已损坏的核心转储。 我尝试拆解它并发现以下内容请帮我分析它..
(gdb) bt
#0 0x55a63c98 in ?? ()
#1 0x00000000 in ?? ()
(gdb) disassemble 0x55a63c90 0x55a63ca8
Dump of assembler code from 0x55a63c90 to 0x55a63ca8:
0x55a63c90: add %cl,%dh
0x55a63c92: cmpsb %es:(%edi),%ds:(%esi)
0x55a63c93: push %ebp
0x55a63c94: add %al,(%eax)
0x55a63c96: add %al,(%eax)
**0x55a63c98: pusha**
0x55a63c99: lret $0x9
0x55a63c9c: subb $0x56,0xd005598(%ebp)
0x55a63ca3: push %ebp
0x55a63ca4: jo 0x55a63cc5
0x55a63ca6: sahf
0x55a63ca7: push %ebp
End of assembler dump.
(gdb) q
这个 Pusha 指令会导致核心转储吗?
不*,pusha所做的只是将所有通用寄存器压入堆栈,包括堆栈指针!导致核心转储的是 Pusha、lret 之后的指令,该指令是带有堆栈弹出的长返回。返回地址是推送到堆栈的最新值,在本例中将是 esi:edi 中的任何内容(因为它们是 Pusha 指令推送的最后一个值),并且很可能指向随机的某个位置。
* 除非你用完了堆栈空间。
当然。 PUSHA 后面跟着 RET 永远不会正确,返回地址将是垃圾。在反汇编中看到 ADD AL,[EAX] 是另一个致命的泄露,这是 0 的反汇编。
换句话说:你正在反汇编数据,而不是代码。你的程序崩溃是因为它正在执行数据。发生的经典方式是通过缓冲区溢出破坏堆栈帧。当函数返回时,它会从损坏的堆栈中弹出一个无效的返回地址,并跳转到never never land。没有出现段错误是非常不幸的。
难以调试,堆栈跟踪是垃圾。您需要在最后一个已知的正确代码地址处设置断点并开始单步执行。您在崩溃之前进入的最后一个好功能通常是麻烦制造者。
pusha
只能导致核心转储。该指令将所有寄存器值压入堆栈,这可能导致溢出。然而问题的根源可能在其他地方 - 最有可能的是调用堆栈在该点太深,并且 pusha
恰好导致了这样的后果,因为它是在这样的条件下执行的。
检查是否看到对齐的反汇编代码:
x/i $eip
还显示寄存器值:
i r