Lettura dei dati di controllo dei bug

Molti driver forniscono routine di callback di controllo dei bug. Quando Windows genera un controllo di 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 usa KBUGCHECK_CALLBACK_ROUTINE
I dati scritti da questa routine diventano parte dei dati di callback. I dati non sono inclusi nel file di dump di arresto anomalo.

BugCheckSecondaryDumpDataCallback usare KBUGCHECK_REASON_CALLBACK_ROUTINE
I dati scritti da questa routine diventano parte dei dati di callback secondari. I dati vengono inclusi nel file di dump di arresto anomalo.

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

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

  • Se si esegue il debug live di un sistema anomalo, i dati di callback già scritti da BugCheckCallback o specificati da BugCheckAddPagesCallback saranno disponibili. 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 di memoria completo o di dump della memoria kernel, i dati di callback specificati da BugCheckAddPagesCallback e i dati di callback secondari scritti da BugCheckSecondaryDumpDataCallback saranno disponibili. 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. I dati di callback secondari saranno disponibili.

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

Visualizzazione dei dati di Callback

Per visualizzare i dati del callback 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 quando tale routine è stata registrata.

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 viene identificato da un tag GUID. Questo tag viene specificato dal campo Guid KBUGCHECK_SECONDARY_DUMP_DATA del parametro 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 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 i metodi nel file di intestazione dbgeng.h. Per informazioni dettagliate, vedere Scrittura di nuove estensioni del debugger.

Se si conosce il tag GUID del blocco 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 buffersize troppo piccolo, ReadTagged avrà esito positivo, ma scriverà solo il numero richiesto di byte nel buffer. Se si specifica un 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, il primo blocco corrispondente verrà restituito 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;

Routine di debug del 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 un secondo controllo di bug, questa nuova verifica di bug verrà elaborata prima. Tuttavia, Windows non ripeterà alcune parti del processo Stop, ad esempio non scriverà un secondo file di dump di arresto anomalo. Il codice Stop visualizzato nella schermata blu sarà il secondo codice di controllo di bug. Se un debugger del kernel è collegato, i messaggi relativi a entrambi i controlli di bug verranno in genere visualizzati.