【问题标题】:How can I get the BSOD bugcheck code text description by code/windows API如何通过代码/Windows API 获取 BSOD 错误检查代码文本描述
【发布时间】:2021-10-18 08:18:11
【问题描述】:

我可以获得一个BSOD的错误检查代码和参数。

然后我可以从Bug Check Code Reference获取文字描述。

但是如何使用一些 windows API 或 c++ 代码从错误检查代码和参数中获取这样的文本描述。

例如,对于错误检查代码 0x9F,我怎样才能得到文本为

DRIVER_POWER_STATE_FAILURE (9f) 驱动程序未能在特定时间内完成电源 IRP。

使用一些 Windows API 或从一些 DLL 读取。

或者说,如何实现类似WinDbg的功能:

1: kd> !analyze -show 0x9F 0x3
DRIVER_POWER_STATE_FAILURE (9f)
A driver has failed to complete a power IRP within a specific time.
Arguments:
Arg1: 0000000000000003, A device object has been blocking an Irp for too long a time
Arg2: 0000000000000000, Physical Device Object of the stack
Arg3: 0000000000000000, nt!TRIAGE_9F_POWER on Win7 and higher, otherwise the Functional Device Object of the stack
Arg4: 0000000000000000, The blocked IRP

我看到有类似 KeGetBugMessageText() 的 API,但它是由 Windows 自己保存的。

有人可以提供帮助并就此提供一些线索或建议吗?

更新: 用于执行带有 'blabb' 建议的命令的主要代码部分:

#pragma comment ( lib ,"dbgeng.lib")
#include <iostream>
#include <dbgeng.h>
#include "StdioOutputCallbacks.h"

//#include <wdbgexts.h>
//WINDBG_EXTENSION_APIS64 ExtensionApis;
StdioOutputCallbacks g_OutputCb;
int main()
{
    IDebugClient* DebugClient = NULL;
    HRESULT Hr = S_OK;

    if ((Hr = DebugCreate(__uuidof(IDebugClient),
       (void**)&DebugClient)) != S_OK) {
       return Hr;
    }
    
    PDEBUG_CONTROL DebugControl;
    if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl),
       (void**)&DebugControl)) == S_OK) {
       DebugClient->SetOutputCallbacks(&g_OutputCb);

       Hr = DebugClient->OpenDumpFile("C:\\Dev\\Deem\\bug\\dcp938\\MEMORY.DMP");
       if (Hr != S_OK) {
          return Hr;
       }
       
       DebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "!analyze -show 9f 3", DEBUG_EXECUTE_DEFAULT);
       DebugControl->Release();
    }
    // done
    DebugClient->Release();
}
and in outputcallback, kept as the msdn sample:
STDMETHODIMP
StdioOutputCallbacks::Output(
   THIS_
   _In_ ULONG Mask,
   _In_ PCSTR Text
)
{
   UNREFERENCED_PARAMETER(Mask);
   fputs(Text, stdout);
   return S_OK;
}

但是执行“!analyze -show 9f 3”(fputs()中Text的内容)的结果是“No export analyze found”。 我也尝试了命令“.opendump C:\...MEMORY.DMP;!analyze -show 9f 3”,opendump命令正确执行,dmp被加载并得到文本输出,包括“为了分析这个文件,运行!analyze -v”,但“!analyze -v”和“!analyze -show ...”都得到“未找到导出分析”。 不带“!”的命令会导致命令解析错误。

