Using Symbols to Maximize your Debugging Experience



Why are symbols and debug information files so important to debugging?


Stack walking and output will be much more complete and accurate. Most programmers do not realize that without having the FPO information that is stored within the symbols debug files it is impossible to walk a stack correctly.

Most, if not all, optimized compiled code uses FPO (frame pointer

optimization) records. In a nutshell what the optimizer does is not use the standard PUSH EBP stack frame and optimizes the code such that a stack frame is not present. Stack frames can no longer be determined by walking a stack chain looking for the previous EBP. This means that all stack walking code for any debugger will contain large gaping holes and appear to be inaccurate and incomplete. To correct this you will need to have symbols loaded for all modules that are in the stack. For almost all development this only requires having a half dozen symbol files loaded. Within the symbol files are the information describing the FPO records that describe what/where the stack frame is for a particular function. This then allows the stack walking code to properly walk the stack.

Symbols provide a name for a memory location. Its much easier to debug a problem when you can see a text name of a piece of memory, IE 'call _RtlAreBitsSet' instead of 'call 0x80537d68'. Anytime SoftICE can display the name of an address it will do so. This applies to output in the code window, register window, and command window where appropriate.

The WHAT command becomes infinitely more useful. Quite often when debugging and reverse engineering you have addresses that are being used, but you are not sure either what that address is or the context in how it is being used. Using the WHAT command on that address will show the most likely use for what a piece of memory is. For example, lets say you wanted to track who was opening a file. One way to accomplish this would be to set a 'bpx _ZwOpenFile'. From here you would issue 'what esi'. The output of the what command will tell you which thread of which application is attempting to open the file. Choosing the WHAT option with the right mouse button is a quick and easy way to start exploring all pieces of memory.

Which symbols are most important?


The most important symbols to have loaded at all times are: ntoskrnl, hal, win32k, ntdll, user32, kernel32, csrss, and your application/driver.

If you are doing shell programming, load up symbols for shell32 and


For each type of debugging you are doing load up the appropriate set of symbols, ie USB, video, games programming, networking. An easy way to set this up is to use the Workspace feature of Symbol Loader.

Be sure to use our configuration application, or Symbol Loader to add these symbols into your winice.dat file so symbols will always be loaded.

Where can I find symbols?


There are several places where you can get symbols for your OS.

- The easiest way to get symbols is to the supplied 'Symbol Retriever'

utility. This utility retrieves symbols from a Symbol Server site for a given binary. It then optionally translated them and loads them into SoftICE. After running Windows Update or a Service Pack update it is required to rerun Symbol Retriever to get the latest symbols for your OS files.

- Symbols are supplied with your MSDN subscription.

- Symbols can be downloaded from Microsoft. This depends on which OS you are using. The newer OS' are only available through purchasing a

CD or from the MSDN site.


Old KB# 11847
Comment List
Related Discussions