托管调用堆栈与本机调用堆栈有什么区别,为什么dbghelp不能解析托管调用堆栈中的符号?有人能告诉我基本原因吗?
发布于 2022-08-08 19:11:40
当运行本机exe时,windows使用内存映射文件功能将exe (和dll)映射到内存中(这并不重要)。因此,当程序运行时,您有一个模块地址,它是从本机exe (或dll)映像加载的基本地址(例如,模块地址指向exe/dll文件中的第一个字节,等等)。因此,当您有一个来自堆栈遍历的地址时,您可以根据加载的模块列表“知道”地址来自哪个模块,因为该地址将位于模块地址范围之一的范围内。然后,它知道偏移到exe文件(即地址-模块地址==偏移到exe)。dbhelp使用此地址查找模块,然后使用偏移量进入exe以查找符号( pdb有一个地址范围到符号的表)。
这就是它对运行中的本机代码的工作方式。
无法为托管exe工作的原因是托管代码是如何工作的。
编译的托管代码不是本机代码,而是电子邮件。托管EXE是围绕IL程序集的小型本机包装器。本机包装器用于“启动”.net运行时并在IL程序集中运行入口点。
.net运行时使用JIT将IL转换为本机代码。它通过分配内存、生成本机代码并将内存页标记为可执行来实现这一点,然后跳到它。因此,当这些地址出现在堆栈遍历中时,它不会映射到任何加载的本机模块(因为它没有)。所以你只看到一个地址,它不能映射到任何PDB文件。
因此,要能够将这个未知地址映射到托管符号,您需要:
因此dbghelp只适用于本机符号映射,对托管堆栈跟踪一无所知。
内存转储(或活动进程内存)的托管堆栈跟踪需要知道/访问内部托管运行时表,以便能够将临时可执行内存页解析为托管符号。
https://stackoverflow.com/questions/73274651
复制相似问题