现在支持将调试信息与要调试的二进制文件分开gdb
。binutils
描述这一点的文档可以在以下位置找到:
经过一番试验,我能够gdb
(7.6)使用 build-id 和 debug-link 方法找到调试信息。这里有两个gdb
片段显示调试器在非标准位置找到调试信息,分别使用 build-id 和 debug-link 方法:
(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.
要创建我使用过的调试信息文件objcopy
和strip
. 我在下面包含了此类命令的详细信息以供参考。
然而,我看这个的原因是希望能够使用-g
. 目前,如果我们尝试,这会破坏调试器,因为我们的共享库太大,重定位被截断以适应以下消息:
/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'
(以及随后的链接故障)
有谁知道一种方法来做:
- 生成一个独立文件,其中包含来自对二进制文件有贡献的源中的所有调试信息(即所有最终出现在
ld
生成二进制文件的命令中的 .o 和 .a 文件)。 - 或者,指示
ld
在二进制文件本身中不包含此调试信息的情况下进行链接,并生成一个可以用 build-id 或 debug-link 标识的独立调试文件?我在文档中没有看到任何关于单通道方法的内容ld
,但是ld
文档很大,也许我错过了。 - 处理上述截断错误的某种方法(这种方法将允许 build-id 或 debug-link 方法工作)。
为可执行文件生成单独的调试文件的示例命令
这是一个使用--build-id
和--add-gnu-debuglink
方法的示例命令行序列:
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
其中 copyDebugAndStrip 是以下 perl 代码:
#!/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 ;