对此问题的答案仅存在于对What is the Purpose of the EBP Frame Pointer Register? 的已接受答案的评论中。。
现代调试器甚至可以在使用 -fomit-frame-pointer 编译的代码中进行堆栈回溯。该设置是最近 gcc 中的默认设置。
gcc 将必要的堆栈展开信息放入一个.eh_frame_hdr
部分中。 请参阅此博文了解更多详细信息。它也用于运行时异常。objdump -h
您会在 Linux 系统上的大多数二进制文件中找到它(带有)。大约为 16k /bin/bash
,而 GNU 为/bin/true
572B ffmpeg
,.
有一个 gcc 选项可以禁用生成它,但它是一个“正常”数据部分,而不是strip
默认删除的调试部分。否则,您将无法回溯没有调试符号的库函数。该部分可能比它所替换的指令更大push/mov/pop
,但它的运行时成本接近于零(例如微指令缓存)。
我认为该部分中存储的信息是从返回地址到堆栈帧大小的映射。由于每条call
指令都会将下一条指令的地址压入堆栈,因此您可以从该地址识别父调用者。下一个返回地址的偏移量存储在该部分中,而不是在堆栈上ebp
创建堆栈帧的链接列表,因此需要回溯的代码可以在需要时使用它。.eh_frame_hdr