Condividi tramite


Lettura dei dati di callback di controllo dei bug

Molti driver forniscono routine di callback di controllo dei bug. Quando Windows rilascia un controllo dei bug, chiama queste routine prima di arrestare il sistema. Queste routine possono specificare e scrivere in aree di memoria note come dati di callback e dati di callback secondari.

BugCheckCallback usare KBUGCHECK_CALLBACK_ROUTINE
I dati scritti da questa routine diventano parte dei dati di callback. I dati non sono inclusi nel file di dump del crash.

BugCheckSecondaryDumpDataCallback utilizza KBUGCHECK_REASON_CALLBACK_ROUTINE
I dati scritti da questa routine diventano parte dei dati di callback secondari. I dati sono inclusi nel file di dump di arresto anomalo del sistema.

BugCheckAddPagesCallback utilizza KBUGCHECK_REASON_CALLBACK_ROUTINE
Le pagine specificate da questa routine diventano parte dei dati di callback. I dati in queste pagine sono inclusi nel file di dump di arresto anomalo del sistema.

La quantità di dati di callback e callback secondari disponibili per il debugger dipende da diversi fattori:

  • Se si esegue il debug in tempo reale di un sistema in arresto anomalo, saranno disponibili i dati di callback già scritti da BugCheckCallback o specificati da BugCheckAddPagesCallback . I dati di callback secondari non saranno disponibili, perché non vengono archiviati in alcuna posizione di memoria fissa.

  • Se si esegue il debug di un dump completo della memoria o del dump della memoria del kernel, saranno disponibili i dati di callback specificati da BugCheckAddPagesCallback e i dati di callback secondari scritti da BugCheckSecondaryDumpDataCallback . I dati di callback scritti da BugCheckCallback non saranno disponibili.

  • Se si esegue il debug di un dump di memoria di piccole dimensioni, i dati di callback non saranno disponibili. Saranno disponibili dati di callback secondari.

Per altri dettagli su queste diverse dimensioni dei file di dump, vedere Varietà di file di dump Kernel-Mode .

Visualizzazione dei dati di callback

Per visualizzare i dati di callback di controllo dei bug, è possibile usare l'estensione !bugdump .

Senza parametri, !bugdump visualizzerà i dati per tutti i callback.

Per visualizzare i dati per una routine di callback specifica, usare !bugdumpComponent, dove Component è lo stesso parametro passato a KeRegisterBugCheckCallback al momento della registrazione di tale routine.

Visualizzazione dei dati di callback secondari

Esistono due metodi per visualizzare i dati di callback secondari. È possibile usare il comando con estensione enumtag oppure scrivere un'estensione del debugger personalizzata.

Ogni blocco di dati di callback secondario è identificato da un tag GUID. Questo tag viene specificato dal campo Guid del parametro (KBUGCHECK_SECONDARY_DUMP_DATA)ReasonSpecificData passato a BugCheckSecondaryDumpDataCallback.

Il comando .enumtag (Enumerate Secondary Callback Data) non è uno strumento molto preciso. Visualizza ogni blocco di dati secondario, che mostra il tag e quindi mostra i dati in formato esadecimale e ASCII. In genere è utile solo per determinare quali tag vengono effettivamente usati per i blocchi di dati secondari.

Per usare questi dati in modo più pratico, è consigliabile scrivere un'estensione del debugger personalizzata. Questa estensione deve chiamare metodi nel file di intestazione denominato dbgeng.h. Per informazioni dettagliate, vedere Scrittura di nuove estensioni del debugger.

Se si conosce il tag GUID del blocco di dati secondario, l'estensione deve usare il metodo IDebugDataSpaces3::ReadTagged per accedere ai dati. Il suo prototipo è il seguente:

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

Ecco un esempio di come usare questo metodo:

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

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

Se si specifica un valore BufferSize troppo piccolo, ReadTagged avrà esito positivo, ma scriverà solo il numero di byte richiesto nel buffer. Se si specifica un valore BufferSize troppo grande, ReadTagged avrà esito positivo ma scriverà solo le dimensioni effettive del blocco nel buffer. Se si specifica un puntatore per TotalSize, ReadTagged lo userà per restituire le dimensioni del blocco effettivo. Se non è possibile accedere al blocco, ReadTagged restituirà un codice di stato di errore.

Se due blocchi hanno tag GUID identici, verrà restituito il primo blocco corrispondente e il secondo blocco sarà inaccessibile.

Se non si è certi del tag GUID del blocco, è possibile usare i metodi IDebugDataSpaces3::StartEnumTagged, IDebugDataSpaces3::GetNextTagged e IDebugDataSpaces3::EndEnumTagged per enumerare i blocchi contrassegnati. I loro prototipi sono i seguenti:

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;

Debug delle routine di callback

È anche possibile eseguire il debug della routine di callback stessa. I punti di interruzione all'interno delle routine di callback funzionano esattamente come qualsiasi altro punto di interruzione.

Se la routine di callback causa una seconda verifica degli errori, questa nuova verifica degli errori verrà elaborata per prima. Tuttavia, Windows non ripeterà determinate parti del processo di arresto; ad esempio, non scriverà un secondo file di dump di crash. Il codice stop visualizzato nella schermata blu sarà il secondo codice di controllo dei bug. Se un debugger del kernel è collegato, i messaggi relativi a entrambi i controlli di bug verranno in genere visualizzati.