Compartir a través de


Depuración de fugas de memoria: DRIVER_VERIFIER_DETECTED_VIOLATION (C4): 0x62

El comprobador de controladores genera la comprobación de errores 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION con un valor de parámetro 1 de 0x62 cuando un controlador se descarga sin liberar primero todas sus asignaciones de grupo. Las asignaciones de memoria sin frecuencia (también denominadas fugas de memoria) son una causa común del rendimiento del sistema operativo reducido. Pueden fragmentar los grupos del sistema y, finalmente, provocar bloqueos del sistema.

Cuando tiene un depurador de kernel conectado a un equipo de prueba que ejecuta El comprobador de controladores, si el comprobador de controladores detecta una infracción, Windows se divide en el depurador y muestra una breve descripción del error.

>Depuración de pérdidas de memoria en la descarga del controlador

Use !analyze para mostrar información sobre la comprobación de errores

Al igual que sucede con cualquier comprobación de errores que se produzca, una vez que tenga control del depurador, el primer paso es ejecutar el comando !analyze -v .

kd> !analyze -v
Connected to Windows 8 9600 x86 compatible target
Loading Kernel Symbols
.................................................................................
Loading User Symbols
.......................
Loading unloaded module list
........
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

DRIVER_VERIFIER_DETECTED_VIOLATION (c4)
A device driver attempting to corrupt the system has been caught.  This is
because the driver was specified in the registry as being suspect (by the
administrator) and the kernel has enabled substantial checking of this driver.
If the driver attempts to corrupt the system, bugchecks 0xC4, 0xC1 and 0xA will
be among the most commonly seen crashes.
Arguments:
Arg1: 00000062, A driver has forgotten to free its pool allocations prior to unloading.
Arg2: 9707712c, name of the driver having the issue.
Arg3: 9c1faf70, verifier internal structure with driver information.
Arg4: 00000003, total # of (paged+nonpaged) allocations that weren't freed.
    Type !verifier 3 drivername.sys for info on the allocations
    that were leaked that caused the bugcheck.

Un 0xC4 de comprobación de errores: DRIVER_VERIFIER_DETECTED_VIOLATION con un valor de parámetro 1 (Arg1) de 0x62 se describe de la siguiente manera:

DRIVER_VERIFIER_DETECTED_VIOLATION (C4) Arg1 Arg2 Arg3 Arg4 Cause Driver Verifier flags 0x62 Nombre del controlador. Número total reservado de asignaciones que no se liberaron, incluido el grupo paginado y no paginado. El controlador se descarga sin liberar primero sus asignaciones de grupo. En Windows 8.1, esta comprobación de errores también se producirá si el controlador se ha descargado sin liberar primero ningún elemento de trabajo (IO_WORKITEM) que haya asignado con IoAllocateWorkItem. Una comprobación de errores con este parámetro solo se produce cuando la opción Pool Tracking está activa. Especifique El seguimiento de grupos (comprobador /flags 0x8). La opción Seguimiento de grupos está habilitada con marcas estándar (comprobador /estándar ).

Use el comando de extensión !verifier 3 para obtener información sobre las asignaciones del grupo.

Para esta comprobación de errores en particular, la información proporcionada en el parámetro 4 (Arg4) es la más importante. Arg4 muestra el número de asignaciones que no se liberaron. La salida del comando !analyze también muestra el comando de extensión del depurador !verifier que puede usar para mostrar cuáles eran esas asignaciones. La salida completa del comando !verifier 3 MyDriver.sys se muestra en el ejemplo siguiente:

kd> !verifier 3 Mydriver.sys

Verify Flags Level 0x000209bb

  STANDARD FLAGS:
    [X] (0x00000000) Automatic Checks
    [X] (0x00000001) Special pool
    [X] (0x00000002) Force IRQL checking
    [X] (0x00000008) Pool tracking
    [X] (0x00000010) I/O verification
    [X] (0x00000020) Deadlock detection
    [X] (0x00000080) DMA checking
    [X] (0x00000100) Security checks
    [X] (0x00000800) Miscellaneous checks
    [X] (0x00020000) DDI compliance checking

  ADDITIONAL FLAGS:
    [ ] (0x00000004) Randomized low resources simulation
    [ ] (0x00000200) Force pending I/O requests
    [ ] (0x00000400) IRP logging
    [ ] (0x00002000) Invariant MDL checking for stack
    [ ] (0x00004000) Invariant MDL checking for driver
    [ ] (0x00008000) Power framework delay fuzzing
    [ ] (0x00040000) Systematic low resources simulation
    [ ] (0x00080000) DDI compliance checking (additional)
    [ ] (0x00200000) NDIS/WIFI verification
    [ ] (0x00800000) Kernel synchronization delay fuzzing
    [ ] (0x01000000) VM switch verification

    [X] Indicates flag is enabled


