There's now gdb
and binutils
support for separating debug info from the binaries to be debugged. Docs describing this can be found in:
After a bit of experimenting, I'm able to get gdb
(7.6) to find the debug info using either the build-id and debug-link methods. Here's two gdb
fragments that show the debugger finding the debug info in the non-standard locations, using the build-id and debug-link methods respectively:
(gdb) set debug-file-directory .
(gdb) file uWithBuildId
Reading symbols from /home/peeterj/build-id/uWithBuildId...Reading symbols from /home/peeterj/build-id/.build-id/2d/41caac1bcbeb65255abc3f35624cf9ed37791a.debug...done.
Reading symbols from /home/peeterj/build-id/uWithDebugLink...Reading symbols from /home/peeterj/build-id/uWithDebugLink.debug...done.
To create the debug info files I've used objcopy
and strip
. I've included details of such commands below for reference.
However, the reason I'm looking at this at all is with the hope of being able to build all of our product code with -g
. Currently this breaks the debugger if we try since our shared-lib is too big with relocation truncated to fit messages like:
/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crtn.o:(.debug_aranges+0x6): relocation truncated to fit: R_X86_64_32 against `.debug_info'
(and subsequent link failure)
Does anybody know of a way to do one of:
ld
command that generates the binary).ld
to link without including this debug info in the binary itself, and generate a standalone debug file that can be identified with a build-id or debug-link? I don't see anything in the docs for a single pass method to do this with ld
, but the ld
docs are big and perhaps I missed it.Here's a sample command line sequence using both the --build-id
and --add-gnu-debuglink
methods:
g++ -g -c -o u.o u.cpp
g++ -o uWithBuildId -Wl,--build-id u.o
g++ -o uWithDebugLink u.o
copyDebugAndStrip uWithBuildId
objcopy --only-keep-debug uWithDebugLink uWithDebugLink.debug
objcopy --add-gnu-debuglink=uWithDebugLink.debug uWithDebugLink
strip -g uWithDebugLink
where copyDebugAndStrip is the following perl code:
#!/usr/bin/perl
my $binary = $ARGV[0] ;
my @p = `objdump --section .note.gnu.build-id -s $binary | tail -2` ;
foreach (@p)
{
chomp ;
s/^ *[\da-f]+ *// ;
s/ .*// ;
s/ //g ;
}
my $buildid = "$p[0]$p[1]" ;
$buildid =~ /^(..)(.*)/ ;
my ($d, $r) = ($1, $2) ;
print "build-id for '$binary': $buildid\n" ;
my $cmd =
"mkdir -p .build-id/$d
rm -f .build-id/$d/$r.debug
objcopy --only-keep-debug $binary .build-id/$d/$r.debug
strip -g $binary
" ;
print $cmd ;
system $cmd ;
Initially it appeared that the binutils
gold linker was capable of building large -g shared libs, providing a solution for (3) above, however, it turns out that is because of a lack of error checking.
On the other hand it looks like work on (1) and (2) is in available if a bleeding edge toolchain is used, part of the fission dwarf/binutils/gcc work described here:
This fission work was mentioned in discussion of a bugzilla report on this relocation truncation error:
http://sourceware.org/bugzilla/show_bug.cgi?id=15444
An example of the use of this split debug files is:
g++ -gsplit-dwarf -gdwarf-4 -c -o main.o main.cpp
gcc -gsplit-dwarf -gdwarf-4 -c -o d1/t1.o d1/t1.c
g++ -gsplit-dwarf -gdwarf-4 -c -o d2/t2.o d2/t2.cpp
gcc -Wl,--index-gdb main.o d1/t1.o d2/t2.o -o main
where gcc
/g++
are version 4.8, the binutils
trunk (cvs -z 9 -d :pserver:[email protected]:/cvs/src co binutils
) has been used configured with --enable-gold=default
, and finally using gdb version 7.6 which can read the split debug info.
Joining gcc in the party, the intel (version 16) compiler supports -gsplit-dwarf. The intel compiler documents that binutils-2.24+,gdb-7.6.1+ are required. The clang compiler codebase has some split dwarf support, but I don't know what state that support is in.