我想了解如何像 gdb 在运行回溯命令时那样构建调用堆栈。这是在一次采访中被问到的,我根据我对调用堆栈和堆栈帧的了解回答了这个问题。我认为这是使用堆栈指针、调用者的返回地址/指令并将其映射到可执行/汇编指令来完成的。我一直在寻找它实际上是如何完成的或者对这个堆栈遍历的一个很好的解释。我在谷歌上找到的所有信息都与微软 API 相关,我正在寻找关于如何构建调用堆栈的通用解释。
问问题
149 次
2 回答
1
谷歌搜索把我带到了这里。
ix86
考虑带有帧指针的非常简单的调用约定。每次调用例程时,都会将下一条指令的地址压入堆栈。进入后立即调用的例程执行push %ebp; mov %esp,%ebp
指令。然后,您最终会得到上面页面中的布局。
假设您在例行程序中停止foo
,调用自bar
,调用自baz
,调用自main
。
您检查 指向的两个单词%ebp
。第一个字是%ebp
(我们称之为它的前一个值prev_ebp
,第二个是返回地址——内部某处的指令指针bar
。
您现在检查 指向的两个单词prev_ebp
。第一个将是prev_prev_ebp
,第二个将是一个返回地址 - 内部某处的指令指针baz
。
重复直到到达 main,并且大致执行了 GDB 使用的过程。
有许多实际的复杂情况,例如不使用帧指针的帧,但您不会理解 :-)
于 2012-10-27T16:29:26.687 回答
0
我不知道它是如何在 gdb 中完成的,但这里有一个想法,如果你可以将所有jmp/call
指令及其目标地址保存在堆栈中,那么在任何时候你都会有一个完整的调用跟踪。
于 2012-10-27T14:37:39.440 回答