Summary of All Verifier Statistics

  RaiseIrqls           0x0
  AcquireSpinLocks     0x0
  Synch Executions     0x0
  Trims                0x0

  Pool Allocations Attempted             0x2db1a
  Pool Allocations Succeeded             0x2db1a
  Pool Allocations Succeeded SpecialPool 0x2db1a
  Pool Allocations With NO TAG           0x0
  Pool Allocations Failed                0x0

  Current paged pool allocations         0x0 for 00000000 bytes
  Peak paged pool allocations            0x0 for 00000000 bytes
  Current nonpaged pool allocations      0x3 for 00001058 bytes
  Peak nonpaged pool allocations         0x13 for 0004A4A0 bytes

## Driver Verification List


  MODULE: 0x84226b28 MyDriver.sys (Loaded)

    Pool Allocation Statistics: ( NonPagedPool / PagedPool )

      Current Pool Allocations: ( 0x00000003 / 0x00000000 )
      Current Pool Bytes:       ( 0x00001058 / 0x00000000 )
      Peak Pool Allocations:    ( 0x00000013 / 0x00000000 )
      Peak Pool Bytes:          ( 0x0004A4A0 / 0x00000000 )
      Contiguous Memory Bytes:       0x00000000
      Peak Contiguous Memory Bytes:  0x00000000

    Pool Allocations:

      Address     Length      Tag   Caller    
      ----------  ----------  ----  ----------
      0x982a8fe0  0x00000020  VMdl  0x9a3bf6ac  MyDriver!DeviceControlDispatch
      0x8645a000  0x00001008  mdrv  0x9a3bf687  MyDriver!DeviceControlDispatch
      0x9a836fd0  0x00000030  Vfwi  0x9a3bf6ed  MyDriver!GetNecessaryObjects

Por ejemplo, el controlador, MyDriver.sys, tiene dos asignaciones de memoria y un elemento de trabajo de E/S que no se han liberado correctamente. Cada lista muestra la dirección de la asignación actual, el tamaño, la etiqueta de grupo usada y la dirección en el código de controlador donde se realizó la solicitud de asignación. Si los símbolos se cargan para el controlador en cuestión, también mostrará el nombre de la función junto a la dirección del autor de la llamada.

De las etiquetas mostradas, solo una (para la asignación en la dirección 0x8645a000) la proporcionó el propio controlador (mdrv). La etiqueta VMdl se usa cada vez que el comprobador del controlador realiza llamadas a IoAllocateMdl. Del mismo modo, la etiqueta Vfwi se usa siempre que un controlador comprobado por el Comprobador de controladores realiza una solicitud para asignar un elemento de trabajo mediante IoAllocateWorkItem.

Si tiene símbolos, puede encontrar dónde se produjeron las asignaciones de memoria en los archivos de origen.

Cuando se cargan símbolos para el controlador, si esos símbolos contienen la información del número de línea, puede usar el comando ln CallerAddress para mostrar la línea donde se realizó la llamada. Esta salida también mostrará el desplazamiento en la función que realizó la asignación.

kd> ln 0x9a3bf6ac  
d:\coding\wdmdrivers\mydriver\handleioctl.c(50)+0x15
(9a3bf660)   MyDriver!DeviceControlDispatch+0x4c   |  (9a3bf6d0)   MyDriver!DeviceControlDispatch

kd> ln 0x9a3bf687  
d:\coding\wdmdrivers\mydriver\handleioctl.c(38)+0x12
(9a3bf660)   MyDriver!DeviceControlDispatch+0x27   |  (9a3bf6d0)   MyDriver!DeviceControlDispatch

kd> ln 0x9a3bf6ed  
d:\coding\wdmdrivers\mydriver\handleioctl.c(72)+0xa
(9a3bf6d0)   MyDriver!GetNecessaryObjects+0x1d   |  (9a3bf71c)   MyDriver!GetNecessaryObjects

Examen del registro de asignaciones de memoria

El Comprobador de controladores también mantiene un registro circular de todas las asignaciones de memoria realizadas en el espacio del kernel cuando el seguimiento del grupo está habilitado. De forma predeterminada, se conservan las asignaciones más recientes de 65 536 (0x10000). A medida que se realiza una nueva asignación, se sobrescribe la asignación más antigua del registro. Si las asignaciones se realizaron recientemente antes del bloqueo, puede ser posible obtener información adicional sobre la asignación que se mostró anteriormente, específicamente la dirección del subproceso y los marcos de la pila del kernel en el momento de la asignación.

Se puede acceder a este registro mediante el comando !comprobador 0x80 AddressOfPoolAllocation. Tenga en cuenta que esto enumerará todas las asignaciones y liberaciones en el registro de esta dirección en particular. Para cancelar o detener la presentación del historial de registros, use los métodos abreviados de teclado: Ctrl + Interrumpir con WinDbg y Ctrl + C con KD.

