gnu ld/gdb:单独的调试文件。当需要链接的调试信息过多时如何生成调试文件?
Posted
技术标签:
【中文标题】gnu ld/gdb:单独的调试文件。当需要链接的调试信息过多时如何生成调试文件?【英文标题】:gnu ld/gdb: separate debug files. How to produce the debug file when there's too much debug info to link? 【发布时间】:2013-05-06 23:30:11 【问题描述】:现在gdb
和binutils
支持将调试信息与要调试的二进制文件分开。可以在以下位置找到描述此内容的文档:
经过一番试验,我可以使用 build-id 和 debug-link 方法获得 gdb
(7.6) 来查找调试信息。下面是两个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
在二进制文件本身中不包含此调试信息的情况下进行链接,并生成一个独立的调试文件,该文件可以通过构建ID 或调试链接进行识别?我在文档中没有看到任何关于使用 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 ;
【问题讨论】:
【参考方案1】:最初,binutils
gold 链接器似乎能够构建大型 -g 共享库,为上述 (3) 提供解决方案,但事实证明这是因为缺乏错误检查。
另一方面,如果使用最前沿的工具链,看起来 (1) 和 (2) 的工作是可用的,这里描述的裂变 dwarf/binutils/gcc 工作的一部分:
http://gcc.gnu.org/ml/gcc/2011-10/msg00326.html http://gcc.gnu.org/wiki/DebugFission在讨论有关此重定位截断错误的 bugzilla 报告时提到了此裂变工作:
http://sourceware.org/bugzilla/show_bug.cgi?id=15444
使用这种拆分调试文件的一个例子是:
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
其中gcc
/g++
是 4.8 版本,binutils
主干 (cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src co binutils
) 已使用 --enable-gold=default
配置,最后使用 gdb 版本 7.6,可以读取拆分调试信息。
加入gcc党,intel(16版)编译器支持-gsplit-dwarf。需要 binutils-2.24+,gdb-7.6.1+ 的 intel 编译器文档。 clang 编译器代码库有一些 split dwarf 支持,但我不知道该支持处于什么状态。
【讨论】:
【参考方案2】:在使用 g++ (v6.3.0) + gold linker (v2.27) + “-g” 参数编译时,我遇到了类似的链接器问题。
staticlib.a(sharedlib.o):(.debug_loc+0x1d38):重定位被截断以适应:R_X86_64_32 反对 `.debug_info' staticlib.a(sharedlib.o):(.debug_loc+0x6c8c):输出中省略了额外的重定位溢出 collect2:错误:ld 返回 1 个退出状态 gmake: *** [exec_file] 错误 1 287.760u 35.837s 7:30.37 71.8% 0+0k 17217048+14932696io 0pf+0w
添加参数“-fdebug-types-section”修复了这个问题。
更多详情请访问:https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html
【讨论】:
以上是关于gnu ld/gdb:单独的调试文件。当需要链接的调试信息过多时如何生成调试文件?的主要内容,如果未能解决你的问题,请参考以下文章