Skip to Main Content
Perplexed Owl Random Ponderings

Benjamin ‘Benilda’ Key:

Useful WinDBG Commands

This article contains information on WinDBG commands that I find to be useful when analyzing a crash dump. It also contains links to web pages where more information can be found. I wrote this article in part to serve as notes so that I do not have to look for the information every time I need to analyzing a crash dump. Now I can just refer to this web page.

I am sharing the article on my website in the hopes that other may find it to be useful as well.

The Windows Debugger (WinDBG) is one component of the Debugging Tools for Windows. It “can be used to debug kernel-mode and user-mode code, analyze crash dumps, and examine the CPU registers while the code executes.” A great deal of documentation on using WinDBG can be found on the Internet. One excellent resource to help you get started is Getting Started with Windows Debugging. The simplest way to install Debugging Tools for Windows is to install the Windows 10 SDK.

Configuration

Unfortunately, WinDBG is not as easy to use as the Visual Studio debugger. When you build something with Visual Studio debugging it is easy; you simply use the Debug/Start Debugging menu item (or press F5) or use the Debug/Attach to Process… menu item (or press Ctrl+Alt+P). You set a break point by pressing F9 on a line of code. To Step Over you press F10. To Step Into you press F11.

I have been using the Visual Studio debugger since the bad old days of Visual C++ 1.52. I also used Visual C++ 6, Visual Studio 2003, Visual Studio 2005, Visual Studio 2010, Visual Studio 2013, Visual Studio 2015, Visual Studio 2017, and Visual Studio 2019. I love Visual Studio. In my opinion Visual Studio has the best damned debugger out there. It does not have all the features of WinDBG but it is simple to use and has enough features for most of my work.

In Visual Studio you do not need to do anything to tell it where your source code or symbol files are. It already knows and everything just works.

My first complaint when I was introduced to WinDBG was that WinDBG knows nothing at all out of the box. You have to tell it where to find your source code. You have to tell it where to find your symbol files. When your source code and symbol files are in 100 different directories in a complex directory hierarchy and on a number of symbol servers, this is annoying and tedious.

I still do not know an easy way to tell WinDBG how to find your source code. I will have to update this article when I learn how.

However, I have devised a easy way of telling WinDBG how to find your debugging symbols.

I wrote ConfigureDebuggingToolsX64.bat to do this for me. You can download the file using the link. For your convenience I have included the file below.


@echo off

rem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
rem This batch file sets various useful environment variables that make it easier to
rem use WinDBG. It also adds the directory containing WinDBG to the path.
rem
rem You should customize the batch file to meet your needs. Then when you want to
rem use WinDBG, simply run this batch file from the command prompt and then start
rem WinDBG from that command prompt.
rem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

rem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
rem You should modify the following environment variables to meet your needs.
rem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

rem Set the LOCAL_SYMBOL_PATH environment variable to a ; delimited list of
rem directories where rarely modified symbols are kept. I typically set this
rem environment variable to the list of directories where vcpkg stores the PDB files.
rem
rem You may also want to include the directories where your build system places symbol
rem files in this list.
set LOCAL_SYMBOL_PATH=D:\vcpkg\installed\x64-windows\debug\bin;D:\vcpkg\installed\x86-windows\debug\bin

rem Set the LOCAL_SYMBOL_CACHE environment variable to the directory where you want
rem the various symbol files that are downloaded from symbol files to be stored.
set LOCAL_SYMBOL_CACHE=%SystemDrive%\SymbolCache

rem Set the COMPANY_SYMBOL_SERVER environment variable to the URL of the symbol
rem server used by your company.
set COMPANY_SYMBOL_SERVER=http://symproxy.mycompany.com/symbols

rem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
rem You should not need to modify the environment variables below this line.
rem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

title Debugging Tools for Windows x64 Command Prompt

echo Setting environment variables for Debugging Tools for Windows.

rem Add the directory containing WinDBG to the path.
set PATH=%PATH%;C:\Program Files (x86)\Windows Kits\10\Debuggers\x64

rem Specify symbol file locations.
set _NT_SYMBOL_PATH=%LOCAL_SYMBOL_PATH%;SRV*%LOCAL_SYMBOL_CACHE%*%COMPANY_SYMBOL_SERVER%;SRV*%LOCAL_SYMBOL_CACHE%*http://msdl.microsoft.com/download/symbols;SRV*%LOCAL_SYMBOL_CACHE%*https://chromium-browser-symsrv.commondatastorage.googleapis.com;SRV*%LOCAL_SYMBOL_CACHE%*https://symbols.mozilla.org;SRV*%LOCAL_SYMBOL_CACHE%*https://driver-symbols.nvidia.com;SRV*%LOCAL_SYMBOL_CACHE%*https://download.amd.com/dir/bin;SRV*%LOCAL_SYMBOL_CACHE%*https://software.intel.com/sites/downloads/symbols

