2009-06-24 65 views
7

在我的公司,我們的鏈接器(ld 2.17)有一個非常令人討厭的問題。它在一個相對較快的系統(Core Duo,2GB Ram)上鍊接非常慢,我現在不知道如何解決這個問題。編譯一個相對較大的項目需要大約五到十分鐘的時間(在Gentoo系統上連接大約需要5秒鐘的時間)。如何在Debian系統上調試(慢速)鏈接器

我個人認爲這是一個巨大的生產力殺手,至少對我而言。我們嘗試使用更新版本的ld(2.19),但沒有取得任何成功。我在#freenode上#debian問過,但這個問題似乎很獨特。我沒有找到關於網絡上類似問題的任何信息。它只發生在我們用調試符號構建時。我將gcc調試信息標誌更改爲-g,-g3和-ggdb,但這也沒有幫助。

所以我的問題是,你如何配置和調試鏈接器?我從來沒有做過這樣的事情,我也找不到任何有關它的文檔。基本上任何合理的gprof gmon.out都會非常有幫助,因爲我可以向binutils開發者詢問具體問題。我完全沒有注意到這一點。

編輯:我們「修復」了我們在大多數系統上切換到debian lenny的問題。感謝您的答案!

回答

5

如果你觀察運行gcc(而不是直接運行該鏈接爲ld)放緩,嘗試用

​​

編譯這將打印出所有的中介命令,如內部collect2和最後ld,並確保傳遞給這些命令的對象在命令完成後仍將保留在磁盤上。

然後,您應該能夠單獨運行命令以查找最糟糕的階段,然後使用不同的選項或分析運行它。

例如,

 
$ echo 'int main() {}' > test.c 
$ gcc -save-temps -v test.c 
Using built-in specs. 
Target: x86_64-pc-linux-gnu 
Configured with: /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' 
Thread model: posix 
gcc version 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 
ignoring nonexistent directory "/usr/local/include" 
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/include" 
#include "..." search starts here: 
#include search starts here: 
/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 
End of search list. 
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) version 4.3.3 (x86_64-pc-linux-gnu) 
     compiled by GNU C version 4.3.3, GMP version 4.2.4, MPFR version 2.4.1-p5. 
warning: GMP header version 4.2.4 differs from library version 4.3.1. 
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 
Compiler executable checksum: 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 assembler version 2.19.1 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.19.1 
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 version 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 source binutils 
$ cd binutils-* 
$ DEB_BUILD_OPTIONS='debug noopt nostrip' dpkg-buildpackage -uc -us 
$ cd .. 
$ sudo dpkg -i *.deb 

而不是快速的黑客,不過,我推薦使用schrootsbuild,以避免污染自己的系統。

+0

+1「就不那麼明顯了Debian支持」與海合會標誌:) – tr9sh 2009-06-24 21:07:33

+0

@ephemient我想邁過源ld.so,並希望看到的源代碼行GDB執行。我已經安裝了binutils-source和libcdbg,但是當控制進入ld.so代碼時,GDB顯示SOurce不可用。你能建議我缺少的東西嗎?謝謝http://stackoverflow.com/questions/20114565/gdb-step-into-dynamic-linkerld-so-code – abhi 2013-11-21 07:28:03

6

您可以嘗試黃金(binutils-gold)而不是ld。 它應該會更快。

下面是從Wikipedia Gold(linker)

報價用於寫入黃金的動機是 作出的接頭比 GNU接頭[3]快,特別是對於大 應用在C++編碼。

黃金的作者(伊恩·蘭斯·泰勒),他解釋了寫他的黃金主題和爲什麼大多數的接頭是緩慢的出版an (longish) article about linkers。如果你對連接器的內部工作感興趣,這篇文章值得一讀。

3

回答分析問題;你應該看看OProfile - 這是一個系統級分析器,可以分析多個正在運行的進程。它應該允許您確定鏈接的哪個子進程花費的時間最多,並且還會顯示最耗時的功能。

1

我想建議兩種方法來檢查:

  1. 使用strace的檢查哪些文件鏈接器加載/解析鏈接;有了這個你可能知道有沒有不必要的路徑被鏈接器搜索到。
  2. 使用ld和-verbose選項來知道ld在做什麼。五分鐘比五秒鐘不應該是鏈接器的問題,它應該是你的主機或某些選項的一些問題。