在使用WinDBG分析Windows内核崩溃转储时,我经常遇到WinDBG无法读取某些内存位置的问题。最近在分析内核崩溃转储(minidump文件)时,我观察到有六个堆栈变量(包括两个参数),其中WinDBG成功地转储了四个堆栈变量的值但是它返回了另外两个变量。我无法理解这一点,因为所有六个变量都是相同堆栈帧的一部分。
除此之外,我注意到当我尝试转储全局数据结构时,WinDBG返回一个错误,指示“无法读取地址0xfffff801139c50d0处的内存”。我无法理解为什么WinDBG无法读取已在我的驱动程序中全局定义的变量。
我已正确加载符号,包括我的驱动程序的PDB文件。 WinDBG没有给我任何符号相关的错误。
我想了解这种行为的原因。为什么WinDBG无法读取本地和全局变量的值?有人可以给我这个行为的解释吗?
答案 0 :(得分:1)
假设您已经可以访问私有符号,此错误通常是由驱动程序中的代码优化引起的,并且PDB没有足够的信息来始终确定变量的更正位置。
使用!lmi <module name>
并检查特征字段是否包含&#34; perf&#34;确定代码是否已经过优化。
正如Debugging Performance Optimized Code中所建议的那样,最终的优化减少了分页(和页面错误),并增加了代码和数据之间的空间局部性。它解决了原始代码定位不佳所带来的关键性能瓶颈。经过此优化的组件可能将其函数内的代码或数据块移动到二进制文件的不同位置。 在通过这些技术优化的模块中,代码和数据块的位置通常位于不同于正常编译和链接后它们所在位置的存储器地址。此外,功能可能已被分成许多非连续的块,以便最常用的代码路径可以在相同的页面上彼此靠近地定位。 因此,函数(或任何符号)加上偏移量不一定具有与非优化代码中相同的含义。使用性能优化代码时的经验法则是,您无法对优化代码执行可靠的地址算法。
您需要检查dv /V
的输出以确定调试器实际查找本地的位置,并确认这是正确的。