kd> !verifier 0x80 0x982a8fe0

Log of recent kernel pool Allocate and Free operations:

There are up to 0x10000 entries in the log.

Parsing 0x00010000 log entries, searching for address 0x982a8fe0.

# 

Pool block 982a8fe0, Size 00000020, Thread 9c158bc0
81b250cd nt!IovAllocateMdl+0x3d
8060e41d VerifierExt!IoAllocateMdl_internal_wrapper+0x35
81b29388 nt!VerifierIoAllocateMdl+0x22
9a3bf6ac MyDriver!DeviceControlDispatch+0x4c
9a3bf611 MyDriver!NonPNPIRPDispatch0x51
9a3bf05a MyDriver!AllIRPDispatch+0x1a
80611710 VerifierExt!xdv_IRP_MJ_DEVICE_CONTROL_wrapper+0xd0
81b3b635 nt!ViGenericDispatchHandler+0x2d
81b3b784 nt!ViGenericDeviceControl+0x18
81b24b4d nt!IovCallDriver+0x2cc
81703772 nt!IofCallDriver+0x62
8191165e nt!IopSynchronousServiceTail+0x16e
81915518 nt!IopXxxControlFile+0x3e8

kd> !verifier 0x80 0x8645a000

Log of recent kernel pool Allocate and Free operations:

There are up to 0x10000 entries in the log.

Parsing 0x00010000 log entries, searching for address 0x8645a000.

# 

Pool block 8645a000, Size 00001000, Thread 9c158bc0
8060ee4f VerifierExt!ExAllocatePoolWithTagPriority_internal_wrapper+0x5b
81b2619e nt!VerifierExAllocatePoolWithTag+0x24
9a3bf687 MyDriver!DeviceControlDispatch+0x27
9a3bf611 MyDriver!NonPNPIRPDispatch0x51
9a3bf05a MyDriver!AllIRPDispatch+0x1a
80611710 VerifierExt!xdv_IRP_MJ_DEVICE_CONTROL_wrapper+0xd0
81b3b635 nt!ViGenericDispatchHandler+0x2d
81b3b784 nt!ViGenericDeviceControl+0x18
81b24b4d nt!IovCallDriver+0x2cc
81703772 nt!IofCallDriver+0x62
8191165e nt!IopSynchronousServiceTail+0x16e
81915518 nt!IopXxxControlFile+0x3e8
81914516 nt!NtDeviceIoControlFile+0x2a

kd> !verifier 0x80 0x9a836fd0  

Log of recent kernel pool Allocate and Free operations:

There are up to 0x10000 entries in the log.

Parsing 0x00010000 log entries, searching for address 0x9a836fd0.

# 

Pool block 9a836fd0, Size 00000030, Thread 88758740
8151713d nt!IovAllocateWorkItem+0x1b
84a133d9 VerifierExt!IoAllocateWorkItem_internal_wrapper+0x29
8151b3a7 nt!VerifierIoAllocateWorkItem+0x16
9a3bf6ed MyDriver!GetNecessaryObjects+0x1d
9a3bf620 MyDriver!NonPNPIRPDispatch0x51
9a3bf05a MyDriver!AllIRPDispatch+0x1a
84a16710 VerifierExt!xdv_IRP_MJ_DEVICE_CONTROL_wrapper+0xd0
8152d635 nt!ViGenericDispatchHandler+0x2d
8152d784 nt!ViGenericDeviceControl+0x18
81516b4d nt!IovCallDriver+0x2cc
810f5772 nt!IofCallDriver+0x62
8130365e nt!IopSynchronousServiceTail+0x16e
81307518 nt!IopXxxControlFile+0x3e8

Corrección de pérdidas de memoria

Esta comprobación de errores del comprobador de controladores está diseñada para evitar que el controlador filtre la memoria del kernel. En cada caso, la corrección adecuada es identificar las rutas de acceso de código existentes en las que los objetos asignados no están liberados y asegurarse de que se liberan correctamente.

El comprobador de controladores estáticos es una herramienta que examina el código fuente del controlador de Windows e informa sobre posibles problemas mediante la simulación del ejercicio de varias rutas de acceso de código. El comprobador de controladores estáticos es una excelente utilidad en tiempo de desarrollo para ayudar a identificar estos tipos de problemas.

Para otras técnicas que puede usar, incluidos los escenarios en los que el Comprobador de controladores no está implicado, consulte Búsqueda de una fuga de memoria en modo kernel.

Búsqueda de una pérdida de memoria en modo kernel

Comprobador de controladores estáticos

Depuración de Windows

Control de una comprobación de errores cuando el comprobador de controladores está habilitado