当我们的程序core掉之后,如果能获取到core时的函数调用堆栈将非常有利于定位问题。在Windows下可以使用SEH机制;在Linux下通过gdb使用coredump文件即可。
但有时候由于某些错误导致堆栈被破坏,发生拿不到调用堆栈的情况。
一些基础预备知识本文不再详述,可以参考以下文章:
需要知道的信息:
- 函数调用对应的
call
指令本质上是先压入下一条指令的地址到堆栈,然后跳转到目标函数地址 - 函数返回指令
ret
则是从堆栈取出一个地址,然后跳转到该地址 - EBP寄存器始终指向当前执行函数相关信息(局部变量)所在栈中的位置,ESP则始终指向栈顶
- 每一个函数入口都会保存调用者的EBP值,在出口处都会重设EBP值,从而实现函数调用的现场保存及现场恢复
- 64位机器增加了不少寄存器,从而使得函数调用的参数大部分时候可以通过寄存器传递;同时寄存器名字发生改变,例如EBP变为RBP
在函数调用中堆栈的情况可用下图说明:
将代码对应起来:
void g() {
int *p = 0;
long a = 0x1234;
printf("%p %x\n", &a, a);
printf("%p %x\n", &p, p);
f();
*p = 1;
}
void b(int argc, char **argv) {
printf("%p %p\n", &argc, &argv);
g();
}
int main(int argc, char **argv) {