Microsoft Docs

Debugging and Testing Windows Drivers

This section provides comprehensive guidance on debugging and testing your Windows drivers. Effective debugging and thorough testing are crucial for developing stable, reliable, and secure drivers.

Note: Driver development requires advanced understanding of operating system internals and hardware. Always test drivers in a controlled environment before deploying to production systems.

Key Concepts and Tools

Debugging a driver differs significantly from debugging a user-mode application. Drivers run in kernel mode, meaning an error can crash the entire operating system. Therefore, specialized tools and techniques are essential.

Kernel Debugging

Kernel debugging allows you to debug a driver running in the target machine's kernel from a separate host machine. This is typically done over a serial port, network (KDNET), or USB 3.0. The primary tool for this is:

  • WinDbg Preview: The modern debugger for Windows. It supports both user-mode and kernel-mode debugging.

Setting up kernel debugging involves configuring both the host and target machines. Common connection methods include:

  • Serial Port: Requires a null-modem serial cable.
  • KDNET (Network): Uses a network connection. This is the preferred method for modern systems.
  • USB 3.0: Requires a compatible USB 3.0 cable and specific hardware support.

You'll need to enable debugging on the target machine using bcdedit commands and then connect WinDbg from the host machine.


# On the target machine to enable network debugging
bcdedit /debug on
bcdedit /set {dbgsettings} dhcp yes
# Or for static IP:
# bcdedit /set {dbgsettings} ip address:
# bcdedit /set {dbgsettings} port <PORT_NUMBER>
# bcdedit /set {dbgsettings} start kdnet

# On the host machine to connect WinDbg
windbg -k net:port=<PORT_NUMBER>,key=<KEY_VALUE>
                

Driver Verifier

Driver Verifier is a robust testing tool that runs in the background and monitors driver operations. It can detect many common driver errors, such as improper memory handling, object usage, and resource leaks, that might otherwise go unnoticed.

  • Enable: Use the verifier.exe utility from the command line or GUI.
  • Configuration: You can select specific tests to run or let Driver Verifier perform a comprehensive set of checks.
  • Impact: Enabling Driver Verifier can significantly slow down the system and may cause the system to crash more readily when errors occur, which is its intended purpose.
Tip: Always run Driver Verifier on a test system before deploying your driver to production. Enable it with default settings and gradually add more specific tests as needed.

Static Analysis Tools

These tools analyze your driver's source code without actually running it, identifying potential bugs, security vulnerabilities, and coding standard violations.

  • Static Driver Verifier (SDV): Analyzes drivers for compliance with specific Windows driver programming rules.
  • Code Analysis (Visual Studio): Built into Visual Studio, it can detect common C/C++ defects.

Testing Strategies

A multi-faceted testing approach is key to ensuring driver quality.

Unit Testing

While challenging for kernel-mode drivers due to the OS environment, some aspects can be unit tested. This usually involves mocking or simulating certain kernel services.

Integration Testing

Test how your driver interacts with other components of the operating system and hardware. This is where kernel debugging becomes invaluable.

Stress and Soak Testing

Run your driver under heavy load or for extended periods to uncover memory leaks, race conditions, and other issues that manifest over time or under stress.

Compatibility Testing

Test your driver on different versions of Windows, hardware configurations, and with other drivers installed to ensure broad compatibility.

Warning: Testing drivers on production hardware without proper precautions can lead to data loss or system instability. Always use dedicated test machines.

Common Debugging Scenarios

  • System Crashes (BSODs): Use kernel debugging to capture crash dumps and analyze the stack trace to identify the faulting driver or module.
  • Deadlocks: Analyze thread states and lock acquisition patterns during kernel debugging.
  • Memory Leaks: Use kernel debugging tools like !pool and !memusage, and static analysis tools to track down memory allocation issues.
  • Race Conditions: Carefully examine code paths that access shared resources and use synchronization primitives correctly. Debugging these can be tricky and may involve logging or specific debugger commands.

Resources