Your New Jekyll Site


The power of symbols

22 Apr 2011

There are two sorts of builds:

Debug builds

This build is what the developers use during development. Code optimization is generally turned off, memory is initialized to zero, the run-time checks for performs memory leaks, and uses guard bytes to track buffer overruns. The compiler produces .pdb files, also known as symbol files.

Release builds

This build has code optimizations turned on, and run-time checks are generally also turned off. The binary will be faster and smaller.


Symbol files contains information vital debug information about an .exe or Dll.

If you run the command dumpbin /EXPORTS on a DLL, on for example kernel32.dll It will lists all the functions that it exports.

1258  4E9 00011801 VirtualAlloc
1259  4EA 00029E73 VirtualAllocEx
1260  4EB 000947EF VirtualAllocExNuma
1261  4EC 0001183E VirtualFree
1262  4ED 00029E8B VirtualFreeEx
1263  4EE 0002D6F7 VirtualLock
1264  4EF 000134EC VirtualProtect
1265  4F0 000947FF VirtualProtectEx
1266  4F1 000132E5 VirtualQuery
1267  4F2 0009480F VirtualQueryEx
1268  4F3 0002D6C3 VirtualUnlock

The third column is the relative memory address from the base address, which is determined when it is loaded into memory, and the last column is the symbol name.

The principle is the same for symbol files. It contains mappings from addresses to function names, line numbers, data types, etc.

Without these symbol files, the only thing you would see in the debugger would be plain assembler code translated from machine code.

push ebp
mov  ebp, esp
sub  esp, 12
push eax
mov  DWORD PTR [ebp-4], 0AAAAh
mov  DWORD PTR [ebp-8], 0BBBBh
mov  DWORD PTR [ebp-12], 0CCCCh
pop  eax
mov  esp, ebp
pop  ebp
ret  8

So for doing debugging these files are very important.

Symbol files for Release builds

Although symbol files is for debugging, it is a misconception that it is only for debug builds. In fact, when you build your official release, you should store the symbols for the build.

They come in handy, if you ever want to analyze a memory crash dump from that build. Rebuilding afterwards will most probably not give you compatible symbol files.

Depending on the compiler you use and version, the symbol file generation can be already enabled by default. Oterwise you can enable it as is shown below.

Image of windbg

The correct symbol files, will help the debugger to map the faulting address to a line number in your code. The word “debug” in Debug build is misleading, since you also can debug Release builds. This is useful to know if you ever encounter an error that just appears on the release build. You might encounter small jumps here and there, where the code optimizer has changed the control flow, but that usually doesn’t cause big problems.

Below, we see the visual studio debugger during a debugging session. It displays the correct line, because the underlying instruction is located on a address which can be mapped to a line in the source code.

Image of windbg