There are two sorts of 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.
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.
- publics and exports
- global symbols
- local symbols
- type data
- source files
- line numbers
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.
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.