A lot of developers have a great experience with KMDF, but then they sometimes hit a wall. They add a chunk of code and the drivers start failing because something in the new code was not implemented correctly. The first question that comes to mind is "how do I figure out what went wrong?"
The framework team realized that this would be a very common occurrence so we made it a policy to log (using WPP) every error returned by the framework. WPP is cool technology, but if you don't have an application listening to the logger, the log entries are lost. Furthermore, if there is a crash, it is hard to get at the log itself. To solve these 2 issues, KMDF keeps a history of each driver's log. The history is about 100 entries long (you can specify a longer history using the registry).
Viewing the log
First you need to load the KMDF debugger extension, wdfkd.dll. The debugger packages that you download from WHDC contain a copy of this DLL, but they are usually out of date. The DLL is also shipped as a part of the KMDF distribution and the WDK. You should use distribution/WDK version of the DLL for now until things stabilize and both the debugger and WDK eventually ship with the same DLL. Here are the steps you should follow to view the log:
- Load the correct symbols. Set your symbol path for the WDF binaries and make sure that your driver's symbols are loaded.
- Load the correct DLL. This means using a fully qualified path name when running the !load command
- Set the TMF search path. KMDF v1.5 changed the way you set the TMF search path, so you must issue a different command KMDF v1.0 and v1.1
- Execute !wdflogdump
Before we proceed, there are a few generic substitutions that you will have to make when running these commands. Each substitution phrase is in <term>. It is up to you replace these phrases with the appropriate values on your installation.
|<arch>||Architecture of the target||x86, i386, amd64, or ia64|
|<build-type>||Type of build, either debug or retail||chk or fre|
|<DDK-root>||The root directory of your DDK/WDK install||C:\WinDDK|
|<DDK-build>||The build number of your DDK/WDK||3790.1830 (Server 2003 SP1), 2195 (XP), etc|
|<driver>||Your driver's name without the '.sys' extension||foo if you driver's image name is foo.sys|
1) Load the correct symbolsYou need to add the DDK/WDK symbol path to your debugger. For V1.0 and V1.1 DDK, the path is <DDK-root>\wdf\kmdf10\symbols\<arch><build-type>\wdf. As an example, the path would be C:\WinDDK\wdf\KMDF10\symbols\x86fre\wdf on my machine when debugging an x86 fre version of KMDF. Currently the beta versions of the WDK are not shipping with the symbols for KMDF, so you must use the symbols for your beta Vista install or use the v1.1 bits.
For V1.0 and V1.1 you will also need to make sure your driver's symbols are loaded since the debugger extension needs to resolve a symbol in your driver. V1.5 removes this requirement and you just need to have KMDF symbols setup properly.
2) Loading the correct wdfkd.dllTo load the correct version of wdfkd.dll you need to specify the fully qualified path to the DLL. For v1.0 and v1.1, it is <DDK-root>\wdf\kmdf10\bin\<arch>, where <arch> in this case is the machine type which is running the debugger (vs the machine being debugged). Here is how I load the extension on my machine:
0:000> !load c:\WinDDK\wdf\KMDF10\bin\x86\wdfkd.dllTo load the DLL from the WDK, the fully qualified path is different, it is <DDK-root><DDK-build>\bin\<arch>. Here is how I load the extension on my machine:
1: kd> !load c:\WinDDK\5461\bin\x86\wdfkd.dll
If you are having issues with which version is being loaded you have a couple of options. The first is to execute the .chain command in the debugger. This will list all loaded extensions. You can look through the list and see if there is more then one version of wdfkd.dll loaded. Second, you can copy the DDK/WDK version of the DLL over the debugger's version of the DLL. If you choose this option, you should make a backup copy of the original DLL.
3) Setting the TMF search path
To set the path for v1.0 , you use the !wdfsearchpath command. The TMF path is <DDK-root>\wdf\kmdf10\symbols\<arch>\<build-type>\wdf\tmf.
For v1.1 and v1.5 the !wdftmffile command should be used instead instead.
- v1.1: the TMF file is located at <DDK-root>\wdf\kmdf10\symbols\<arch>\<build-type>\wdf\tmf\wdf010001.tmf.
- v1:5: the TMF file is located at <DDK-root><DDK-build>\tools\tracing\<arch>\wdf01005.tmf.
Here are examples of all 3 variations, notice that I am using the fully qualified path name when executing the command and that the command echoes back the path.
1: kd> !c:\WinDDK\wdf\KMDF10\bin\x86\wdfkd.wdfsearchpath c:\WinDDK\wdf\KMDF10\symbols\x86fre\wdf\tmf
wdftrace: searchpath is: c:\WinDDK\wdf\KMDF10\symbols\x86fre\wdf\tmf
1: kd> !c:\WinDDK\wdf\KMDF10\bin\x86\wdfkd.wdftmffile c:\WinDDK\wdf\KMDF10\symbols\x86fre\wdf\tmf\wdf01001.tmf
Set TMF file name is : 'C:\WinDDK\wdf\KMDF10\symbols\x86fre\wdf\tmf\wdf01001.tmf
1: kd> !c:\WinDDK\5461\bin\x86\wdfkd.wdftmffile C:\WinDDK\5461\tools\tracing\i386\wdf01005.tmf
Set TMF file name is : 'C:\WinDDK\5461\tools\tracing\i386\wdf01005.tmf'
4) Execute !wdflogdumpThis is the same for all versions. The syntax for this command is !wdflogdump <driver>. Here is the output from the osrusbfx2 example using KMDF v1.1 (and again note the fully qualified path for the DDL):
1: kd> !c:\WinDDK\wdf\KMDF10\bin\x86\wdfkd.wdflogdump osrusbfx2
Trace searchpath is: c:\WinDDK\wdf\KMDF10\symbols\x86fre\wdf\tmf
Trace format prefix is: %7!u!: %!FUNC! -
Log at a400b000
Gather log: Please wait, this may take a moment (reading 4032 bytes).
% read so far ... 10, 20, 30, 40, 100
There are 47 log entries
--- start of log ---
1: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x5BFF06B8 !devobj 0xA400F128 entering PnP State WdfDevStatePnpInit from WdfDevStatePnpObjectCreated
2: FxPkgPnp::Dispatch - WDFDEVICE 0x5BFF06B8 !devobj 0xA400F128, IRP_MJ_PNP, 0x00000000(IRP_MN_START_DEVICE) IRP 0x87F7B5D0