共用方式為


讀取錯誤檢查回呼資料

許多驅動程式都會提供 錯誤檢查回呼例程。 當 Windows 發出錯誤檢查時,它會在關閉系統之前呼叫這些例程。 這些例程可以指定和寫入記憶體區域,稱為回呼數據和次要回呼數據

BugCheckCallback 使用 KBUGCHECK_CALLBACK_ROUTINE
這個例程所撰寫的數據會成為 回呼數據的一部分。 當機轉儲檔案中不包含數據。

BugCheckSecondaryDumpDataCallback 使用 KBUGCHECK_REASON_CALLBACK_ROUTINE
這個例程所撰寫的數據會成為 次要回呼數據的一部分。 數據會包含在損毀傾印檔案中。

BugCheckAddPagesCallback 使用 KBUGCHECK_REASON_CALLBACK_ROUTINE
這個例程所指定的頁面會成為 回呼數據的一部分。 這些頁面中的數據會包含在故障轉儲檔案中。

除錯程式可用的回呼和次要回呼資料量取決於幾個因素:

  • 如果您正在執行損毀系統的即時偵錯,則已由 BugCheckCallback 寫入或由 BugCheckAddPagesCallback 指定的回呼數據將可供使用。 次要回調數據將無法使用,因為它不會儲存在任何固定記憶體位置中。

  • 如果您正在偵錯完整記憶體傾印或核心記憶體傾印,則由 BugCheckAddPagesCallback 指定的回呼資料以及由 BugCheckSecondaryDumpDataCallback 寫入的次要回呼資料將可供使用。 BugCheckCallback 所寫入的回呼數據將不可用。

  • 如果您要偵錯小型記憶體傾印檔,回呼資料將無法取得。 次要回呼數據將可供使用。

如需這些不同傾印檔案大小的詳細資訊,請參閱 Kernel-Mode 傾印檔案的品種

顯示回調資料

若要顯示 Bug 檢查回呼資料,您可以使用 !bugdump 擴充功能。

如果沒有任何參數, !bugdump 將會顯示所有回呼的數據。

若要檢視一個特定回呼例程的數據,請使用 !bugdump元件,其中 Component 是註冊該例程時傳遞給 KeRegisterBugCheckCallback 的相同參數。

顯示次要回呼數據

顯示次要回呼數據的方法有兩種。 您可以使用 .enumtag 命令,也可以撰寫自己的調試程式延伸模組。

次要回呼數據的每個區塊都會由 GUID 標記識別。 這個標記由傳遞到 BugCheckSecondaryDumpDataCallback 的參數 (KBUGCHECK_SECONDARY_DUMP_DATA)ReasonSpecificDataGuid 欄位所指定。

.enumtag (列舉次要回呼數據) 命令不是一個非常精確的工具。 它會顯示每個次要數據區塊,顯示標記,然後以十六進位和 ASCII 格式顯示數據。 通常只有在判斷哪些標籤實際用於次要數據區塊時才有用。

若要以更實用的方式使用此數據,建議您撰寫自己的調試程序擴充功能。 此延伸模組必須呼叫 dbgeng.h 頭檔中的方法。 如需詳細資訊,請參閱 撰寫新的調試程式延伸模組

如果您知道次要數據區塊的 GUID 標記,擴充功能應該使用 IDebugDataSpaces3::ReadTagged 方法來存取數據。 其原型如下所示:

STDMETHOD(ReadTagged)(
    THIS_
    IN LPGUID Tag,
    IN ULONG Offset,
    OUT OPTIONAL PVOID Buffer,
    IN ULONG BufferSize,
    OUT OPTIONAL PULONG TotalSize
    ) PURE; 

以下是如何使用此方法的範例:

UCHAR RawData[MY_DATA_SIZE];
GUID MyGuid = .... ;

Success = DataSpaces->ReadTagged(  &MyGuid,  0,  RawData,
                                   sizeof(RawData),  NULL); 

如果您提供的 BufferSize 太小, ReadTagged 將會成功,但只會將要求的位元組數目寫入 Buffer。 如果您指定的 BufferSize 太大, ReadTagged 將會成功,但只會將實際的區塊大小寫入 Buffer。 如果您提供 TotalSize 的指標, ReadTagged 會使用它來傳回實際區塊的大小。 如果無法存取區塊, ReadTagged 會傳回失敗狀態代碼。

如果兩個區塊具有相同的 GUID 標記,則會傳回第一個相符區塊,而第二個區塊將無法存取。

如果您不確定區塊的 GUID 標記,您可以使用 IDebugDataSpaces3::StartEnumTaggedIDebugDataSpaces3::GetNextTaggedIDebugDataSpaces3::EndEnumTagged 方法來列舉標記區塊。 其原型如下所示:

STDMETHOD(StartEnumTagged)(
    THIS_
    OUT PULONG64 Handle
    ) PURE;

STDMETHOD(GetNextTagged)(
    THIS_
    IN ULONG64 Handle,
    OUT LPGUID Tag,
    OUT PULONG Size
    ) PURE;

STDMETHOD(EndEnumTagged)(
    THIS_
    IN ULONG64 Handle
    ) PURE;

偵錯回撥程序

您也可以偵錯回呼例程本身。 回呼函式內的斷點就像任何其他斷點一樣運作。

如果回呼例程造成第二個錯誤檢查,則會先處理這個新的錯誤檢查。 不過,Windows 不會重複執行停止程序的某些部分,例如,它不會寫入第二個當機記憶體傾印檔。 藍色畫面上顯示的停止代碼將是第二個問題檢查碼。 如果有附加內核調試器,通常會顯示關於兩次錯誤檢查的訊息。