Operating system 如gdb所示构造调用堆栈

Operating system 如gdb所示构造调用堆栈,operating-system,gdb,Operating System,Gdb,我想了解如何像gdb在运行backtrace命令时那样构建调用堆栈。这是在一次采访中被问到的,我根据自己对调用堆栈和堆栈框架的了解回答了这个问题。我认为这是通过使用堆栈指针、调用方的返回地址/指令并将其映射到可执行/汇编指令来实现的。我一直在寻找它实际上是如何完成的,或者对这个堆栈行走的一个很好的解释。我在谷歌上找到的所有信息都与微软API有关,我正在寻找一个关于如何构建调用堆栈的通用解释 我不知道它在gdb中是如何实现的,但有一个想法,如果你能将所有jmp/call指令及其目标地址保存在一个堆

我想了解如何像gdb在运行backtrace命令时那样构建调用堆栈。这是在一次采访中被问到的,我根据自己对调用堆栈和堆栈框架的了解回答了这个问题。我认为这是通过使用堆栈指针、调用方的返回地址/指令并将其映射到可执行/汇编指令来实现的。我一直在寻找它实际上是如何完成的,或者对这个堆栈行走的一个很好的解释。我在谷歌上找到的所有信息都与微软API有关,我正在寻找一个关于如何构建调用堆栈的通用解释

我不知道它在gdb中是如何实现的,但有一个想法,如果你能将所有
jmp/call
指令及其目标地址保存在一个堆栈中,那么在任何时候你都会有一个完整的调用跟踪。

我不知道它在gdb中是如何实现的,但有一个想法,如果你能把所有的
jmp/call
指令和它们的目标地址放在一个堆栈中,那么在任何时候你都会有一个完整的调用跟踪

考虑使用帧指针的非常简单的
ix86
调用约定。每次调用例程时,下一条指令的地址都会被推送到堆栈上。被调用的例程在进入时立即执行
push%ebp;mov%esp,%ebp
说明。然后,您完全可以使用上面页面中的布局

假设您在例程
foo
中停止,从
bar
调用,从
baz
调用,从
main
调用

您检查了由
%ebp
指向的两个单词。第一个字是
%ebp
的前一个值(我们称之为
prev\u ebp
),第二个字是返回地址--
条内某处的指令指针

现在检查
prev\u ebp
指向的两个单词。第一个单词是
prev\u ebp
,第二个单词是返回地址--
baz
内某处的指令指针

重复此步骤,直到到达main,并且大致执行了GDB使用的过程

有许多实际的复杂情况,例如不使用帧指针的帧,但您不应该理解:-)

谷歌搜索引导了我

考虑使用帧指针的非常简单的
ix86
调用约定。每次调用例程时,下一条指令的地址都会被推送到堆栈上。被调用的例程在进入时立即执行
push%ebp;mov%esp,%ebp
说明。然后,您完全可以使用上面页面中的布局

假设您在例程
foo
中停止,从
bar
调用,从
baz
调用,从
main
调用

您检查了由
%ebp
指向的两个单词。第一个字是
%ebp
的前一个值(我们称之为
prev\u ebp
),第二个字是返回地址--
条内某处的指令指针

现在检查
prev\u ebp
指向的两个单词。第一个单词是
prev\u ebp
,第二个单词是返回地址--
baz
内某处的指令指针

重复此步骤,直到到达main,并且大致执行了GDB使用的过程

有许多实际的复杂情况,例如不使用帧指针的帧,但您不需要理解:-)