許多驅動程式都會提供 錯誤檢查回呼例程。 當 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)ReasonSpecificData 的 Guid 欄位所指定。
.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::StartEnumTagged、 IDebugDataSpaces3::GetNextTagged 和 IDebugDataSpaces3::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 不會重複執行停止程序的某些部分,例如,它不會寫入第二個當機記憶體傾印檔。 藍色畫面上顯示的停止代碼將是第二個問題檢查碼。 如果有附加內核調試器,通常會顯示關於兩次錯誤檢查的訊息。