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 --only-keep-debug a.out a.out.pdb $ strip a.out
As we can now see, our debug symbols are extracted and removed from
$ 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
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
$ 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.
a.out can now be distributed & debugged with external symbols.
$ 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