Lectura de los datos de devolución de llamada de comprobación de errores
Muchos controladores proporcionan rutinas de devolución de llamada de comprobación de errores. Cuando Windows emite una comprobación de errores, llama a estas rutinas antes de apagar el sistema. Estas rutinas pueden especificar y escribir en áreas de memoria conocidas como datos de devolución de llamada y datos de devolución de llamada secundarios.
BugCheckCallback usa KBUGCHECK_CALLBACK_ROUTINE
Los datos escritos por esta rutina forman parte de los datos de devolución de llamada. Los datos no se incluyen en el archivo de volcado de memoria.
BugCheckSecondaryDumpDataCallback usa KBUGCHECK_REASON_CALLBACK_ROUTINE
Los datos escritos por esta rutina forman parte de los datos de devolución de llamada secundarios. Los datos se incluyen en el archivo de volcado de memoria.
BugCheckAddPagesCallback usa KBUGCHECK_REASON_CALLBACK_ROUTINE
Las páginas especificadas por esta rutina forman parte de los datos de devolución de llamada. Los datos de esas páginas se incluyen en el archivo de volcado de memoria.
La cantidad de datos de devolución de llamada y de devolución de llamada secundaria que está disponible para el depurador depende de varios factores:
Si está realizando la depuración en directo de un sistema bloqueado, los datos de devolución de llamada que ya ha escrito BugCheckCallback o especificados por BugCheckAddPagesCallback estarán disponibles. Los datos de devolución de llamada secundarios no estarán disponibles, ya que no se almacenan en ninguna ubicación de memoria fija.
Si está depurando un volcado de memoria completo o un volcado de memoria del kernel, los datos de devolución de llamada especificados por BugCheckAddPagesCallback y los datos de devolución de llamada secundarios escritos por BugCheckSecondaryDumpDataCallback estarán disponibles. Los datos de devolución de llamada escritos por BugCheckCallback no estarán disponibles.
Si está depurando un pequeño volcado de memoria, los datos de devolución de llamada no estarán disponibles. Los datos de devolución de llamada secundarios estarán disponibles.
Consulte Variedades de archivos de volcado de Kernel-Mode para obtener más detalles sobre estos diferentes tamaños de archivo de volcado.
Mostrar datos de devolución de llamada
Para mostrar los datos de devolución de llamada de comprobación de errores, puede usar la extensión !bugdump .
Sin ningún parámetro, !bugdump mostrará los datos de todas las devoluciones de llamada.
Para ver los datos de una rutina de devolución de llamada específica, use !bugdumpComponent, donde Component es el mismo parámetro que se pasó a KeRegisterBugCheckCallback cuando se registró esa rutina.
Mostrar datos de devolución de llamada secundaria
Hay dos métodos para mostrar los datos de devolución de llamada secundarios. Puede usar el comando .enumtag o puede escribir su propia extensión del depurador.
Cada bloque de datos de devolución de llamada secundario se identifica mediante una etiqueta GUID. Esta etiqueta se especifica mediante el campo Guid del parámetro (KBUGCHECK_SECONDARY_DUMP_DATA)ReasonSpecificData pasado a BugCheckSecondaryDumpDataCallback.
El comando .enumtag (Enumerar datos de devolución de llamada secundarios) no es un instrumento muy preciso. Muestra todos los bloques de datos secundarios, que muestran la etiqueta y, a continuación, muestran los datos en formato hexadecimal y ASCII. Por lo general, solo resulta útil determinar qué etiquetas se usan realmente para los bloques de datos secundarios.
Para usar estos datos de forma más práctica, se recomienda escribir su propia extensión del depurador. Esta extensión debe llamar a métodos en el archivo de encabezado dbgeng.h. Para obtener más información, consulte Escritura de nuevas extensiones del depurador.
Si conoce la etiqueta GUID del bloque de datos secundario, la extensión debe usar el método IDebugDataSpaces3::ReadTagged para acceder a los datos. Su prototipo es el siguiente:
STDMETHOD(ReadTagged)(
THIS_
IN LPGUID Tag,
IN ULONG Offset,
OUT OPTIONAL PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG TotalSize
) PURE;
Este es un ejemplo de cómo usar este método:
UCHAR RawData[MY_DATA_SIZE];
GUID MyGuid = .... ;
Success = DataSpaces->ReadTagged( &MyGuid, 0, RawData,
sizeof(RawData), NULL);
Si proporciona un bufferSize demasiado pequeño, ReadTagged se realizará correctamente, pero escribirá solo el número de bytes solicitado en Buffer. Si especifica un BufferSize que es demasiado grande, ReadTagged se realizará correctamente, pero escribirá solo el tamaño de bloque real en Buffer. Si proporciona un puntero para TotalSize, ReadTagged lo usará para devolver el tamaño del bloque real. Si no se puede acceder al bloque, ReadTagged devolverá un código de estado de error.
Si dos bloques tienen etiquetas GUID idénticas, se devolverá el primer bloque coincidente y no se podrá acceder al segundo bloque.
Si no está seguro de la etiqueta GUID del bloque, puede usar los métodos IDebugDataSpaces3::StartEnumTagged, IDebugDataSpaces3::GetNextTagged e IDebugDataSpaces3::EndEnumTagged para enumerar los bloques etiquetados. Sus prototipos son los siguientes:
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;
Depuración de rutinas de devolución de llamada
También es posible depurar la propia rutina de devolución de llamada. Los puntos de interrupción dentro de las rutinas de devolución de llamada funcionan igual que cualquier otro punto de interrupción.
Si la rutina de devolución de llamada provoca una segunda comprobación de errores, esta nueva comprobación de errores se procesará primero. Sin embargo, Windows no repetirá determinadas partes del proceso de detención; por ejemplo, no escribirá un segundo archivo de volcado de memoria. El código Stop mostrado en la pantalla azul será el segundo código de comprobación de errores. Si se adjunta un depurador de kernel, normalmente aparecerán mensajes sobre ambas comprobaciones de errores.