【问题标题】:Howto debug a (slow) linker on a debian system如何在 debian 系统上调试(慢)链接
【发布时间】:2010-11-05 15:22:09
【问题描述】:

在我的公司,我们的链接器(ld 2.17)存在一个非常烦人的问题。它在相对较快的系统(Core Duo,2GB Ram)上链接非常非常慢,我现在真的不知道如何解决这个问题。编译一个比较大的项目大约需要五到十分钟(在我的Gentoo系统上链接大约需要5秒)。

我个人认为这是一个巨大的生产力杀手,至少对我来说是这样。我们尝试使用更新版本的 ld (2.19) 但没有任何成功。我在#freenode 上的#debian 中询问过,但这个问题似乎非常独特。我在网上没有找到任何关于类似问题的信息。只有当我们使用调试符号构建时才会发生这种情况。我将 gcc 调试信息标志更改为 -g、-g3 和 -ggdb,但这也无济于事。

所以我的问题是,您如何分析和调试链接器?我从来没有做过类似的事情,也找不到任何关于它的文档。基本上任何合理的 gprof gmon.out 都会非常有帮助,因为我可以向 binutils 开发人员询问具体问题。我只是完全忘记了这一点。

编辑:我们“修复”了在大多数系统上切换到 debian lenny 的问题。感谢您的回答!

【问题讨论】:

    标签: linux performance debugging linker profiling


    【解决方案1】:

    您可以尝试使用金币 (binutils-gold) 而不是 ld。 它应该更快。

    这是Wikipedia Gold(linker)的引述

    写黄金的动机是 制作一个比 GNU 链接器[3],特别是对于大型 用 C++ 编写的应用程序。

    gold 的作者 (Ian Lance Taylor) 发表了an (longish) article about linkers,他在其中解释了他编写 gold 的主题以及为什么大多数链接器都很慢。如果您对链接器的内部工作感兴趣,这篇文章值得一读。

    【讨论】:

    • 谢谢,我知道黄金,但我们还没有准备好继续使用它
    【解决方案2】:

    如果您观察到运行 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-检查 --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,馅饼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/包括 搜索列表结束。 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 测试。 o 测试.s 使用 BFD 版本 (GNU Binutils) 2.19.1 的 GNU 汇编器版本 2.19.1 (x86_64-pc-linux-gnu) COMPILER_PATH=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/libexec/gcc/x86_64 -pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/libexec/gcc /x86_64-pc-linux-gnu/4.3.3/:/usr/libexec/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/: /usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc -linux-gnu/bin/ LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/lib/gcc/x86_64 -pc-linux-gnu/4.3.3/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib /gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/lib/:/usr/lib/gcc/x86_64-pc-linux -gnu/4.3.3/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-save-temps' '-v' '-mtune=generic' /usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr /lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3 .3/../../../../lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc /x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3 .3/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux -gnu/4.3.3/../../../../x86_64-pc-linux-gnu/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/。 ./../.. test.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc /x86_64-pc-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crtn .o $ ls a.out test.c test.i test.o test.s $ /usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 / usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/ 4.3.3/../../../../lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/ gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/ 4.3.3/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc- linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/ ../../.. test.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/ gcc/x86_64-pc-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/ crtn.o $ .../collect2 -v ... collect2 版本 4.3.3 (x86-64 Linux/ELF) /usr/bin/ld -v --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-pc-linux-gnu /4.3.3/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../ ../lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../ ../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../.. /../../x86_64-pc-linux-gnu/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../.. test.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 /crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crtn.o GNU ld (GNU Binutils) 2.19.1 $

    如果您在构建ld 的调试版本时需要帮助,这里有一个帮助您快速入门的方法。

    $ sudo apt-get install build-essential dpkg-dev $ sudo apt-get build-dep binutils $ apt-get 源 binutils $ cd binutils-* $ DEB_BUILD_OPTIONS='debug noopt nostrip' dpkg-buildpackage -uc -us $ 光盘 .. $ sudo dpkg -i *.deb

    不过,我建议您使用schrootsbuild 来避免污染您自己的系统,而不是那种快速破解。

    【讨论】:

    • @ephemient 我正在尝试跳过 ld.so 的源代码,并希望查看在 GDB 中执行的源代码行。我已经安装了 binutils-source 和 libcdbg,但是当控件进入 ld.so 代码时,GDB 显示 SOURce 不可用。你能建议我错过什么吗?谢谢stackoverflow.com/questions/20114565/…
    【解决方案3】:

    回答分析问题;你应该看看OProfile - 这是一个系统级的分析器,可以分析多个正在运行的进程。它应该可以让您确定链接的哪个子流程花费的时间最多,并且还会显示哪些功能花费的时间最多。

    【讨论】:

      【解决方案4】:

      我想建议两种检查方法:

      1. 使用 strace 检查链接器正在加载/解析链接的文件;有了这个,您可能知道链接器是否搜索了任何不必要的路径。
      2. 使用带有 -verbose 选项的 ld 来了解 ld 正在做什么。五分钟对比五秒不应该是链接器的问题,应该是你的主机或某个选项的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-19
        • 1970-01-01
        • 2012-06-08
        • 2012-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多