PDBs on Linux
On Windows, debugger symbols aren’t stored side-by-side with the executable data in the same file. They’re stored in a .pdb
file (short for “program database”). This is especially great if you distribute your program to end-users, but still want to be able to debug any crashes. Just keep the .pdb
file somewhere save, and any crash log you get send can easily translated back into source locations.
On Linux, debug symbols are traditionally stored inside the executable, and stripped (using strip(1)
) before distributing. This takes away the possibility to debug any crash, send to you from the stripped executable.
Today I discovered a neat little trick to create something resembling PDBs on Linux, by making use of objcopy(1)
. In our example, I already have compiled an executable a.out
, which I want to distribute to my users:
$ ls -lah a.out
-rwxr-xr-x 1 woot woot 30K May 5 11:26 a.out
As we can see, the executable, with debug symbols, has a size of 30k.
Now we extract the debug symbols into another file, using objcopy(1)
:
$ objcopy --only-keep-debug a.out a.out.pdb
$ strip a.out
As we can now see, our debug symbols are extracted and removed from a.out
:
$ ls -lah .
-rwxr-xr-x 1 woot woot 6.3K May 5 11:26 a.out
-rwxr-xr-x 1 woot woot 28K May 5 11:25 a.out.pdb
If we now want to debug a.out
, however, gdb(1)
is telling us it’s missing debug information:
$ gdb a.out
Reading symbols from a.out...(no debugging symbols found)...done.
We need to attach the .pdb
symbols to a.out
. This can be achieved by making use of GNUs .gnu_debuglink
directives:
$ objcopy --add-gnu-debuglink=a.out.pdb a.out
To confirm it’s working, we start gdb(1)
, to see whether it can now pick up any symbols:
$ gdb a.out
Reading symbols from a.out...Reading symbols from /home/woot/tmp/pdbtest/a.out.pdb...done.
Lovely! Our a.out
can now be distributed & debugged with external symbols.
Summary
$ objcopy --only-keep-debug a.out a.out.pdb # extract symbols
$ strip a.out # strip away any debug information
$ objcopy --add-gnu-debuglink=a.out.pdb a.out # attach the symbols to the executable