How To Use the Kernel Debugger to Debug Driver Initialization

Last reviewed: January 23, 1996
Article ID: Q141470
The information in this article applies to:
  • Microsoft Windows NT Workstation versions 3.5 and 3.51
  • Microsoft Windows NT Server versions 3.5 and 3.51

SUMMARY

When you debug problems with Windows NT, it is sometimes necessary to identify variables or data structures created when Kernel-mode drivers are initialized. This is a problem, because the Kernel Debugger (I386KD, ALPHAKD, MIPSKD and PPCKD) only allow break points to be set when the symbols are loaded, and symbols can only be loaded when their respective driver is loaded. The following procedure explains how to get around this situation and how to trace DriverEntry(), which is the first function called for each driver by the Windows NT I/O manager at boot up.

NOTE: The GUI version of the debugger (WINDBG) allows for breakpoints to be kept during a remote reboot of Windows NT, but other problems with that version of the debugger usually require that the console debuggers (mentioned above) be used.

MORE INFORMATION

  1. Make sure that the connection between your local debugger and the remote machine is established and configured properly. To do this, you may want to break into the target and unassemble some kernel functions (such as NtUnlockFile()). Also make sure the modem at the target machine is set to stay enabled on loss of DTR, so your connection is not cut off when the target machine reboots

  2. Issue the "!drivers" command to obtain the list of loaded drivers. Note the sequence in which they appear, as this is the sequence in which they are loaded after rebooting. Make a note of the driver that precedes the one you need to debug.

  3. Reboot the target computer (.reboot). The symbols are unloaded.

  4. As soon as you see the symbols for NTOSKRNL.EXE loading (this is echoed to your screen only if you have started the debugger with the "-v" switch), Press CTRL+C to break into the target.

  5. Set a break point on IopLoadDriver. This breaks into the system each time a driver is about to be loaded.

  6. Let the target continue ("g") until you hit this break point after the preceding driver (see step 1) is loaded. Your driver is now about to be loaded.

  7. Set a break point on MmLoadSystemImage.

  8. The debugger now breaks every time information is loaded from the disk into memory (which can happen several times for a single driver).

  9. Let the target run to the return address of MmLoadSystemImage, by using the "g" command with the RetAddr for MmLoadSystemImage (For example: g 8015b677). This return address should take you back into IopLoadUnloadDriver or IopLoadDriver. You may need to repeat this step several times until you see the symbols for your driver being loaded.

This takes you to a break point where the symbols for the driver are loaded, but DriverEntry() has not been called yet. You can now set any BP you need for this driver, including on DriverEntry().

NOTE: An alternative procedure is as follows:

  1. Make sure that the connection between your local debugger and the remote machine is established and configured properly. To do this, you may want to break into the target and unassemble some kernel functions (such as NtUnlockFile()). Also make sure the modem at the target machine is set to stay enabled on loss of DTR, so your connection is not cut off when the target machine reboots

  2. Issue the "!drivers" command to obtain the list of loaded drivers. Note the sequence in which they appear, as this is the sequence in which they are loaded after rebooting. Make a note of the driver that precedes the one you need to debug.

  3. Reboot the target computer (.reboot). The symbols are unloaded.

  4. As soon as you see the symbols for NTOSKRNL.EXE loading (this is echoed to your screen only if you have started the debugger with the "-v" switch), Press CTRL+C to break into the target.

  5. Issue "g MmLoadSystemImage", do "t" once and get the stack frame:

          kd> t
    
          8016651e 55               push    ebp
    
          kd> k
          ChildEBP RetAddr
          ff67ab90 8015b677 ntoskrnl!_MmLoadSystemImage+0x6
          ff67ac14 801aece1 ntoskrnl!_IopLoadDriver+0x293
          ff67ac38 801ac56e ntoskrnl!_IopInitializeSystemDrivers+0x7f
          ff67ad6c 801ab879 ntoskrnl!_IoInitSystem+0x3af
          ff67af4c 80132910 ntoskrnl!_Phase1Initialization+0x475
          ff67af7c 8013cf4e ntoskrnl!_PspSystemThreadStartup+0x40
          00000000 00000000 ntoskrnl!_KiThreadStartup+0x16
    
    

  6. Set a breakpoint at the return address of MmLoadSystemImage:

          kd> bp 8015b677
    

  7. Issue "g". The debugger will now break after loading a driver image. When you see the symbols loaded of the driver you want to debug, set a breakpoint on its DriverEntry function.


KBCategory: kbhowto
KBSubcategory: nthowto
Additional reference words: prodnt 3.50 3.51


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: January 23, 1996
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.