This batch file assumes that you are using a 64-bit version of Windows, the Windows 10 SDK was installed in the default location, and you installed the Debugging Tools for Windows component.

To use this batch file simply make any necessary changes to the LOCAL_SYMBOL_PATH, LOCAL_SYMBOL_CACHE, and COMPANY_SYMBOL_SERVER environment variables. The open the Command Prompt and run the batch file. This will set the _NT_SYMBOL_PATH environment variable which tells WinDBG where to find the symbol files and ensure that the directory containing WinDBG.exe is included in your path. Then run WinDBG from the command prompt.

Commands

This article is not meant to be a tutorial on how to use WinDBG to debug a program or to analyze a crash dump. For a tutorial on using WinDBG to debug a program see Getting Started with WinDBG (User-Mode). For a tutorial on using WinDBG to analyze a crash dump see Analyze crash dump files by using WinDBG. The book Advanced Windows Debugging: Developing and Administering Reliable, Robust, and Secure Software by Daniel Pravat and Mario Hewardt is an in-depth, real-world, insider’s guide to Windows debugging using the Debugging Tools for Windows.

This article is meant to provide an introduction and a list of commands that I find to be useful when analyzing a crash dump, which is my most common use case for using WinDBG.

So, without any further delay, here are the WinDBG commands I find to be most useful.

Command Description
!analyze -v

The !analyze extension displays information about the current exception or bug check.

The -v option displays verbose output.

!findstack The !findstack extension locates all of the stacks that contain a specified symbol or module.
!sym noisy

The !sym extension controls noisy symbol loading and symbol prompts.

The noisy parameter ctivates noisy symbol loading.

.ecxr The .ecxr command displays the context record that is associated with the current exception.
.exr

The .exr command displays the contents of an exception record.

The .exr command takes one parameter, the Address parameter. The Address parameter Specifies the address of the exception record. If you specify -1 as the address, the debugger displays the most recent exception.

.reload /f

The .reload command deletes all symbol information for the specified module and reloads these symbols as needed. In some cases, this command also reloads or unloads the module itself.

The /f option forces the debugger to immediately load the symbols. This parameter overrides lazy symbol loading.

.srcfix The .srcfix and .lsrcfix commands automatically set the source path to indicate that a source server will be used.
~ (Thread Status)

The tilde (~) command displays status for the specified thread or for all threads in the current process.

The ~* command displays all threads.

kc, kp, kP

The k* commands display the stack frame of the given thread, together with related information.

The kc command1 displays a clean stack trace. Each display line includes only the module name and the function name.

The kp command2 displays all of the parameters for each function that is called in the stack trace. The parameter list includes each parameter’s data type, name, and value. The command is case sensitive. This command requires full symbol information.

There is very little available information on how to read the output of the kp command.3 However, the following helpful tip may be of use to you.

The general format of a line in the call stack seems to be the following.

${Addr} ${Mod}!${Func}+${Offset}

Sometimes the format is as follows.

${Addr} ${Mod}!${Func}+${Offset} [${Path} @ ${Num}]

Where:

  • Addr: Memory address information or more precisely a child stack pointer and current instruction pointer for the frame.
  • Mod: Module Name
  • Func: Function Name
  • Offset: Offset after method start.
  • Path: Partial or full path to source code file.
  • Num: Line number in the file referenced by Path.

The kP command is similar to the kp command. This command displays all of the parameters for each function that is called in the stack trace, like the kp command. However, for the kP command, the function parameters are printed on a second line of the display, instead of on the same line as the rest of the data.

Note that the k command can be combined with the ~* command as follows: ~*k. This causes the call stack to be displayed for all threads. The is true for all versions of the k command.


  1. Technically the command is k and the second letter is a parameter that occurs just after the command. It took me awhile to figure this out. Logically there should be a separator between the command and parameter and if it is all runs together it is a command, not a one character command immediately followed by a one character parameter.↩︎

  2. Technically the command is k and the second letter is a parameter that occurs just after the command. It took me awhile to figure this out. Logically there should be a separator between the command and parameter and if it is all runs together it is a command, not a one character command immediately followed by a one character parameter.↩︎

  3. I have not been able to find any official documentation on the format of the kp command output. You would think that Microsoft would provide a clearly marked “Call Stack Format” or “How to Read the Call Stack” section on the k, kb, kc, kd, kp, kP, kv (Display Stack Backtrace) page but that would be too easy. The EXAMPLE STACK TRACE section of Windows Stack Trace Fundamentals provides some information. The answer to the Understanding Windbg output from call stack question on Stack Overflow provides more information.↩︎

Back to top