【问题标题】:WinDbg not showing register valuesWinDbg 不显示寄存器值
【发布时间】:2016-03-12 17:52:21
【问题描述】:

基本上,这与here 提出的问题相同。

在运行 Windows 7 或更早版本(使用 WinDbg 6.2 及更高版本)的机器上执行内核调试时,调试器不会在寄存器窗口中显示任何内容。按Customize... 按钮会出现一个显示Registers are not yet known 的消息框。

同时,发出r 命令会打印出完全有效的寄存器值。

这种行为的原因是什么,可以修复吗?

【问题讨论】:

    标签: debugging windbg


    【解决方案1】:

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

    问题

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

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

    有了这些知识,我们现在可以对 WinDbg 如何获取目标机器上的寄存器值做出有根据的猜测。

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

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

    1. 调用IDebugRegisters::GetNumberRegisters获取寄存器总数。
    2. 调用IDebugRegisters::GetValues,将Count参数设置为寄存器总数,Indices参数设置为NULLStart参数设置为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 时一切正常。

    确实,不清楚该错误是在调试器引擎中,它报告的寄存器数量超过了它可以检索的值,还是在 WinDbg 中,如果引擎失败,它根本拒绝显示 任何 值生产所有个。

    解决方案

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

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

    就是这样,玩得开心!

    【讨论】:

    • 我刚刚花了半天时间尝试使寄存器窗口在连接到 Win7 调试器时与 WinDbg 10.0.17134.1 一起工作但失败了。您的扩展程序也没有解决问题。所以我最终使用了 WinDbg v.6.12.0002.633,而不是像一个魅力!幸运的是,它们可以同时安装。困难的部分实际上是找到旧版本的 WinDbg。因此,为了将来节省他人和我自己的时间here it is,并提供如何安装的说明。
    • @c00000fd 您能否在 GitHub 上打开一个问题,描述您在使用扩展程序时所采取的步骤?
    • @MichaelBikovitsky:我下载了您的release build,然后将 64 位版本的 WingDbg.dll 放在一个文件夹中。然后在_NT_DEBUGGER_EXTENSION_PATH env-var 中使用它的路径并启动WinDbg。然后用.load WingDbg.dll 命令加载它。测试已加载:.chain。确实如此。然后尝试闯入Win7调试器并且寄存器窗口仍然是空的。试了几次。没有运气。如果 dll 生成任何日志,我可以将它们发送给您。有的话发邮件给我。
    • @c00000fd 加载扩展后是否执行了!regfix 命令?
    • @MichaelBikovitsky:不,这可能就是原因。那么你应该更好地记录它。
    猜你喜欢
    • 2022-06-22
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    • 2016-03-06
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多