c-在不使用ebp的情况下实现堆栈回溯



当编译器被明确告知不要使用ebp作为堆栈帧指针时,如何实现堆栈回溯?

这个问题的答案只出现在关于EBP帧指针寄存器的用途是什么的已接受答案的评论中?。

即使在使用-fomit帧指针编译的代码中,现代调试器也可以进行堆栈回溯。该设置是最近的gcc中的默认设置。

gcc将必要的堆栈展开信息放入.eh_frame_hdr部分。有关详细信息,请参阅此博客文章。它也用于运行时异常。您可以在Linux系统上的大多数二进制文件中找到它(使用objdump -h)。/bin/bash大约为16k,而GNU /bin/true大约为572B,ffmpeg大约为108k。

有一个gcc选项可以禁用生成它,但它是一个"正常"数据段,而不是strip默认删除的调试段。否则,您无法通过没有调试符号的库函数进行回溯。该部分可能比它所替换的push/mov/pop指令大,但它的运行时成本几乎为零(例如uop缓存)。


我认为存储在该部分中的信息是从返回地址到堆栈帧大小的映射。由于每条call指令都将下一条指令的地址推送到堆栈上,因此可以从该地址识别父调用方。与推动ebp在堆栈上创建堆栈帧的链表不同,到下一个返回地址的偏移量存储在.eh_frame_hdr部分中,因此如果需要回溯的代码需要,可以使用它。

相关内容

最新更新