Uncovering How Workspaces Work in WinDbg
Author - Jason Epperly
Workspaces have always been a little confusing to me. I knew how to bend them to do what I needed to get the job done, however they still remained a bit mysterious. Recently I decided to sort this out, just so I knew how they worked under the hood. But before I show you my investigation let's discuss the different types of workspaces. Windbg uses several built-in types including Base, User, Kernel, Remote, Processor Architecture, Per Dump, and Per Executable. It also uses named workspaces (or user defined workspaces). When you perform a particular type of debugging (e.g. live user-mode, post-mortem dump analysis etc.) these workspaces are combined into the final environment. Here's a diagram to illustrate the possible combination of workspaces.
- The green line is the case where WinDbg is used to open a dump file. In this scenario the Base workspace + per dump workspace is used. Note: per dump simply means each individual dump file opened gets its own workspace.
- The blue line is the scenario where WinDbg is used to live debug a running application, using the Base+User-mode workspaces.
- The orange line is an example of WinDbg used to perform a live kernel debug on an x86 machine. In this case windbg is using Base+Kernel+x86 workspaces.
From the diagram you can see windbg typically uses a combination of two workspaces. While live kernel debugging it uses three workspaces.
So what is in a workspace?
- Session Information
- All break point (bp's) and handling information for exceptions and events (sx settings).
- All open source files.
- All user-defined aliases.
- Configuration settings
- The symbol path.
- The executable image path.
- The source path.
- The current source options that were set with l+, l- (Set Source Options) .
- Log file settings.
- The COM or 1394 kernel connection settings, if the connection was started by using the graphical interface.
- The most recent paths in each Open dialog box (except for the workspace file and text file paths, which are not saved).
- The current .enable_unicode, .force_radix_output, and .enable_long_status settings.
- WinDbg graphical interface.
- The title of the WinDbg window
- The Automatically Open Disassembly setting
- The default font
- The size and position of the WinDbg window on the desktop.
- Which debugging information windows are open.
- The size and position of each open window, including the window's size, its floating or docked status, whether it is tabbed with other windows, and all of the related settings in its shortcut menu.
- The location of the pane boundary in the Debugger Command window and the word wrap setting in that window.
- Whether the toolbar and status bar, and the individual toolbars on each debugging information window, are visible.
- The customization of the Registers window.
- The flags in the Calls window, Locals window, and Watch window.
- The items that were viewed in the Watch window.
- The cursor location in each Source window.
All of these settings (except for the blue ones) are applied cumulatively (Base first, then the next workspace, etc). The blue items above are only loaded from the last workspace in the chain. To show this in action I created a simple walk through to illustrate the use of workspaces the debugger.
First I opened windbg without the use of any command line options. When it opens in this dormant state (not attached to anything and has nothing opened) its using the Base workspace. If I don't change anything (e.g. window placement) I am not prompted with any workspace dialogs when I start debugging. However if I moved the debugger's main window to any location (we will call this position 1) followed by executing any of the highlighted operations below -
I am prompted with this dialog-
Choosing "Yes" on the dialog above integrates my changes into the "Base" workspace so window position 1 is now part of my Base workspace.
Now I'm going to select "Open Executable" and browse to our old faithful target binary notepad.exe. Once the binary is opened, windbg uses Base+Notepad (per Executable file). Now I'll move the debugger's main window again (we will call this position 2) and choose the option Debug > Stop debugging. Because of the window location change, I am prompted with the following-
If I choose 'Yes', windbg will use window position 2 for anytime I open the notepad executable in the future. After closing the notepad.exe executable, windbg reverts back to using the Base workspace.
This time I'll actually launch notepad (not from the debugger) and attach to the running notepad.exe process with the debugger. We are now at Base+User-mode. I moved the debugger window (new position 3), selected Debug > Stop Debugging and get prompted with this dialog-
Choosing "Yes" will store WinDbg window position 3 in the User-mode workspace. Once I have completed this step, Windbg is again using the Base workspace because we stopped debugging.
To futher illustrate workspaces I'll attach a to a target Virtual Machine for Kernel Debugging but not break in. Windbg is using Base+Kernel now. I moved the window again and as soon as I break-in I get this dialog-
I chose 'No' on the dialog because I'm getting the hang of things. If I move the window again and type qd (quit and detach) to end the current kernel debug session, I will see this dialog-
So before we ended the session, we were at Base+Kernel+AMD64.
Running through this exercise helped me understand why I usually create a named workspace, change all my settings and use the command line option -W to open my workspace. Hopefully this will clear up some of the complexities involved with workspaces. This is why the debugger help file recommends making all the changes you need at the lowest possible level (i.e. Base first, then the others).
Hope this helps...