最近做的项目在windows和Linux两种平台上运行,调试分别使用windbg和gdb,虽然平台不同,使用的工具不同,但思路都是一样的,都是先从call trace中查看当前运行到哪了。每当看到call trace一行行的打出来,就觉得先成功一半了。总结了一下call trace是如何实现的,放上来备忘。
从函数调用的过程开始说。每次函数调用都会产生一个栈帧,%ebp寄存器指向,栈指针是%esp指针,本函数中使用的局部变量就是在栈上分配的。函数调用指令call 实现上相当于push %eip + jmp, 就是先把返回地址(也就是下一条指令的地址)压栈,然后跳转到子函数。相应的ret 指令相当于 pop %eip,把栈里的内容赋到eip里,这样就回到了原先保存的地址。此外还有一条指令