首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WinDbg未显示寄存器值

问WinDbg未显示寄存器值
EN

Stack Overflow用户
提问于 2016-03-12 17:52:21
回答 1查看 3K关注 0票数 8

基本上,这是问here的同一个问题。

当对运行Windows7或更高版本的计算机执行内核调试时,使用WinDbg Version6.2或更高版本,调试器不会在“寄存器”窗口中显示任何内容。按Customize...按钮将生成一个读取Registers are not yet known的消息框。

同时,发出r命令将导致输出完全有效的寄存器值。

这种行为的原因是什么,它能解决吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-12 17:52:21

TL;DR:我编写了一个扩展DLL来修复这个错误。可用here。

问题

要理解这个问题,我们首先需要理解的是,WinDbg基本上只是微软在dbgeng.dll内部实现的Windows符号调试器引擎的前端。其他前端包括命令行kd.exe (内核调试器)和cdb.exe (用户模式调试器)。

引擎实现了我们期望调试器提供的所有功能:处理符号文件、读写内存和寄存器、设置断点等等。然后引擎通过COM类接口公开所有这些功能(它们实现了IUnknown,但不是注册的组件)。例如,这允许我们编写自己的调试器(就像this person做的那样)。

有了这些知识,我们现在可以对WinDbg如何获得目标机器上的寄存器值进行有知识的猜测。

引擎公开用于操作寄存器的IDebugRegisters接口。这个接口声明了GetValues方法,用于一次检索多个寄存器的值。但是WinDbg怎么知道有多少寄存器呢?这就是为什么我们有GetNumberRegisters方法。

因此,要检索目标上所有寄存器的值,我们必须执行如下操作:

  1. 调用IDebugRegisters::GetNumberRegisters以获取寄存器的总数。
  2. 调用IDebugRegisters::GetValues,将Count参数设置为寄存器总数,Indices参数设置为NULL,Start参数设置为0。

不过,有一个小问题:第二个调用在E_INVALIDARG中失败。

嗯,什么?怎么会失败呢?特别令人费解的是这个返回值的文档:

其中一个寄存器的索引值大于目标机器上的寄存器数。

但是我只是问你有多少寄存器,那么这个值怎么会超出范围呢?好吧,让我们继续读这些文档,也许会有一些事情变得清晰起来:

如果返回值不是S_OK,则某些寄存器可能仍被读取。如果无法访问目标,则返回类型为E_UNEXPECTED,且值不变;否则,值将包含部分结果,无法读取的寄存器将具有DEBUG_VALUE_INVALID类型。

(强调我的)

啊哈!所以也许引擎看不懂其中的一个寄存器!但是哪一个呢?结果,引擎在xcr0寄存器上卡住了。来自英特尔64和IA-32架构软件开发人员手册

扩展控制寄存器XCR0包含一个状态组件位图,该位图指定软件已启用XSAVE功能集来管理的用户状态组件。如果与状态组件对应的位在XCR0中是清晰的,则无论指令掩码的值如何,XSAVE功能集中的指令都不会在该状态组件上操作。

好的,寄存器控制XSAVE指令的操作,它保存了CPU扩展特性(比如XMM和AVX)的状态。根据this页面上的最后一个注释,这个指令需要操作系统的一些支持。尽管评论声明Windows 7(我正在测试的VM运行的内容)确实支持这条指令,但看起来手头的问题无论如何都与操作系统有关,因为当目标是Windows 8时,一切都很好。

实际上,还不清楚bug是在调试器引擎中,它报告的寄存器比它能够检索的值多,还是在WinDbg中,如果引擎无法生成所有值,它就会拒绝显示任何值。

解决方案

当然,我们可以咬紧牙关,只需使用较早版本的WinDbg来调试旧版本的Windows。但这其中的挑战在哪里?

相反,我向您介绍一个解决这个问题的debugger extension。它这样做的方法是(在this library的帮助下)挂钩相关的调试器引擎方法,并返回S_OK (如果唯一失败的寄存器是xcr0 )。否则,它会传播故障。扩展支持运行时卸载,因此如果遇到问题,可以始终禁用钩子。

就这样,玩得开心!

票数 20
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35961246

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档