One of the things that surprised me when I started using Visual Studio, coming from a Linux programming background, was the amount of files it generates when you create and compile a project. One of these files is usually named
project.pdb and contains the debug information for the final executable, along with information for incremental linking (Microsoft calls it the “program database“, hence the PDB extension). It turns out having separate debug information files can be useful when you want to distribute your program in binary form, but still be able to debug it when you get crash reports.
I was curious if the GNU toolchain could do the same, and the answer is yes. According to the gdb documentation there are two ways of using debug info from another file:
- Adding a debug link to the executable file: create the binary with embedded debug information as usual, then copy it to another file, strip it out and add the debug link:
objcopy --only-keep-debug program program.debug strip program objcopy --add-gnu-debuglink=program.debug program
The debug link contains the file name, and a CRC of the full contents of the debug file. When loading the executable into gdb, it will look in
.debug/program.debug(paths relative to the executable file) for a file containing debug information. This method works with every executable format that can contain a section called
.gnu_debuglink. I tested it on cygwin.
- Build ID:
ld, the GNU linker, can embed a special section with a build identifier, which can be either a MD5 or SHA1 hash of the output file contents, a random number, or any given bitstring (see the documentation of the –build-id option). This ID will then be copied and preserved when a debug file is created or the binary is stripped. When a Build ID is present, gdb will try to load a debug file in
<debug-dir>is each directory specified with
xxis the first byte of the hexadecimal Build ID bitstring, and-
yyyyyyyyis the rest of the bitstring.
This method is supported only on some platforms using ELF format for binaries and the GNU binutils.