如何在Debian系统上调试(缓慢的)链接器

7
在我们公司,我们的链接器(ld 2.17)存在一个非常烦人的问题。它在相对快的系统上(Core Duo,2GB RAM)链接非常缓慢,我不知道该如何解决这个问题。编译一个相对较大的项目需要大约五到十分钟的时间(在我的 Gentoo 系统上需要大约 5 秒钟来链接)。
就我个人而言,我认为这是一个巨大的生产力杀手。我们尝试使用更新的版本 ld(2.19),但没有任何成功的经验。我在 #debian 上询问,但这个问题似乎非常独特。我在网上没有找到任何类似的问题信息。只有当我们构建带有调试符号的时候才会出现这种情况。我将 gcc 的调试信息标志更改为 -g、-g3 和 -ggdb,但也没有帮助。
那么我的问题是,你如何分析和调试链接器?我从未做过这样的事情,也找不到任何相关文档。任何合理的 gprof gmon.out 都会非常有帮助,因为我可以向 binutils 开发人员询问具体的问题。我对此一无所知。
编辑:我们通过切换到 Debian Lenny 解决了我们的问题。感谢回答!
4个回答

6
你可以尝试使用黄金(binutils-gold)代替ld。它应该更快。
以下是来自维基百科Gold(链接器)的一句引用:
“编写gold的动机是为了制作比GNU链接器[3]更快的链接器,特别是对于使用C ++编写的大型应用程序。”
gold的作者(Ian Lance Taylor)发表了一篇(较长)关于链接器的文章,其中解释了他编写gold的动机以及为什么大多数链接器都很慢。如果您对链接器的内部工作方式感兴趣,这篇文章值得一读。

1
谢谢,我知道黄金,但我们还没有准备好转向它。 - user118861

5
如果你发现使用gcc编译速度变慢(而不是直接使用链接器ld),可以尝试使用以下命令进行编译:
$ gcc -save-temps -v [...其余命令行参数...]
这将输出所有中间命令,例如内部的collect2和最终的ld,并确保传递给这些命令的对象即使在命令完成后也会保留在磁盘上。
然后,您应该能够单独运行这些命令,找到最慢的阶段,然后使用不同的选项或者进行性能分析。
例如:
$ echo 'int main() {}' > test.c
$ gcc -save-temps -v test.c
使用内置规范。
目标:x86_64-pc-linux-gnu
配置为:/var/tmp/paludis/sys-devel-gcc-4.3.3-r2/work/gcc-4.3.3/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.3.3 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.3.3 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.3.3/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.3.3/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/include/g++-v4 --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --disable-fixed-point --enable-nls --without-included-gettext --with-system-zlib --disable-checking --disable-werror --enable-secureplt --enable-multilib --enable-libmudflap --disable-libssp --enable-libgomp --enable-cld --disable-libgcj --enable-objc-gc --enable-languages=c,c++,objc,obj-c++,treelang,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.3.3-r2 p1.1, pie-10.1.5'
线程模型:posix
gcc 版本 4.3.3 (Gentoo 4.3.3-r2 p1.1, pie-10.1.5)
COLLECT_GCC_OPTIONS='-save-temps' '-v' '-mtune=generic'
 /usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/cc1 -E -quiet -v test.c -D_FORTIFY_SOURCE=2 -mtune=generic -fpch-preprocess -o test.i
忽略不存在的目录 "/usr/local/include"
忽略不存在的目录 "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/include"
#include "..." 搜索从这里开始:
#include  搜索从这里开始:
 /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/include
 /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/include-fixed
 /usr/include
搜索结束。
COLLECT_GCC_OPTIONS='-save-temps' '-v' '-mtune=generic'
 /usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/cc1 -fpreprocessed test.i -quiet -dumpbase test.c -mtune=generic -auxbase test -version -o test.s
GNU C (Gentoo 4.3.3-r2 p1.1, pie-10.1.5) 版本 4.3.3 (x86_64-pc-linux-gnu)
        由 GNU C 编译器版本 4.3.3、GMP 版本 4.2.4、MPFR 版本 2.4.1-p5 编译。
警告:GMP 头文件版本 4.2.4 与库版本 4.3.1 不同。
GGC 启发式算法:--param ggc-min-expand=100 --param ggc-min-heapsize=131072
编译器可执行文件校验和:20f3dbffbfd03e5311a257ae1239cd71
COLLECT_GCC_OPTIONS='-save-temps' '-v' '-mtune=generic'
 /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/bin/as -V -Qy -o test.o test.s
GNU 汇编器版本 2.19.1 (x86_64-pc-linux-gnu),使用 BFD 版本 (GNU Binutils) 2.19.1
COMPILER_PATH=/usr/libexec/gcc/x86_64-pc-linux-gnu/
如果您需要构建ld的调试版本,这里有一个快速的配方可以帮助您开始。
$ sudo apt-get install build-essential dpkg-dev
$ sudo apt-get build-dep binutils
$ apt-get source binutils
$ cd binutils-*
$ DEB_BUILD_OPTIONS='debug noopt nostrip' dpkg-buildpackage -uc -us
$ cd ..
$ sudo dpkg -i *.deb
不过,与其使用这种快速方法,我建议使用schrootsbuild来避免污染您自己的系统。

@ephemient 我正在尝试跨越ld.so的源代码,并希望在GDB中查看正在执行的源代码行。我已经安装了binutils-source和libcdbg,但是当控制进入ld.so代码时,GDB显示“源代码不可用”。您能否建议我缺少什么?谢谢 https://dev59.com/jHnZa4cB1Zd3GeqPpWSz - abhi

3
回答分析问题的方法是:查看OProfile - 这是一个系统级的分析器,可以对多个运行中的进程进行分析。它可以帮助你确定哪个子进程花费了最多的时间,并显示最耗时的函数。

1

我想提出两种检查方法:

  1. 使用strace检查链接器正在加载/解析以进行链接的文件;通过这种方式,您可以知道链接器是否搜索了任何不必要的路径。
  2. 使用带有-verbose选项的ld来了解ld正在执行的操作。与五秒钟相比,五分钟不应该是链接器的问题,而应该是您的主机或某些选项存在问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接