windows - x86 调试中符号如何解决使用 FPO 遍历堆栈的问题?

标签 windows debugging x86 symbols callstack

在此答案中:https://stackoverflow.com/a/8646611/192359 ,解释了在调试 x86 代码时,即使使用 FPO(帧指针省略),符号也允许调试器显示调用堆栈。

给出的解释是:

On the x86 PDBs contain FPO information, which allows the debugger to reliably unwind a call stack.

我的问题是这些信息是什么?据我了解,仅知道函数是否具有 FPO 并不能帮助您找到堆栈指针的原始值,因为这取决于运行时信息。

我在这里缺少什么?

最佳答案

从根本上来说,总是可以利用足够的信息来遍历堆栈1,除非堆栈或执行上下文已被不可恢复地损坏。

例如,即使不使用rbp作为帧指针,返回地址仍然位于堆栈中的某个位置,您只需要知道在哪里即可。对于不在函数体中(间接或直接)修改 rsp 的函数,它将位于距 rsp 的简单固定偏移处。对于在函数体中修改 rsp 的函数(即具有可变堆栈大小的函数),与 rsp 的偏移量可能取决于函数中的确切位置。

PDB 文件仅包含此“边带”信息,该信息允许某人确定函数中任何指令的返回地址。 Hans 链接了相关的内存结构 above - 您可以看到,由于它知道局部变量的大小等,因此它可以计算 rsp 和帧基址之间的偏移量,从而获得返回地址。它还知道有多少指令字节是“序言”的一部分,这很重要,因为如果 IP 仍在该区域,则应用不同的规则(即,堆栈尚未调整以反射(reflect)该函数中的局部变量)。

在 64 位 Windows 中,确切的函数调用 ABI 已经变得更加具体,并且所有函数通常都必须提供展开信息:不在 .pdb 中> 但直接位于二进制文件中包含的部分中。因此,即使没有 .pdb 文件,您也应该能够展开结构正确的 64 位 Windows 程序。它允许任何寄存器用作帧指针,并且仍然允许帧指针省略(有一些限制)。详情start here .


1 如果这不是真的,问问自己当前正在运行的函数如何返回?现在,从技术上讲,您可以设计一个程序,该程序以无法返回的方式破坏或忘记堆栈,并且永远不会退出或使用诸如 exit()abort() 终止。这是非常不寻常的,不可能在汇编之外。

关于windows - x86 调试中符号如何解决使用 FPO 遍历堆栈的问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45714943/

相关文章:

c# - 以编程方式将 Microsoft Print 中的文件名和路径设置为 PDF 打印机

c# - Azure:如何创建对内部端点的服务引用

调试 JNI 模块中的特定访问冲突

c - x86 汇编代码基本

linux - 如何制作多架构 Docker 镜像?

ruby-on-rails - 在 VM Vagrant Box 中创建 Windows 上的 Ruby on Rails 环境

windows - 获取主题编辑控件的非客户区的大小

iOS 错误消息 : reason: '-[__NSArrayM length]:

c++ - 按字母顺序对字符串数组排序的问题

x86 - 多核/NUMA 上的 CPUID