【问题讨论】:

    标签: windows kernel windbg bsod


    【解决方案1】:

    我不确定您在寻找什么。 所有这些都在 windows sdk/ddk 中的 bugcodes.h 中#定义

    C:\Program Files (x86)\Windows Kits\10\Include>pss DRIVER_POWER_STATE_FAILURE
    .\10.0.17763.0\shared\bugcodes.h
    1505:// MessageId: DRIVER_POWER_STATE_FAILURE
    1509://  DRIVER_POWER_STATE_FAILURE
    1511:#define DRIVER_POWER_STATE_FAILURE       ((ULONG)0x0000009FL)
    

    反之亦然

    C:\Program Files (x86)\Windows Kits\10\Include>grep -ir #define.*0x0000009fl --include *.h *
    10.0.17763.0/shared/bugcodes.h:#define DRIVER_POWER_STATE_FAILURE       ((ULONG)0x0000009FL)  
    

    或使用 DbgEng 编写 WinDbg 扩展或独立可执行文件。

    打开转储->WaitForEvent->执行命令 !bugdump .bug****

    或者您也可以探索IDebugDataSpaces::****tag**** 方法,例如read、start、next、end。

    编辑

    Scott Noone 可能表示 ext.dll 是内置的 windbg 扩展

    正如我已经说过的,您可能需要编写一个 windbg 分析扩展作为扩展或独立
    其中大部分是没有文档或措辞不佳的文档

    这是在 ext.dll 中编译的错误检查代码的转储,这可能是 scott noone 在他的回答中所指出的。

    0:000> dps ext!g_BugCheckApiRefs l10
    00007ff9`4a45ccc0  00000000`00000001
    00007ff9`4a45ccc8  00007ff9`49efead0 ext!BugCheckAPC_INDEX_MISMATCH
    00007ff9`4a45ccd0  00000000`00000002
    00007ff9`4a45ccd8  00007ff9`49efeb60 ext!BugCheckDEVICE_QUEUE_NOT_BUSY
    00007ff9`4a45cce0  00000000`00000003
    00007ff9`4a45cce8  00007ff9`49efebc0 ext!BugCheckINVALID_AFFINITY_SET
    00007ff9`4a45ccf0  00000000`00000004
    00007ff9`4a45ccf8  00007ff9`49efec20 ext!BugCheckINVALID_DATA_ACCESS_TRAP
    00007ff9`4a45cd00  00000000`00000005
    00007ff9`4a45cd08  00007ff9`49efec80 ext!BugCheckINVALID_PROCESS_ATTACH_ATTEMPT
    00007ff9`4a45cd10  00000000`00000006
    00007ff9`4a45cd18  00007ff9`49efece0 ext!BugCheckINVALID_PROCESS_DETACH_ATTEMPT
    00007ff9`4a45cd20  00000000`00000007
    00007ff9`4a45cd28  00007ff9`49efed40 ext!BugCheckINVALID_SOFTWARE_INTERRUPT
    00007ff9`4a45cd30  00000000`00000008
    00007ff9`4a45cd38  00007ff9`49efeda0 ext!BugCheckIRQL_NOT_DISPATCH_LEVEL
    0:000>  
    

    或者你的电源故障

    0:000> .shell -ci "dps ext!g_BugCheckApiRefs l150" grep -A 1 -i 09f
    00007ff9`4a45d600  00000000`0000009f
    00007ff9`4a45d608  00007ff9`49f04450 ext!BugCheckDRIVER_POWER_STATE_FAILURE
    .shell: Process exited
    0:000>  
    

    这里有一个完整的调用堆栈Leadign to yourQuery about !analyze -show 9f 3

    Child-SP          RetAddr           Call Site
    000000d3`6d67b768 00007ff9`49fa302a ext!GetBugCheckDescription
    000000d3`6d67b770 00007ff9`49f822c2 ext!DebugFailureAnalysis::ParseInputArgs+0xc66
    000000d3`6d67bb00 00007ff9`49f549c5 ext!AnalyzeBugCheck+0x10a
    000000d3`6d67bbd0 00007ff9`4ae0187d ext!analyze+0x4e5
    000000d3`6d67bd90 00007ff9`4ae01a31 dbgeng!ExtensionInfo::CallA+0x27d
    000000d3`6d67be50 00007ff9`4ae01d0e dbgeng!ExtensionInfo::Call+0x121
    000000d3`6d67c050 00007ff9`4adff9d8 dbgeng!ExtensionInfo::CallAny+0x17a
    000000d3`6d67c570 00007ff9`4ae43662 dbgeng!ParseBangCmd+0xe0c
    000000d3`6d67cd30 00007ff9`4ae44635 dbgeng!ProcessCommands+0xcd6
    000000d3`6d67ce20 00007ff9`4ad6baf7 dbgeng!ProcessCommandsAndCatch+0x79
    000000d3`6d67ce90 00007ff9`4ad6be04 dbgeng!Execute+0x2bb
    000000d3`6d67d380 00007ff6`4c7b62dc dbgeng!DebugClient::ExecuteWide+0x94
    000000d3`6d67d3e0 00007ff6`4c7b879a kd!MainLoop+0x514
    000000d3`6d67f460 00007ff6`4c7bb55d kd!wmain+0x3e6
    000000d3`6d67f700 00007ff9`857c7c24 kd!__wmainCRTStartup+0x14d
    000000d3`6d67f740 00007ff9`85d8d721 KERNEL32!BaseThreadInitThunk+0x14
    000000d3`6d67f770 00000000`00000000 ntdll!RtlUserThreadStart+0x21
    0:000>                                                            
    

    函数是一个简单的比较返回例程,如

    while array[i] != 0x9f skip 
    return String array[i]+0x8 
    

    详细说明由

    void PrintBugDescription(_BUGCHECK_ANALYSIS *param_1,DebugFailureAnalysis *param_2)
    

    编辑 自从我上次发表评论以来,我一直在想

    1. 如何在不编写代码的情况下处理这种情况
    2. 没有可操作的内核内存转储
    3. 可能扩展到未知的远程机器

    我想出了一个使用 sysinternals livekd.exe 的小型 python 包装器

    脚本

    :\>cat liv.py
    import subprocess
    import regex
    foo = subprocess.run(
        [r"f:\sysint\livekd", "-b" ,"-c \"!analyze -show 9f 03;q\""],
        stdout=subprocess.PIPE,
        universal_newlines=True
        )
    resta = regex.search("Reading" , foo.stdout).start()
    reend = regex.search("quit:" , foo.stdout).end()
    print(foo.stdout[resta:reend])
    

    脚本执行结果

    :\>python liv.py
    Reading initial command '!analyze -show 9f 03;q'
    *** ERROR: Module load completed but symbols could not be loaded for LiveKdD.SYS
    DRIVER_POWER_STATE_FAILURE (9f)
    A driver has failed to complete a power IRP within a specific time.
    Arguments:
    Arg1: 0000000000000003, A device object has been blocking an Irp for too long a time
    Arg2: 0000000000000000, Physical Device Object of the stack
    Arg3: 0000000000000000, nt!TRIAGE_9F_POWER on Win7 and higher, otherwise the Functional Device Object of the stack
    Arg4: 0000000000000000, The blocked IRP
    *******************************************************************************
    *                                                                             *
    *                        Bugcheck Analysis                                    *
    *                                                                             *
    *******************************************************************************
    
    Use !analyze -v to get detailed debugging information.
    
    BugCheck 0, {0, 0, 0, 0}
    
    Probably caused by : LiveKdD.SYS ( LiveKdD+2f4f )
    
    Followup:     MachineOwner
    ---------
    
    quit:
    

    【讨论】:

    • 非常感谢!
      我想要的是:给定输入“0x9F”,输出应该是“DRIVER_POWER_STATE_FAILURE (9f) 驱动程序未能在特定时间内完成电源 IRP。”
      那么bugcodes.h中没有包含bugcheck代码的详细描述,我从哪里可以找回呢?
      谢谢!
    • 或来自stackoverflow.com/questions/11035784/…,“关于已知错误检查代码的文本被编译成扩展DLL之一。”,DLL名称是什么以及如何从DLL中获取文本?
    • 添加信息看看
    • 非常感谢!这很有帮助。我将检查有关 windbg GetBugCheckDescription 和 PrintBugDescription 的更多详细信息。谢谢!
    • 它们没有被导出,所以你不能 LoadLib->Getproc 并且如果你碰巧弯曲它来加载和调用,你没有要读取的转储,并且任何 Idebug 接口都不会被初始化就像你使用 Dbgeng->IDebugClient->OpenDump() 一样,据我所知,你将编写一个 windbg 克隆并将字符串传递给 IdebugControl->Execute("show 9f 3")
    【解决方案2】:

    添加另一个答案作为先前的答案太杂乱和评论。

    目录预编译和链接的内容

    F:\bugdesc>ls -lg
    -rw-r--r-- 1 197121 156689581 Aug 17 23:49 MEMORY.DMP                                                                   
    -rw-r--r-- 1 197121       600 Aug 26 01:22 bugdesc.cpp
    -rw-r--r-- 1 197121       109 Aug 19 00:04 complink.bat
    -rw-r--r-- 1 197121      1019 Aug 26 01:21 stdioimpl.h
    

    bat文件内容

    F:\bugdesc>cat complink.bat
    cl  /nologo /W4 /Od  /Zi /EHsc /I"C:\Program Files (x86)\Windows Kits\10\Debuggers\inc" %1.cpp /link /RELEASE
    

    包含 StdioOutputCallbacks 实现的文件

    F:\bugdesc>cat stdioimpl.h
    #include <windows.h>
    #include <stdio.h>
    #include <dbgeng.h>
    #pragma comment(lib, "dbgeng.lib")
    class StdioOutputCallbacks : public IDebugOutputCallbacks {
    public:
        STDMETHOD(QueryInterface)(THIS_ _In_ REFIID ifid, _Out_ PVOID *iface);
        STDMETHOD_(ULONG, AddRef)(THIS);
        STDMETHOD_(ULONG, Release)(THIS);
        STDMETHOD(Output)(THIS_ IN ULONG Mask, IN PCSTR Text);
    };
    STDMETHODIMP
    StdioOutputCallbacks::QueryInterface(THIS_ _In_ REFIID ifid, _Out_ PVOID *iface){
        *iface = NULL;
        if (IsEqualIID(ifid, __uuidof(IDebugOutputCallbacks))){
            *iface = (IDebugOutputCallbacks *)this;
            AddRef();
            return S_OK;
        }    else    {
            return E_NOINTERFACE;
        }
    }
    STDMETHODIMP_(ULONG)
    StdioOutputCallbacks::AddRef(THIS) { return 1; }
    STDMETHODIMP_(ULONG)
    StdioOutputCallbacks::Release(THIS) { return 0; }
    STDMETHODIMP StdioOutputCallbacks::Output(THIS_ IN ULONG, IN PCSTR Text){
        fputs(Text, stdout);
        return S_OK;
    }
    

    主源文件的内容

    F:\bugdesc>cat bugdesc.cpp
    #include "stdioimpl.h"
    //implement proper error handling and release of Interfaces
    void __cdecl main(void)
    {
        IDebugClient *g_Client;
        IDebugControl *g_Control;
        StdioOutputCallbacks g_OutputCb;
        DebugCreate(__uuidof(IDebugClient), (void **)&g_Client);
        g_Client->QueryInterface(__uuidof(IDebugControl), (void **)&g_Control);
        g_Client->SetOutputCallbacks(&g_OutputCb);
        g_Client->SetOutputCallbacks(&g_OutputCb);
        g_Client->OpenDumpFile("F:\\bugdesc\\memory.dmp");
        g_Control->WaitForEvent(0, INFINITE);
        g_Control->Execute(0, "!analyze -show 9f 3", 0);
    }
    

    以 x64 格式与 vs-community 2017 编译并链接

    F:\bugdesc>complink.bat bugdesc
    
    F:\bugdesc>cl  /nologo /W4 /Od  /Zi /EHsc /I"C:\Program Files (x86)\Windows Kits\10\Debuggers\inc" bugdesc.cpp /link /RELEASE
    bugdesc.cpp
    

    目录后编译和链接的内容

    F:\bugdesc>ls -lg
    total 159485
    -rw-r--r-- 1 197121 156689581 Aug 17 23:49 MEMORY.DMP
    -rw-r--r-- 1 197121       600 Aug 26 01:22 bugdesc.cpp
    -rwxr-xr-x 1 197121    406016 Aug 26 01:25 bugdesc.exe
    -rw-r--r-- 1 197121     30072 Aug 26 01:25 bugdesc.obj
    -rw-r--r-- 1 197121   5992448 Aug 26 01:25 bugdesc.pdb
    -rw-r--r-- 1 197121       109 Aug 19 00:04 complink.bat
    -rw-r--r-- 1 197121      1019 Aug 26 01:21 stdioimpl.h
    -rw-r--r-- 1 197121    176128 Aug 26 01:25 vc140.pdb
    

    在没有正确的 dll 和失败的情况下执行

    F:\bugdesc>bugdesc.exe
    No .natvis files found at C:\WINDOWS\SYSTEM32\Visualizers.
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip 
    Microsoft (R) Windows Debugger Version 10.0.18362.1 AMD64
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip
    Loading Dump File [F:\bugdesc\memory.dmp]
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip
    ***    Type referenced: nt!_MMPTE_TRANSITION                          ***
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip
    For analysis of this file, run !analyze -v
    No export analyze found<<<<<<<<<<<<<<<<<<
    

    从windbg安装文件夹复制相关的dll

    F:\bugdesc>copy ..\windbg_dlls\*.* .
    ..\windbg_dlls\dbgeng.dll
    ..\windbg_dlls\dbghelp.dll
    ..\windbg_dlls\ext.dll
    ..\windbg_dlls\symsrv.dll
            4 file(s) copied.
    

    执行与成功

    F:\bugdesc>bugdesc.exe
    
    Microsoft (R) Windows Debugger Version 10.0.17763.132 AMD64
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip
    Loading Dump File [F:\bugdesc\memory.dmp]
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip
    *******************************************************************************
    *                                                                             *
    *                        Bugcheck Analysis                                    *
    *                                                                             *
    *******************************************************************************
    
    Use !analyze -v to get detailed debugging information.
    
    BugCheck E2, {0, 0, 0, 0}
    
    Probably caused by : Unknown_Image
     *** Followup info cannot be found !!! Please contact "BADEV"
    
    ---------
    
    DRIVER_POWER_STATE_FAILURE (9f)<<<<<<<<<<<<<<<<<<<<<<<
    A driver has failed to complete a power IRP within a specific time.
    Arguments:
    Arg1: 0000000000000003, A device object has been blocking an Irp for too long a time
    Arg2: 0000000000000000, Physical Device Object of the stack
    Arg3: 0000000000000000, nt!TRIAGE_9F_POWER on Win7 and higher, otherwise the Functional Device Object of the stack
    Arg4: 0000000000000000, The blocked IRP
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip
    

    【讨论】:

    • 非常感谢!复制 dll 后,我现在得到文本描述。另一个提示是它被构建到 x64 版本。
    • 好的,如果它解决了问题,标记它
    • 32 位 64 位具有单独的 dll 构建和复制相关 dll。还要检查 LoadExtension()。 ,调用扩展()。方法
    猜你喜欢
    • 2017-03-27
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    • 1970-01-01
    • 2013-06-06
    • 2020-12-13
    相关资源
    最近更新 更多