8

现在支持将调试信息与要调试的二进制文件分开gdbbinutils描述这一点的文档可以在以下位置找到:

经过一番试验,我能够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.

要创建我使用过的调试信息文件objcopystrip. 我在下面包含了此类命令的详细信息以供参考。

然而,我看这个的原因是希望能够使用-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'

(以及随后的链接故障)

有谁知道一种方法来做:

  1. 生成一个独立文件,其中包含来自对二进制文件有贡献的源中的所有调试信息(即所有最终出现在ld生成二进制文件的命令中的 .o 和 .a 文件)。
  2. 或者,指示ld在二进制文件本身中不包含此调试信息的情况下进行链接,并生成一个可以用 build-id 或 debug-link 标识的独立调试文件?我在文档中没有看到任何关于单通道方法的内容ld,但是ld文档很大,也许我错过了。
  3. 处理上述截断错误的某种方法(这种方法将允许 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 ;
4

2 回答 2

7

最初,gold 链接器似乎binutils能够构建大型 -g 共享库,为上述 (3) 提供了解决方案,但事实证明这是因为缺乏错误检查。

另一方面,如果使用最前沿的工具链,看起来 (1) 和 (2) 的工作是可用的,这里描述的裂变 dwarf/binutils/gcc 工作的一部分:

在讨论有关此重定位截断错误的 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 版本,binutilstrunk ( 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 支持,但我不知道该支持处于什么状态。

于 2013-05-08T20:40:57.113 回答
1

使用 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

于 2017-12-05T21:26:22.233 回答