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

时间:2015-12-03 00:46:14

标签: c assembly x86 backtrace

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

1 个答案:

答案 0 :(得分:2)

对此问题的回答只是对What is the purpose of the EBP frame pointer register?上接受的答案的评论。

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

gcc将必要的堆栈展开信息放入.eh_frame_hdr部分。 See this blog post for more details。它也用于运行时异常。您可以在Linux系统上的大多数二进制文件中找到它(带objdump -h)。 /bin/bash约为16k,GNU /bin/true为572B,ffmpeg为108k。

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

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